From 0d260f61a019c6d2b133727315bca758c6bdfe74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sun, 17 May 2015 21:07:10 +0200 Subject: [PATCH 1/4] cc2538: Fix .data LMA/VMA mismatch with some toolchains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some toolchains, like Sourcery CodeBench Lite 2013.05-23 arm-none-eabi (http://sourcery.mentor.com/public/gnu_toolchain/arm-none-eabi/) automatically force the alignment of an output section LMA to use the maximum alignment of all its input sections. This toolchain uses GNU binutils 2.23, and this automatic behavior is the same as the manual behavior of the ALIGN_WITH_INPUT feature of GNU binutils 2.24+. This behavior is not an issue per se, but it creates a gap between _etext and the LMA of the .data output section if _etext does not have the same alignment, while reset_handler() initialized this section by copying the data from _etext to its VMA, hence an offset in the addresses of loaded data, and missing data. This commit fixes this issue by making reset_handler() directly use the LMA of the .data section using LOADADDR(.data), rather than assuming that _etext is this LMA. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/cc2538.lds | 1 + cpu/cc2538/startup-gcc.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cpu/cc2538/cc2538.lds b/cpu/cc2538/cc2538.lds index 17b048778..0ca3a2550 100644 --- a/cpu/cc2538/cc2538.lds +++ b/cpu/cc2538/cc2538.lds @@ -91,6 +91,7 @@ SECTIONS *(.data*) _edata = .; } > SRAM AT > FLASH + _ldata = LOADADDR(.data); .ARM.exidx : { diff --git a/cpu/cc2538/startup-gcc.c b/cpu/cc2538/startup-gcc.c index 99a624a7d..b72701505 100644 --- a/cpu/cc2538/startup-gcc.c +++ b/cpu/cc2538/startup-gcc.c @@ -275,7 +275,7 @@ void(*const vectors[])(void) = }; /*---------------------------------------------------------------------------*/ /* Linker constructs indicating .data and .bss segment locations */ -extern unsigned long _etext; +extern unsigned long _ldata; extern unsigned long _data; extern unsigned long _edata; extern unsigned long _bss; @@ -303,7 +303,7 @@ reset_handler(void) REG(SYS_CTRL_EMUOVR) = 0xFF; /* Copy the data segment initializers from flash to SRAM. */ - pul_src = &_etext; + pul_src = &_ldata; for(pul_dst = &_data; pul_dst < &_edata;) { *pul_dst++ = *pul_src++; From 0de729572b70dca479cf4627b01e08c03e24d7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sun, 17 May 2015 21:34:01 +0200 Subject: [PATCH 2/4] cc2538: Word-align .data LMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be fast, the reset_handler() function uses word accesses to initialize the .data output section. However, most toolchains do not automatically force the alignment of an output section LMA to use the maximum alignment of all its input sections. Because of that, assuming that .data contains some words, the LMA of the .data output section was not word-aligned in some cases, resulting in an initialization performed using slow unaligned word accesses. This commit forces the alignment of the LMA of the .data output section with a word boundary in order to always use fast aligned word accesses to read the .data load area. Note that this solution is better than using ALIGN_WITH_INPUT, both because the latter is a new feature incompatible with older toolchains, and because it could create a big gap between _etext and the LMA of .data if strongly-aligned data were added to .data, although only a word alignment is required here. The same considerations apply to the VMA of .data. However, it is already automatically word-aligned, both because .data contains words, and because the end VMA of the previous output section (.socdata) is word-aligned. Moreover, if the VMA of .data were forcibly word-aligned, then a filled gap could appear at the beginning of this section if strongly-aligned data were added to it, thus wasting flash memory. Consequently, it's better not to change anything for the VMA of .data, all the more it's very unlikely that it does not contain any word and that the end VMA of .socdata becomes non-word-aligned, and this would only result in a slower initialization. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/cc2538.lds | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cc2538/cc2538.lds b/cpu/cc2538/cc2538.lds index 0ca3a2550..84908bd60 100644 --- a/cpu/cc2538/cc2538.lds +++ b/cpu/cc2538/cc2538.lds @@ -85,7 +85,7 @@ SECTIONS *(.udma_channel_control_table) } > SRAM - .data : + .data : ALIGN(4) { _data = .; *(.data*) From 609c615303ba809c6b000209cdb102f178cef1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sat, 23 May 2015 18:25:33 +0200 Subject: [PATCH 3/4] cc2538: Move the stack out of .bss MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initialization code clearing .bss is allowed to use the stack, so the stack can not be in .bss, or this code will badly fail if it uses the stack. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/cc2538.lds | 5 +++++ cpu/cc2538/startup-gcc.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cpu/cc2538/cc2538.lds b/cpu/cc2538/cc2538.lds index 84908bd60..cfd4cb48c 100644 --- a/cpu/cc2538/cc2538.lds +++ b/cpu/cc2538/cc2538.lds @@ -106,6 +106,11 @@ SECTIONS _ebss = .; } > SRAM + .stack (NOLOAD) : + { + *(.stack) + } > SRAM + #if (LPM_CONF_MAX_PM==2) && (LPM_CONF_ENABLE != 0) .nrdata (NOLOAD) : { diff --git a/cpu/cc2538/startup-gcc.c b/cpu/cc2538/startup-gcc.c index b72701505..bf00c90f9 100644 --- a/cpu/cc2538/startup-gcc.c +++ b/cpu/cc2538/startup-gcc.c @@ -89,7 +89,7 @@ void uart1_isr(void) WEAK_ALIAS(default_handler); #endif /*---------------------------------------------------------------------------*/ /* Allocate stack space */ -static unsigned long stack[512]; +static unsigned long stack[512] __attribute__ ((section(".stack"))); /*---------------------------------------------------------------------------*/ /* Linker construct indicating .text section location */ extern uint8_t _text[0]; From 1cd3c9e7e5235d0aca5f3d4fa461036f6749b4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sun, 17 May 2015 22:28:01 +0200 Subject: [PATCH 4/4] cc2538: Initialize .data/.bss using ROM functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is safer because the previous code assumed that the start and end VMAs of .data and .bss were word-aligned, which is not always the case, so the initialization code could write data outside these sections. The ROM functions support any address boundary. This is faster because the ROM functions are ultra optimized, using realignment and the LDM/STM instructions, which is much better than the previous simple loops of single word accesses. This is smaller because the ROM functions don't require to add any code to the target device other than simple function calls. This makes the code simpler and more maintainable because standard functions are not reimplemented and no assembly is used. Note that this is also faster and smaller than the corresponding functions from the standard string library. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/startup-gcc.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/cpu/cc2538/startup-gcc.c b/cpu/cc2538/startup-gcc.c index bf00c90f9..b4155fa29 100644 --- a/cpu/cc2538/startup-gcc.c +++ b/cpu/cc2538/startup-gcc.c @@ -40,6 +40,7 @@ #include "reg.h" #include "flash-cca.h" #include "sys-ctrl.h" +#include "rom-util.h" #include /*---------------------------------------------------------------------------*/ @@ -275,11 +276,11 @@ void(*const vectors[])(void) = }; /*---------------------------------------------------------------------------*/ /* Linker constructs indicating .data and .bss segment locations */ -extern unsigned long _ldata; -extern unsigned long _data; -extern unsigned long _edata; -extern unsigned long _bss; -extern unsigned long _ebss; +extern uint8_t _ldata; +extern uint8_t _data; +extern uint8_t _edata; +extern uint8_t _bss; +extern uint8_t _ebss; /*---------------------------------------------------------------------------*/ /* Weak interrupt handlers. */ void @@ -298,26 +299,13 @@ default_handler(void) void reset_handler(void) { - unsigned long *pul_src, *pul_dst; - REG(SYS_CTRL_EMUOVR) = 0xFF; /* Copy the data segment initializers from flash to SRAM. */ - pul_src = &_ldata; - - for(pul_dst = &_data; pul_dst < &_edata;) { - *pul_dst++ = *pul_src++; - } + rom_util_memcpy(&_data, &_ldata, &_edata - &_data); /* Zero-fill the bss segment. */ - __asm(" ldr r0, =_bss\n" - " ldr r1, =_ebss\n" - " mov r2, #0\n" - " .thumb_func\n" - "zero_loop:\n" - " cmp r0, r1\n" - " it lt\n" - " strlt r2, [r0], #4\n" " blt zero_loop"); + rom_util_memset(&_bss, 0, &_ebss - &_bss); /* call the application's entry point. */ main();