diff --git a/Makefile b/Makefile index 378f47a..35468be 100644 --- a/Makefile +++ b/Makefile @@ -72,21 +72,30 @@ OBJCOPY := $(TOOLCHAIN)-objcopy OBJDUMP := $(TOOLCHAIN)-objdump SIZE := $(TOOLCHAIN)-size -# The SAM D20 series is based on an ARM Cortex M0 core +# The SAM D20 series is based on an ARM Cortex M0+ core # # ARCH_FLAGS := -mcpu=cortex-m0plus -mthumb +# Flags to be used when semihosting +# +# +ifdef SEMIHOSTING +LDFLAGS += --specs=rdimon.specs -lc -lrdimon +else +LDFLAGS += --specs=nano.specs -lc +endif + # Compilation Flags # # Display all warnings. Compile functions and data into their own sections so # they can be discarded if unused. The linker performs garbage collection of # unused input sections. # -CFLAGS = $(COMPILATION_FLAGS) -Wall -Wextra $(ACCEPT_WARN) -std=gnu99 \ +CFLAGS += $(COMPILATION_FLAGS) -Wall -Wextra $(ACCEPT_WARN) -std=gnu99 \ -ffunction-sections -fdata-sections $(ARCH_FLAGS) -ASFLAGS = -Wall $(ARCH_FLAGS) -a=/dev/null -LDFLAGS = $(COMPILATION_FLAGS) $(LINKER_FLAGS) -Wextra $(ARCH_FLAGS) +ASFLAGS += -Wall $(ARCH_FLAGS) -a=/dev/null +LDFLAGS += $(COMPILATION_FLAGS) -lm $(LINKER_FLAGS) -lm -Wextra $(ARCH_FLAGS) # Compilation Defines # @@ -95,6 +104,9 @@ LDFLAGS = $(COMPILATION_FLAGS) $(LINKER_FLAGS) -Wextra $(ARCH_FLAGS) ifdef TARGET_CHIP CFLAGS += -D$(TARGET_CHIP) -D__$(TARGET_CHIP)__ endif +ifdef SEMIHOSTING +CFLAGS += -D__SEMIHOSTING__ +endif # Startup and system code # @@ -226,7 +238,7 @@ etags: $(TAGFILES) # .PHONY: emacs emacs: - @emacs $(TAGFILES) Makefile config.mk + @emacs $(TAGFILES) Makefile config.mk README.md # Removes everything in the output directory # diff --git a/README-nrf51-gcc-blackmagic.md b/README-samd20-gcc-blackmagic.md similarity index 88% rename from README-nrf51-gcc-blackmagic.md rename to README-samd20-gcc-blackmagic.md index 16ca350..04ef995 100644 --- a/README-nrf51-gcc-blackmagic.md +++ b/README-samd20-gcc-blackmagic.md @@ -76,6 +76,22 @@ outside of RAM and ROM. These commands can be automated by placing them in a `gdbscript-custom` file. +### Semihosting ### + +You can build for semihosting by defining the `SEMIHOSTING` variable +in make. Like this: + +``` +make -kB SEMIHOSTING=1 +``` + +This build will be significantly larger (in terms of RAM and ROM). + +For this build, when a debugger is present at startup the +`semihost_printf`, `semihost_puts` and `semihost_putchar` functions +will print to stdio on the host. The Blackmagic Debug Probe supports +this. + ## Emacs ## The command `make emacs` can be used to quickly launch an instance of diff --git a/README.md b/README.md index da6714a..a8844b4 120000 --- a/README.md +++ b/README.md @@ -1 +1 @@ -README-nrf51-gcc-blackmagic.md \ No newline at end of file +README-samd20-gcc-blackmagic.md \ No newline at end of file diff --git a/chip/sections.ld b/chip/sections.ld index 86943b9..fe368db 100644 --- a/chip/sections.ld +++ b/chip/sections.ld @@ -45,6 +45,8 @@ * __data_end * __bss_start * __bss_end + * __end__ + * end * __heap_start * __heap_end * __stack_end @@ -139,6 +141,7 @@ SECTIONS .heap (COPY): { __end__ = .; + end = __end__; __heap_start = __end__; *(.heap*) __HeapLimit = .; diff --git a/chip/startup_samd20.c b/chip/startup_samd20.c index e9de444..7ad5242 100644 --- a/chip/startup_samd20.c +++ b/chip/startup_samd20.c @@ -42,6 +42,7 @@ */ #include "samd20.h" +#include "semihosting.h" /* Initialize segments */ extern uint32_t __fixed_start; @@ -59,6 +60,7 @@ int main(void); /** \endcond */ void __libc_init_array(void); +extern void initialise_monitor_handles(void); /* Default empty handler */ void Dummy_Handler(void); @@ -174,6 +176,18 @@ void Reset_Handler(void) /* Initialize the C library */ __libc_init_array(); +#ifdef __SEMIHOSTING__ + /* If there's a debugger attached */ + if (DSU->STATUSB.reg & DSU_STATUSB_DBGPRES) { + + /* Initialise handles for semihosting */ + initialise_monitor_handles(); + + /* Set semihosting functions */ + set_semihosting(); + } +#endif /* __SEMIHOSTING__ */ + /* Branch to main function */ main(); diff --git a/inc/semihosting.h b/inc/semihosting.h new file mode 100644 index 0000000..a657841 --- /dev/null +++ b/inc/semihosting.h @@ -0,0 +1,56 @@ +/* + * Wrapper functions for semihosting + * Copyright (C) 2014 Richard Meadows + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SEMIHOSTING_H +#define SEMIHOSTING_H + +/** + * Please use the semihost_*() wrappers so that semihosting functions + * can be disables from the makefile! + */ + +#ifndef __SEMIHOSTING__ + +/* Dummy function handlers */ +#define semihost_putchar(c) +#define semihost_puts(s) +#define semihost_printf(...) + +#else + +/* We would get a SVC exception if we called stdio without a debug probe */ +void set_semihosting(void); + +/* Real function handlers */ +#define semihost_putchar(c) __putchar(c) +#define semihost_puts(s) __puts(s) +#define semihost_printf(...) __printf(__VA_ARGS__) + +void __putchar(char c); +void __puts(const char* s); +void __printf(const char *format, ...); + +#endif /* __SEMIHOSTING__ */ + +#endif /* SEMIHOSTING_H */ diff --git a/src/main.c b/src/main.c index a4777b4..6966f58 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,9 @@ #include "samd20.h" #include "pindefs.h" +#include +#include "semihosting.h" + int main(void) { SystemInit(); @@ -38,6 +41,8 @@ int main(void) /* Configure the SysTick for 50ms interrupts */ SysTick_Config(SystemCoreClock / 20); + semihost_printf("Hello World\n"); + while (1); } diff --git a/src/semihosting.c b/src/semihosting.c new file mode 100644 index 0000000..1871fcb --- /dev/null +++ b/src/semihosting.c @@ -0,0 +1,53 @@ +/* + * Wrapper functions for semihosting + * Copyright (C) 2014 Richard Meadows + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "samd20.h" + +uint8_t semihosting_en = 0; + +void set_semihosting(void) { + semihosting_en = 1; +} + +void __putchar(char c) { + if (semihosting_en) { + putchar(c); + } +} +void __puts(const char* s) { + if (semihosting_en) { + puts(s); + } +} +void __printf(const char *format, ...) { + if (semihosting_en) { + va_list args; + + va_start(args, format); + vprintf(format, args); + } +}