STM32 Memory Problem

Sysprogs forums Forums VisualGDB STM32 Memory Problem

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #7501
    malcolmrook
    Participant

    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 data

    Index     Value
    608         0x20001F700000000
    609         0x0801826920001F78
    610         0xFFFFFFF920001FA8
    611         0x0000070A00000000
    612         0x20008B7A200044C0
    613        0x0800DFA3200094AA
    614         0x0100000008D1614E

    Changing 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

     

     

    #7519
    support
    Keymaster

    Hi,

    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.

    #7544
    andyjt
    Participant

    Those 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 = 16K

    FLASH(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

     

     

    #7558
    support
    Keymaster

    Yes, 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.

    #7564
    malcolmrook
    Participant

    An 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);
    } > SRAM

    PROVIDE(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.

    #7566
    malcolmrook
    Participant

    Found 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.

    #7575
    support
    Keymaster

    Hi,

    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.

Viewing 7 posts - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.