From ca926f00e0e4b26b81ec666d5b03a58b6ece1e6a Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Fri, 6 Sep 2013 22:21:35 +0000 Subject: [PATCH] [stm32l1] Add semihosting example This is not specifically an L1 example, but it lives beside the L1 "usart" example to show how easy it is to add semihosting support to existing code. Tested with the by now relatively old g-a-e 2012q4 release and OpenOcd 0.8.0-dev-00011-g70a2ffa (2013-05-14-19:41) --- .../usart-semihosting/Makefile | 32 +++++++ .../stm32l-discovery/usart-semihosting/README | 61 ++++++++++++ .../usart-semihosting/usart-semihosting.c | 92 +++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 examples/stm32/l1/stm32l-discovery/usart-semihosting/Makefile create mode 100644 examples/stm32/l1/stm32l-discovery/usart-semihosting/README create mode 100644 examples/stm32/l1/stm32l-discovery/usart-semihosting/usart-semihosting.c diff --git a/examples/stm32/l1/stm32l-discovery/usart-semihosting/Makefile b/examples/stm32/l1/stm32l-discovery/usart-semihosting/Makefile new file mode 100644 index 0000000..51e1a41 --- /dev/null +++ b/examples/stm32/l1/stm32l-discovery/usart-semihosting/Makefile @@ -0,0 +1,32 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +BINARY = usart-semihosting + +LDSCRIPT = ../../../../../libopencm3/lib/stm32/l1/stm32l15xxb.ld + +# To disable, run "make ENABLE_SEMIHOSTING=0" or comment next line out +ENABLE_SEMIHOSTING ?= 1 + +ifeq ($(ENABLE_SEMIHOSTING),1) +LDFLAGS += --specs=rdimon.specs -lrdimon +CFLAGS += -DENABLE_SEMIHOSTING=1 +endif + +include ../../Makefile.include diff --git a/examples/stm32/l1/stm32l-discovery/usart-semihosting/README b/examples/stm32/l1/stm32l-discovery/usart-semihosting/README new file mode 100644 index 0000000..93ad917 --- /dev/null +++ b/examples/stm32/l1/stm32l-discovery/usart-semihosting/README @@ -0,0 +1,61 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This example program sends some characters on USART2 on the +ST STM32L DISCOVERY eval board. (USART2 TX on PA2 @ 115200 8n1) + +It can _ALSO_ use semihosting to use regular stdio via the attached debugger. +This expects you to be using gcc-arm-embedded from +https://launchpad.net/gcc-arm-embedded + +Semihosting is a neat feature, but remember that your application will +NOT WORK standalone if you have semihosting turned on! + +$ make ENABLE_SEMIHOSTING=0 will rebuild this image _without_ semihosting + +Semihosting is supported in "recent"[1] OpenOCD versions, however, you need +to enable semihosting first! If you have not enabled semihosting, you +will receive a message like this: + +(gdb) run +The program being debugged has been started already. +Start it from the beginning? (y or n) y + +Starting program: +/home/karlp/src/libopencm3-examples/examples/stm32/l1/stm32l-discovery/usart-semihosting/usart-semihosting.elf + +Program received signal SIGTRAP, Trace/breakpoint trap. +0x08000456 in initialise_monitor_handles () +(gdb) + +# Here we enable semi-hosting + +(gdb) mon arm semihosting enable +semihosting is enabled +(gdb) continue +... + +You should now see the semihosting output in the window running OpenOCD. + +Size Notes +~~~~~~~~~~ +Semihosting is basically free + +# Without +$ arm-none-eabi-size usart-semihosting.elf + text data bss dec hex filename + 29056 2212 60 31328 7a60 usart-semihosting.elf + +# With +$ arm-none-eabi-size usart-semihosting.elf + text data bss dec hex filename + 29832 2212 232 32276 7e14 usart-semihosting.elf + +The large size here is because of printf being included regardless, see +nano.specs if you care about this, this data here is to show that semihosting +doesn't cost much at all. + + +[1] At least since OpenOcd version 0.8.0-dev-00011-g70a2ffa (2013-05-14-19:41) +possibly earlier. diff --git a/examples/stm32/l1/stm32l-discovery/usart-semihosting/usart-semihosting.c b/examples/stm32/l1/stm32l-discovery/usart-semihosting/usart-semihosting.c new file mode 100644 index 0000000..602d5b9 --- /dev/null +++ b/examples/stm32/l1/stm32l-discovery/usart-semihosting/usart-semihosting.c @@ -0,0 +1,92 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * Copyright (C) 2012 Karl Palsson + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include +#include + +/* For semihosting on newlib */ +extern void initialise_monitor_handles(void); + +static void clock_setup(void) +{ + /* We are running on MSI after boot. */ + /* Enable GPIOD clock for LED & USARTs. */ + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN); + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOBEN); + + /* Enable clocks for USART2. */ + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN); +} + +static void usart_setup(void) +{ + /* Setup USART2 parameters. */ + usart_set_baudrate(USART2, 115200); + usart_set_databits(USART2, 8); + usart_set_stopbits(USART2, USART_STOPBITS_1); + usart_set_mode(USART2, USART_MODE_TX); + usart_set_parity(USART2, USART_PARITY_NONE); + usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE); + + /* Finally enable the USART. */ + usart_enable(USART2); +} + +static void gpio_setup(void) +{ + /* Setup GPIO pin GPIO7 on GPIO port B for Green LED. */ + gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7); + + /* Setup GPIO pins for USART2 transmit. */ + gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2); + + /* Setup USART2 TX pin as alternate function. */ + gpio_set_af(GPIOA, GPIO_AF7, GPIO2); +} + +int main(void) +{ + int i, j = 0, c = 0; + + clock_setup(); + gpio_setup(); + usart_setup(); +#if defined(ENABLE_SEMIHOSTING) && (ENABLE_SEMIHOSTING) + initialise_monitor_handles(); +#endif + + /* Blink the LED (PD12) on the board with every transmitted byte. */ + while (1) { + gpio_toggle(GPIOB, GPIO7); /* LED on/off */ + usart_send_blocking(USART2, c + '0'); /* USART2: Send byte. */ + printf("Magic semihosting: %c\n", c + '0'); + c = (c == 9) ? 0 : c + 1; /* Increment c. */ + if ((j++ % 80) == 0) { /* Newline after line full. */ + usart_send_blocking(USART2, '\r'); + usart_send_blocking(USART2, '\n'); + } + for (i = 0; i < 100000; i++) /* Wait a bit. */ + __asm__("NOP"); + } + + return 0; +}