# read from uint32_t in flash is zero STM32F1

I am working on an STM32F103RBT6 program and at some point I need to store values in the FLASH.

Writing in Flash is working as a charm, if I parse through the memory of my microcontroller, I see that the data has been written at the expected spot.

However, if I try to read the data I stored on a word (uint32_t), I read 0.

__attribute__((__section__(".nb_Frames"))) const uint32_t nb_Frames_Flash;
uint8_t CAN_nb_Frames_Tx_cc = 0;

[...]

CAN_nb_Frames_Tx_cc = (nb_Frames_Flash & 0x000000FF);


For example here, I want to get the low byte of the value stored in nb_Frames_Flash (0x01 for example), but CAN_nb_Frames_Tx_cc stays = 0.

I am sure that nb_Frames_Flash != 0 because If I go through these lines step by step thanks to the debugger, I can see that nb_Frames_Flash = 0x00010101 (which is the value I wrote in the Flash). The assignement just feels like it's not going through ...

I have tried to change the assignement : CAN_nb_Frames_Tx_cc = (nb_Frames_Flash & 0x000000FF); by adding casts, changing the definition of CAN_nb_Frames_Tx_cc (uint32_t for instance), going through an intermediate variable ... But it just won't work ...

I am really stuck here and I don't know why it is not properly working.

The thing that makes me go nuts is that reading in Flash is completely working for structures. I stored structures in Flash, and I have no issue to read them and store them in a RAM variable ...

EDIT : Here is my linker script :

{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 128K - 5K
Erases (RW)     : ORIGIN = 0x801EC00, LENGTH = 4
Frames (RW)     : ORIGIN = 0x801EC04, LENGTH = 4
TRAMESTx (RW)   : ORIGIN = 0x801EC08, LENGTH = 1400
TRAMESRx (RW)   : ORIGIN = 0x801F180, LENGTH = 1800
TRAMESADC(RW)   : ORIGIN = 0x801F888, LENGTH = 800
TRAMESOP (RW)   : ORIGIN = 0x801FBA8, LENGTH = 800
}

/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH

.nb_Erases :
{
. = ALIGN(4);

*(.nb_Erases)

. = ALIGN(4);
} > Erases

.nb_Frames :
{
. = ALIGN(4);

*(.nb_Frames)

. = ALIGN(4);
} > Frames

.user_TramesTx :
{
. = ALIGN(4);

*(.user_TramesTx)

. = ALIGN(4);
} > TRAMESTx

.user_TramesRx :
{
. = ALIGN(4);

*(.user_TramesRx)

. = ALIGN(4);
} > TRAMESRx

{
. = ALIGN(4);

. = ALIGN(4);

.user_TramesOp :
{
. = ALIGN(4);

*(.user_TramesOp)

. = ALIGN(4);
} > TRAMESOP

• Publish your linker script. The section .nb_Frames can be placed at a wrong address, eg. RAM, bss or in a black-hole. You could also generate a map file to see the exact placement. – filo Jul 25 '18 at 8:51
• I added it, but I am pretty confident about it being correct since I can write in flash without any issue. But feel free to say if anything is wrong ! – B.Clergue Jul 25 '18 at 9:39

You need to make nb_Frames_Flash volatile.
The compiler sees no change to nb_Frames_Flash anywhere in the code. Thus it implies it is 0. Resulting no code will be inserted for the assignement of CAN_nb_Frames_Tx_cc. (check the assembler, it will be missing)
__attribute__((__section__(".nb_Frames"))) volatile const uint32_t nb_Frames_Flash;
The volatile keyword explicitly instructs to compiler to perform a read for every use of nb_Frames_Flash.
• @B.Clergue The compiler optimizations. Try it without -O0. – Jeroen3 Jul 25 '18 at 19:25