diff --git a/miosix/_doc/textdoc/Changelog.txt b/miosix/_doc/textdoc/Changelog.txt index fa00fcb14703ce84e12713fc6bb33c1fbec7f034..ddb7158974a69f79afde0c66eccc9536f918242e 100644 --- a/miosix/_doc/textdoc/Changelog.txt +++ b/miosix/_doc/textdoc/Changelog.txt @@ -1,5 +1,8 @@ Changelog for Miosix np embedded OS +- Added SDRAM initialization code for stm32f429 board, and SDRAM linker + scripts. The new default is to put .data/.bss/stack and heap in the SDRAM, + and to leave the upper 2MB of it for the LCD. - Cleaned up code completion configuration for Netbeans. Now the IDE automatically detects the source files that belong to the project by looking at the debug symbols in the produced elf file. diff --git a/miosix/_tools/ram_test/main.cpp b/miosix/_tools/ram_test/main.cpp index 88808510d6921016cb0f685fa9a167a1b56de1cc..24963c8f3524ed36557bb71bf72c59dfbf21b094 100644 --- a/miosix/_tools/ram_test/main.cpp +++ b/miosix/_tools/ram_test/main.cpp @@ -21,6 +21,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "sha1.h" const unsigned int ramBase=0x60000000; //Tune this to the right value @@ -49,6 +50,7 @@ template<typename T> bool ramTest() } unsigned int a[5]; sha.Result(a); + sleep(10); //To check SDRAM retention ability sha.Reset(); for(unsigned int i=ramBase;i<ramBase+ramSize;i+=sizeof(T)) { @@ -63,11 +65,14 @@ template<typename T> bool ramTest() int main() { - iprintf("RAM test\nTesting word size transfers\n"); - if(ramTest<unsigned int>()) return 1; - iprintf("Testing halfword size transfers\n"); - if(ramTest<unsigned short>()) return 1; - iprintf("Testing byte size transfers\n"); - if(ramTest<unsigned char>()) return 1; - iprintf("Ok\n"); + for(;;) + { + iprintf("RAM test\nTesting word size transfers\n"); + if(ramTest<unsigned int>()) return 1; + iprintf("Testing halfword size transfers\n"); + if(ramTest<unsigned short>()) return 1; + iprintf("Testing byte size transfers\n"); + if(ramTest<unsigned char>()) return 1; + iprintf("Ok\n"); + } } diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/core/stage_1_boot.cpp b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/core/stage_1_boot.cpp index f472d466b640a8f14919a727a6bbe73a2d9efe8f..58e52fcf3c8fba042e0ce4757f807546cb2c99c5 100644 --- a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/core/stage_1_boot.cpp @@ -1,5 +1,6 @@ #include "interfaces/arch_registers.h" +#include "interfaces/bsp.h" #include "core/interrupts.h" //For the unexpected interrupt call #include <string.h> @@ -26,18 +27,6 @@ void program_startup() //Cortex M3 core appears to get out of reset with interrupts already enabled __disable_irq(); - //SystemInit() is called *before* initializing .data and zeroing .bss - //Despite all startup files provided by ST do the opposite, there are three - //good reasons to do so: - //First, the CMSIS specifications say that SystemInit() must not access - //global variables, so it is actually possible to call it before - //Second, when running Miosix with the xram linker scripts .data and .bss - //are placed in the external RAM, so we *must* call SystemInit(), which - //enables xram, before touching .data and .bss - //Third, this is a performance improvement since the loops that initialize - //.data and zeros .bss now run with the CPU at full speed instead of 8MHz - SystemInit(); - //These are defined in the linker script extern unsigned char _etext asm("_etext"); extern unsigned char _data asm("_data"); @@ -68,6 +57,24 @@ void program_startup() void Reset_Handler() __attribute__((__interrupt__, noreturn)); void Reset_Handler() { + //SystemInit() is called *before* initializing .data and zeroing .bss + //Despite all startup files provided by ST do the opposite, there are three + //good reasons to do so: + //First, the CMSIS specifications say that SystemInit() must not access + //global variables, so it is actually possible to call it before + //Second, when running Miosix with the xram linker scripts .data and .bss + //are placed in the external RAM, so we *must* call SystemInit(), which + //enables xram, before touching .data and .bss + //Third, this is a performance improvement since the loops that initialize + //.data and zeros .bss now run with the CPU at full speed instead of 8MHz + SystemInit(); + //ST does not provide code to initialize the stm32f429-disco SDRAM at boot. + //Put after SystemInit() as SDRAM is timing-sensitive and needs the full + //clock speed. + #ifdef __ENABLE_XRAM + miosix::configureSdram(); + #endif //__ENABLE_XRAM + /* * Initialize process stack and switch to it. * This is required for booting Miosix, a small portion of the top of the diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp.cpp b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp.cpp index dd70a7d45c08cb4efe52c23d123ed5077c56fa20..c28a7c2bde78b49b448775d2d3b1a369b2002ff4 100644 --- a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp.cpp +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp.cpp @@ -53,21 +53,140 @@ namespace miosix { // Initialization // -void IRQbspInit() +/** + * The example code from ST checks for the busy flag after each command. + * Interestingly I couldn't find any mention of this in the datsheet. + */ +static void sdramCommandWait() +{ + for(int i=0;i<0xffff;i++) + if((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY)==0) return; +} + +void configureSdram() { //Enable all gpios RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN; - GPIOA->OSPEEDR=0xaaaaaaaa; //Default to 50MHz speed for all GPIOS - GPIOB->OSPEEDR=0xaaaaaaaa; - GPIOC->OSPEEDR=0xaaaaaaaa; - GPIOD->OSPEEDR=0xaaaaaaaa; - GPIOE->OSPEEDR=0xaaaaaaaa; - GPIOF->OSPEEDR=0xaaaaaaaa; - GPIOG->OSPEEDR=0xaaaaaaaa; + + //For reasons unknown the write to GPIOB->AFR does not occur without a DMB + //in the middle + __DMB(); + + //First, configure SDRAM GPIOs + GPIOB->AFR[0]=0x0cc00000; + GPIOC->AFR[0]=0x0000000c; + GPIOD->AFR[0]=0x000000cc; + GPIOD->AFR[1]=0xcc000ccc; + GPIOE->AFR[0]=0xc00000cc; + GPIOE->AFR[1]=0xcccccccc; + GPIOF->AFR[0]=0x00cccccc; + GPIOF->AFR[1]=0xccccc000; + GPIOG->AFR[0]=0x00cc00cc; + GPIOG->AFR[1]=0xc000000c; + + GPIOB->MODER=0x00002800; + GPIOC->MODER=0x00000002; + GPIOD->MODER=0xa02a000a; + GPIOE->MODER=0xaaaa800a; + GPIOF->MODER=0xaa800aaa; + GPIOG->MODER=0x80020a0a; + + GPIOA->OSPEEDR=0xaaaaaaaa; //Default to 50MHz speed for all GPIOs... + GPIOB->OSPEEDR=0xaaaaaaaa | 0x00003c00; //...but 100MHz for the SDRAM pins + GPIOC->OSPEEDR=0xaaaaaaaa | 0x00000003; + GPIOD->OSPEEDR=0xaaaaaaaa | 0xf03f000f; + GPIOE->OSPEEDR=0xaaaaaaaa | 0xffffc00f; + GPIOF->OSPEEDR=0xaaaaaaaa | 0xffc00fff; + GPIOG->OSPEEDR=0xaaaaaaaa | 0xc0030f0f; GPIOH->OSPEEDR=0xaaaaaaaa; + + //Since we'we un-configured PB3/PB4 from the default at boot TDO,NTRST, + //finish the job and remove the default pull-up + GPIOB->PUPDR=0; + + //Second, actually start the SDRAM controller + RCC->AHB3ENR |= RCC_AHB3ENR_FMCEN; + + //This doesn't seem to be needed, but better be safe + __DMB(); + + //SDRAM is a IS42S16400J -7 speed grade, connected to bank 2 (0xd0000000) + //Some bits in SDCR[1] are don't care, and the have to be set in SDCR[0], + //they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDCR[0]=FMC_SDCR1_SDCLK_1// SDRAM runs @ half CPU frequency + | FMC_SDCR1_RBURST // Enable read burst + | 0; // 0 delay between reads after CAS + FMC_Bank5_6->SDCR[1]=0 // 8 bit column address + | FMC_SDCR1_NR_0 // 12 bit row address + | FMC_SDCR1_MWID_0 // 16 bit data bus + | FMC_SDCR1_NB // 4 banks + | FMC_SDCR1_CAS_1; // 2 cycle CAS latency (F<133MHz) + + #ifdef SYSCLK_FREQ_180MHz + //One SDRAM clock cycle is 11.1ns + //Some bits in SDTR[1] are don't care, and the have to be set in SDTR[0], + //they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDTR[0]=(6-1)<<12 // 6 cycle TRC (66.6ns>63ns) + | (2-1)<<20; // 2 cycle TRP (22.2ns>15ns) + FMC_Bank5_6->SDTR[1]=(2-1)<<0 // 2 cycle TMRD + | (7-1)<<4 // 7 cycle TXSR (77.7ns>70ns) + | (4-1)<<8 // 4 cycle TRAS (44.4ns>42ns) + | (2-1)<<16 // 2 cycle TWR + | (2-1)<<24; // 2 cycle TRCD (22.2ns>15ns) + #elif defined(SYSCLK_FREQ_168MHz) + //One SDRAM clock cycle is 11.9ns + //Some bits in SDTR[1] are don't care, and the have to be set in SDTR[0], + //they aren't just don't care, the controller will fail if they aren't at 0 + FMC_Bank5_6->SDTR[0]=(6-1)<<12 // 6 cycle TRC (71.4ns>63ns) + | (2-1)<<20; // 2 cycle TRP (23.8ns>15ns) + FMC_Bank5_6->SDTR[1]=(2-1)<<0 // 2 cycle TMRD + | (6-1)<<4 // 6 cycle TXSR (71.4ns>70ns) + | (4-1)<<8 // 4 cycle TRAS (47.6ns>42ns) + | (2-1)<<16 // 2 cycle TWR + | (2-1)<<24; // 2 cycle TRCD (23.8ns>15ns) + #else + #error No SDRAM timings for this clock + #endif + + FMC_Bank5_6->SDCMR= FMC_SDCMR_CTB2 // Enable bank 2 + | 1; // MODE=001 clock enabled + sdramCommandWait(); + + //ST and SDRAM datasheet agree a 100us delay is required here. + delayUs(100); + + FMC_Bank5_6->SDCMR= FMC_SDCMR_CTB2 // Enable bank 2 + | 2; // MODE=010 precharge all command + sdramCommandWait(); + + FMC_Bank5_6->SDCMR= (8-1)<<5 // NRFS=8 SDRAM datasheet says + // "at least two AUTO REFRESH cycles" + | FMC_SDCMR_CTB2 // Enable bank 2 + | 3; // MODE=011 auto refresh + sdramCommandWait(); + + FMC_Bank5_6->SDCMR=0x220<<9 // MRD=0x220:CAS latency=2 burst len=1 + | FMC_SDCMR_CTB2 // Enable bank 2 + | 4; // MODE=100 load mode register + sdramCommandWait(); + + // 64ms/4096=15.625us + #ifdef SYSCLK_FREQ_180MHz + //15.625us*90MHz=1406-20=1386 + FMC_Bank5_6->SDRTR=1386<<1; + #elif defined(SYSCLK_FREQ_168MHz) + //15.625us*84MHz=1312-20=1292 + FMC_Bank5_6->SDRTR=1292<<1; + #else + #error No refresh timings for this clock + #endif +} + +void IRQbspInit() +{ _led::mode(Mode::OUTPUT); ledOn(); delayMs(100); diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp_impl.h b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp_impl.h index dd877042f0083df9e82640d81b7bd85d53476840..f7328521623a66f6abfc9fedd691b380ad97fe27 100644 --- a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp_impl.h +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/interfaces-impl/bsp_impl.h @@ -44,6 +44,13 @@ namespace miosix { \{ */ +/** + * \internal + * Called by stage_1_boot.cpp to enable the SDRAM before initializing .data/.bss + * Requires the CPU clock to be already configured (running from the PLL) + */ +void configureSdram(); + /** * \internal * used by the ledOn() and ledOff() implementation diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/stm32_2m+6m_xram.ld b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/stm32_2m+6m_xram.ld new file mode 100644 index 0000000000000000000000000000000000000000..1241513082489d468e3d29bcadd7aadfc6c3ad30 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/stm32_2m+6m_xram.ld @@ -0,0 +1,179 @@ +/* + * C++ enabled linker script for stm32 (2M FLASH, 256K RAM, 8M XRAM) + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This chip has an unusual quirk that the RAM is divided in two block mapped + * at two non contiguous memory addresses. I don't know why they've done that, + * probably doing the obvious thing would have made writing code too easy... + * Anyway, since hardware can't be changed, we've got to live with that and + * try to make use of both RAMs. + * + * Given the constraints above, this linker script puts: + * - read only data and code (.text, .rodata, .eh_*) in FLASH + * - the 512Byte main (IRQ) stack, .data and .bss in the "small" 64KB RAM + * - .data, .bss, stacks and heap in the external 6MB SDRAM. + * Note that the SDRAM is 8MB, but this linker script only uses the lower 6. + * The upper 2MB are reserved as framebuffers for the LCD. Notice that the + * choice to allocate this space is due to the SDRAM architecture, composed of + * 4 banks of 2MB each. Reserving a bank for the LCD allows the software + * running on the board and the LCD to operate (almost) independently. + */ + +/* + * The main stack is used for interrupt handling by the kernel. + * + * *** Readme *** + * This linker script places the main stack (used by the kernel for interrupts) + * at the bottom of the ram, instead of the top. This is done for two reasons: + * + * - as an optimization for microcontrollers with little ram memory. In fact + * the implementation of malloc from newlib requests memory to the OS in 4KB + * block (except the first block that can be smaller). This is probably done + * for compatibility with OSes with an MMU and paged memory. To see why this + * is bad, consider a microcontroller with 8KB of ram: when malloc finishes + * up the first 4KB it will call _sbrk_r asking for a 4KB block, but this will + * fail because the top part of the ram is used by the main stack. As a + * result, the top part of the memory will not be used by malloc, even if + * available (and it is nearly *half* the ram on an 8KB mcu). By placing the + * main stack at the bottom of the ram, the upper 4KB block will be entirely + * free and available as heap space. + * + * - In case of main stack overflow the cpu will fault because access to memory + * before the beginning of the ram faults. Instead with the default stack + * placement the main stack will silently collide with the heap. + * Note: if increasing the main stack size also increase the ORIGIN value in + * the MEMORY definitions below accordingly. + */ +_main_stack_size = 0x00000200; /* main stack = 512Bytes */ +_main_stack_top = 0x10000000 + _main_stack_size; +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* Mapping the heap into the large 192KB RAM */ +_heap_end = 0xd0600000; /* end of available ram */ + +/* identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* specify the memory areas */ +MEMORY +{ + flash(rx) : ORIGIN = 0x08000000, LENGTH = 2M + /* + * Note, the small ram starts at 0x10000000 but it is necessary to add the + * size of the main stack, so it is 0x10000200. + */ + smallram(wx) : ORIGIN = 0x10000200, LENGTH = 64K-0x200 + largeram(wx) : ORIGIN = 0x20000000, LENGTH = 192K + xram(wx) : ORIGIN = 0xd0000000, LENGTH = 6M + lcdram(wx) : ORIGIN = 0xd0600000, LENGTH = 2M +} + +/* now define the output sections */ +SECTIONS +{ + . = 0; + + /* .text section: code goes to flash */ + .text : + { + /* Startup code must go at address 0 */ + KEEP(*(.isr_vector)) + + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + /* these sections for thumb interwork? */ + *(.glue_7) + *(.glue_7t) + /* these sections for C++? */ + *(.gcc_except_table) + *(.gcc_except_table.*) + *(.ARM.extab*) + *(.gnu.linkonce.armextab.*) + + . = ALIGN(4); + /* .rodata: constant data */ + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + /* C++ Static constructors/destructors (eabi) */ + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + /* C++ Static constructors/destructors (elf) */ + . = ALIGN(4); + _ctor_start = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + _ctor_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > flash + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > flash + __exidx_end = .; + + . = ALIGN(8); + _etext = .; + + /* .data section: global variables go to ram, but also store a copy to + flash to initialize them */ + .data : ALIGN(8) + { + _data = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + _edata = .; + } > xram AT > flash + + /* .bss section: uninitialized global variables go to ram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > xram + _bss_end = .; + + _end = .; + PROVIDE(end = .); +} diff --git a/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/stm32_2m+8m_xram.ld b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/stm32_2m+8m_xram.ld new file mode 100644 index 0000000000000000000000000000000000000000..07e2b45ef4cb044c86044797c996aa07df5ef4c4 --- /dev/null +++ b/miosix/arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/stm32_2m+8m_xram.ld @@ -0,0 +1,173 @@ +/* + * C++ enabled linker script for stm32 (2M FLASH, 256K RAM, 8M XRAM) + * Developed by TFT: Terraneo Federico Technologies + * Optimized for use with the Miosix kernel + */ + +/* + * This chip has an unusual quirk that the RAM is divided in two block mapped + * at two non contiguous memory addresses. I don't know why they've done that, + * probably doing the obvious thing would have made writing code too easy... + * Anyway, since hardware can't be changed, we've got to live with that and + * try to make use of both RAMs. + * + * Given the constraints above, this linker script puts: + * - read only data and code (.text, .rodata, .eh_*) in FLASH + * - the 512Byte main (IRQ) stack, .data and .bss in the "small" 64KB RAM + * - .data, .bss, stacks and heap in the external 8MB SDRAM. + */ + +/* + * The main stack is used for interrupt handling by the kernel. + * + * *** Readme *** + * This linker script places the main stack (used by the kernel for interrupts) + * at the bottom of the ram, instead of the top. This is done for two reasons: + * + * - as an optimization for microcontrollers with little ram memory. In fact + * the implementation of malloc from newlib requests memory to the OS in 4KB + * block (except the first block that can be smaller). This is probably done + * for compatibility with OSes with an MMU and paged memory. To see why this + * is bad, consider a microcontroller with 8KB of ram: when malloc finishes + * up the first 4KB it will call _sbrk_r asking for a 4KB block, but this will + * fail because the top part of the ram is used by the main stack. As a + * result, the top part of the memory will not be used by malloc, even if + * available (and it is nearly *half* the ram on an 8KB mcu). By placing the + * main stack at the bottom of the ram, the upper 4KB block will be entirely + * free and available as heap space. + * + * - In case of main stack overflow the cpu will fault because access to memory + * before the beginning of the ram faults. Instead with the default stack + * placement the main stack will silently collide with the heap. + * Note: if increasing the main stack size also increase the ORIGIN value in + * the MEMORY definitions below accordingly. + */ +_main_stack_size = 0x00000200; /* main stack = 512Bytes */ +_main_stack_top = 0x10000000 + _main_stack_size; +ASSERT(_main_stack_size % 8 == 0, "MAIN stack size error"); + +/* Mapping the heap into the large 192KB RAM */ +_heap_end = 0xd0800000; /* end of available ram */ + +/* identify the Entry Point */ +ENTRY(_Z13Reset_Handlerv) + +/* specify the memory areas */ +MEMORY +{ + flash(rx) : ORIGIN = 0x08000000, LENGTH = 2M + /* + * Note, the small ram starts at 0x10000000 but it is necessary to add the + * size of the main stack, so it is 0x10000200. + */ + smallram(wx) : ORIGIN = 0x10000200, LENGTH = 64K-0x200 + largeram(wx) : ORIGIN = 0x20000000, LENGTH = 192K + xram(wx) : ORIGIN = 0xd0000000, LENGTH = 8M +} + +/* now define the output sections */ +SECTIONS +{ + . = 0; + + /* .text section: code goes to flash */ + .text : + { + /* Startup code must go at address 0 */ + KEEP(*(.isr_vector)) + + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + /* these sections for thumb interwork? */ + *(.glue_7) + *(.glue_7t) + /* these sections for C++? */ + *(.gcc_except_table) + *(.gcc_except_table.*) + *(.ARM.extab*) + *(.gnu.linkonce.armextab.*) + + . = ALIGN(4); + /* .rodata: constant data */ + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + /* C++ Static constructors/destructors (eabi) */ + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + /* C++ Static constructors/destructors (elf) */ + . = ALIGN(4); + _ctor_start = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + _ctor_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > flash + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > flash + __exidx_end = .; + + . = ALIGN(8); + _etext = .; + + /* .data section: global variables go to ram, but also store a copy to + flash to initialize them */ + .data : ALIGN(8) + { + _data = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + _edata = .; + } > xram AT > flash + + /* .bss section: uninitialized global variables go to ram */ + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + . = ALIGN(8); + } > xram + _bss_end = .; + + _end = .; + PROVIDE(end = .); +} diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index 917c77e7a572e62d2e5e78ec5fed9bc61ecf46f8..f30993e35b4c7dc1c4c676520cff441b6cc706de 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -196,7 +196,7 @@ endif ## ifeq ($(OPT_BOARD),stm32f207zg_ethboard_v2) - ## Linker script type, there are three options + ## Linker script type, there are two options ## 1) Code in FLASH, stack + heap in internal RAM (file *_rom.ld) ## the most common choice, available for all microcontrollers ## 2) Code in external RAM, stack + heap in internal RAM @@ -234,10 +234,22 @@ endif ## ifeq ($(OPT_BOARD),stm32f429zi_stm32f4discovery) - ## Linker script type + ## Linker script type, there are three options + ## 1) Code in FLASH, stack + heap in internal RAM (file *_rom.ld) + ## the most common choice, available for all microcontrollers + ## 2) Code in FLASH, stack + heap in external RAM (file *8m_xram.ld) + ## You must uncomment -D__ENABLE_XRAM below in this case. + ## 3) Code in FLASH, stack + heap in external RAM (file *6m_xram.ld) + ## Same as above, but leaves the upper 2MB of RAM for the LCD. LINKER_SCRIPT_PATH := arch/cortexM4_stm32f4/stm32f429zi_stm32f4discovery/ - LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_2m+256k_rom.ld - #TODO: more options + #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_2m+256k_rom.ld + #LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_2m+8m_xram.ld + LINKER_SCRIPT := $(LINKER_SCRIPT_PATH)stm32_2m+6m_xram.ld + + ## Uncommenting __ENABLE_XRAM enables the initialization of the external + ## 8MB SDRAM memory. Do not uncomment this even if you don't use a linker + ## script that requires it, as it is used for the LCD framebuffer. + XRAM := -D__ENABLE_XRAM ## Select clock frequency. Warning: the default clock frequency for ## this board is 168MHz and not 180MHz because, due to a limitation in @@ -733,10 +745,10 @@ else ifeq ($(ARCH),cortexM4_stm32f4) ## Select appropriate compiler flags for both ASM/C/C++/linker AFLAGS_BASE := -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 - CFLAGS_BASE += -D_ARCH_CORTEXM4_STM32F4 $(CLOCK_FREQ) $(SRAM_BOOT) \ + CFLAGS_BASE += -D_ARCH_CORTEXM4_STM32F4 $(CLOCK_FREQ) $(XRAM) $(SRAM_BOOT)\ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ $(OPT_OPTIMIZATION) -ffunction-sections -Wall -g -c - CXXFLAGS_BASE += -D_ARCH_CORTEXM4_STM32F4 $(CLOCK_FREQ) $(SRAM_BOOT) \ + CXXFLAGS_BASE += -D_ARCH_CORTEXM4_STM32F4 $(CLOCK_FREQ) $(XRAM) $(SRAM_BOOT)\ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ $(OPT_EXCEPT) $(OPT_OPTIMIZATION) -ffunction-sections \ -Wall -g -c diff --git a/miosix/config/miosix_settings.h b/miosix/config/miosix_settings.h index ee129f194914c0f78c93fbe118ed12f597c85447..a2deb70206efa3ab6e328c83449f9cb99585916a 100644 --- a/miosix/config/miosix_settings.h +++ b/miosix/config/miosix_settings.h @@ -130,7 +130,7 @@ const unsigned char MAX_OPEN_FILES=8; /** * \def JTAG_DISABLE_SLEEP * JTAG debuggers lose communication with the device if it enters sleep - * mode, so to use debugging it is necessary to disble sleep in the idle thread. + * mode, so to use debugging it is necessary to disable sleep in the idle thread. * By default it is not defined (idle thread calls sleep). */ //#define JTAG_DISABLE_SLEEP diff --git a/miosix_np_2/nbproject/configurations.xml b/miosix_np_2/nbproject/configurations.xml index 3bb25a253da3328e672394cd8c079ee957b9ff8a..18536fa3b58f4fc5ed3f2a71a1eb2ddb4d1ec3ac 100644 --- a/miosix_np_2/nbproject/configurations.xml +++ b/miosix_np_2/nbproject/configurations.xml @@ -8596,6 +8596,7 @@ <Elem>SYSCLK_FREQ_168MHz</Elem> <Elem>_ARCH_CORTEXM4_STM32F4</Elem> <Elem>_BOARD_STM32F429ZI_STM32F4DISCOVERY</Elem> + <Elem>__ENABLE_XRAM</Elem> <Elem>__VFP_FP__</Elem> </preprocessorList> </cTool> @@ -8605,6 +8606,7 @@ <Elem>SYSCLK_FREQ_168MHz</Elem> <Elem>_ARCH_CORTEXM4_STM32F4</Elem> <Elem>_BOARD_STM32F429ZI_STM32F4DISCOVERY</Elem> + <Elem>__ENABLE_XRAM</Elem> <Elem>__VFP_FP__</Elem> </preprocessorList> </ccTool>