Sysprogs forums › Forums › VisualGDB › STM32 Memory Problem
Tagged: STM32 STM32L151RE Memory
- This topic has 6 replies, 3 voices, and was last updated 8 years, 10 months ago by support.
-
AuthorPosts
-
January 20, 2016 at 18:45 #7501malcolmrookParticipant
Hi
I have a STM32L151RE micro with bootloader at 0x8000000 and application firmware at 0x8004000. The firmware occupies approx. 85K flash and 37K ram. The compiler used was VisualGDB.
During initialisation the firmware loads arrays with user data in the form of a 64 bit Id and 2 32bit fields from external memory. To keep things clean I am initialising the arrays with a simple for loop setting all elements to zero.
Arrays are declared global as
uint64_t op_id[2000];
uint32_t u_id[2000];
uint32_t expiry[2000];The initialisation loop is
for (op_cnt = 0; op_cnt < 2000; op_cnt++)
{
op_id[op_cnt] = 0x0000000000000000;
expiry[op_cnt] = 0x00000000;
u_id[op_cnt] = 0x00000000;
}
Unfortunately some elements of op_id are not zeroed but contain dataIndex Value
608 0x20001F700000000
609 0x0801826920001F78
610 0xFFFFFFF920001FA8
611 0x0000070A00000000
612 0x20008B7A200044C0
613 0x0800DFA3200094AA
614 0x0100000008D1614EChanging the firmware can cause the affected indexes to move.
Looking at these values they appear to be memory and program addresses. The shows 20001F70 to be element 609 (index 608) of op_id and other values also refer to points within the processes.
Has anyone any idea what is happening? Possible compiler problem?
Malcolm
January 23, 2016 at 06:16 #7519supportKeymasterHi,
Perhaps some of the data gets overwritten? Please try setting a breakpoint right after initializing them with zero and use the Watch window to check whether they actually contain zeros. If not, check that those variables actually fit in the RAM area of your device. If yes, try setting a data breakpoint on one of them to see what code modifies it.
January 26, 2016 at 10:59 #7544andyjtParticipantThose numbers look suspiciously like Program Counter, Stack or Variable addresses. I guess the bootloader and firmware code is getting mixed up.
I’d be checking the contents of your .lds file is correct and takes into account the bootloader address and firmware address ,eg something like:
MEMORY
{
BOOT (RX) : ORIGIN = 0x08000000, LENGTH = 16KFLASH(RX):: ORIGIN = 0x08004000, LENGTH = ??K
SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 320K
}I’d also double check the lengths and that _estack address is correct – I found a problem with a lesser used STM32F303C8T6 micro had the estack set above the actual 12K (IIRC?) in the .lds file provided by VisualGDB
January 27, 2016 at 22:19 #7558supportKeymasterYes, that should help. Also VisualGDB 5.1 Preview 2 automatically verifies _estack by trying to write at _estack – 4 and check that the memory gets actually modified.
January 28, 2016 at 10:51 #7564malcolmrookParticipantAn update.
I had already set a breakpoint immediately after the initialisation loop which is where I obtained the values given in my original post.
I have experienced some similar problems before when using large arrays but got round them by declaring them global.
The array variables are declared global and should fit within the RAM as build shows 37K used out of 80K.
I have not tried setting the data breakpoint, as suggested by Bazis, yet but will do.
MCU has 512K flash and 80K ram so FLASH length set in lds file as 480K (512K – 32K for bootloader) and SRAM set to 80K.
_estack address is 20014000 which is within the SRAM (20000000 – 20014140)
lds file is below
ENTRY(Reset_Handler)
MEMORY
{
FLASH (RX) : ORIGIN = 0x08004000, LENGTH = 480K
SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 80K
EEPROM (RX) : ORIGIN = 0x08080000, LENGTH = 16K
}_estack = 0x20014000;
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} > FLASH.text :
{
. = ALIGN(4);
_stext = .;*(.text)
*(.text*)
*(.rodata)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
_etext = .;} > FLASH
.ARM.extab :
{
. = ALIGN(4);
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
. = ALIGN(4);
} > FLASH.exidx :
{
. = ALIGN(4);
PROVIDE(__exidx_start = .);
*(.ARM.exidx*)
. = ALIGN(4);
PROVIDE(__exidx_end = .);
} > FLASH.ARM.attributes :
{
*(.ARM.attributes)
} > FLASH.preinit_array :
{
PROVIDE(__preinit_array_start = .);
KEEP(*(.preinit_array*))
PROVIDE(__preinit_array_end = .);
} > FLASH.init_array :
{
PROVIDE(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array*))
PROVIDE(__init_array_end = .);
} > FLASH.fini_array :
{
PROVIDE(__fini_array_start = .);
KEEP(*(.fini_array*))
KEEP(*(SORT(.fini_array.*)))
PROVIDE(__fini_array_end = .);
} > FLASH. = ALIGN(4);
_sidata = .;.data : AT(_sidata)
{
. = ALIGN(4);
_sdata = .;PROVIDE(__data_start__ = _sdata);
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;PROVIDE(__data_end__ = _edata);
} > SRAM.bss :
{
. = ALIGN(4);
_sbss = .;PROVIDE(__bss_start__ = _sbss);
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;PROVIDE(__bss_end__ = _ebss);
} > SRAMPROVIDE(end = .);
}
Finally had to bite the bullet and downloaded full evaluation of Keil MDK 5. Used exactly the same code for main.c and it works fine. Only difference was the size of the bin file produced at 37K instead of 85K. Surely VisualGDB should do better. Downside of Keil is the price. A single seat license will cost almost £1300 if I have to go down that route.
January 28, 2016 at 13:08 #7566malcolmrookParticipantFound the source of the problem.
I was initializing all the peripherals at the start of the program, including 3 uart ports.
Receive on all ports was interrupt driven with the callback capturing data byte by byte and writing to buffers which were set to 300 bytes with a counter and a data set flag.
I then initialized GPS and GSM modules before reading the user data. Unfortunately at this point the main loop which would read the data set flags and process received data was not entered.
The result was that GPS module was sending out location messages, which were being buffered but not processed.
I had omitted to do a bounds check on the interrupt routine for the uart handling the GPS messages so it continued to buffer data beyond the 300 byte array size.
As it happened the address of the array put it as the last entry in ram.
The result was that it kept writing with no problems until it eventually hit the stack address with obviously unpredictable results.
It was a stupid mistake which I should never have made.
I found it while looking at all the global variables after I had hit the problem and saw the byte counter for the uart data received (uint16_t to handle byte count beyond 256) way beyond where it should have been.
I have now put in a trap to stop writing the uart buffer at its designated size .
All is now OK.
Sometimes just putting your problems down in writing can clear you head and start you thinking straight.
Many thanks to those who offered advice.
January 30, 2016 at 08:01 #7575supportKeymasterHi,
Good to hear you got it to work. Regarding the size, please try switching to newlib-nano. It significantly reduces the size of your binary.
-
AuthorPosts
- You must be logged in to reply to this topic.