cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 RAM writing issue.

kalbar666
Associate II
Posted on December 15, 2015 at 18:10

Hello,

I am having a bit of a mysterious bug in here. I am working on STM32F427 chip and tryin to write a bootloader. I have a problem with copying memory from FLASH to RAM. Looks like there is a specific memory address in RAM towards which I can't seem to write data properly. If in flash memory I have a value 0x12345678 then after copying it to RAM I get 0xXXXX5678 (XXXX- random stuff that was already in RAM). This is happening only in this one particular region and it doesn't help at all what kind of pointers I am using to write to it (uint8_t*, uint32_t*). I have even tried creating a temporary value in RAM and copying to the problematic memory region and the same problem appeared. Memory sections seem to be aligned in linker script (. = ALIGN(4);) and memory addresses coming out of it used in copying seem to be aligned as well. The weird thing is that I can move the whole RAM memory in linker from 0x20000000 to 0x20000200 and the problem is moving to the same address related to the beginning of RAM.

I have replicated the same problem on the STM32F429 Discovery board with the same code.

I have found two other threads with exactly the same issue but with no answers.

https://community.arm.com/thread/8464

https://my.st.com/public/STe2ecommunities/mcu/Lists/stm81/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fstm81%2fMemory%20issue%20on%20STM8L151G6&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580001E3853D9DB932A46A3FE4CD15CAB46FB&currentviews=236

I am bit stuck over here and any help will be apprieciated.

#stm32-ram
10 REPLIES 10
Posted on December 15, 2015 at 18:36

I have found two other threads with exactly the same issue but with no answers.

Forums are filled with people who can't answer their own problems, and when they do figure stuff out often don't bother to post back. One of your cites is for a STM8 which is a wholly different compiler and chip architecture. The other really doesn't provide enough data to be able to actually replicate the issue by anyone else. I'd be very cautious of the IT command and it's ability to restart.

Are you doing this in assembler, or C? If C which version, and does turning off optimization impact things? What does the compiled code (assembler) look like?

If the issue moves with linker memory base it's honestly more suggestive of some other utilization of that memory area, check the .MAP, and check the stack location.

Can you provide an example that sufficiently demonstrates the problem to a third party?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 15, 2015 at 18:47

> specific memory address in RAM

Namely?

> it doesn't help at all what kind of pointers I am using to write to it (uint8_t*, uint32_t*)

How EXACTLY do you do the ''write to [RAM] using pointer''?

How do you verify the content of RAM?

> I have replicated the same problem on the STM32F429 Discovery board with the same code.

Can you post it?

JW

kalbar666
Associate II
Posted on December 16, 2015 at 10:53

My linker script:


/* Entry Point */

ENTRY(Reset_Handler)


/* Highest address of the user mode stack */

_estack = 0x2002FFFF; /* end of RAM */

/* Generate a link error if heap and stack don't fit into RAM */

_Min_Heap_Size = 0xA000; /* required amount of heap 40kB*/

_Min_Stack_Size = 0x2800; /* required amount of stack 10kB*/



/* Specify the memory areas */

MEMORY

{

FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K

RAM (xrw) : ORIGIN = 0x20000400, LENGTH = 192K

CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K

}



/* Define output sections */

SECTIONS

{

_isrVectorFlashB = LOADADDR(.isr_vector);


/* The startup code goes first into FLASH */

.isr_vector :

{

. = ALIGN(4);

_isrVectorRamB = .;


KEEP(*(.isr_vector)) /* Startup code */


. = ALIGN(4);

_isrVectorRamE = .;

} >RAM AT>FLASH



.startup :

{

. = ALIGN(4);

*(.text.Reset_Handler)

*(.text.copyFlashToRam) 

*(.text.copyFunction)

*(.text.fillZeroBss)

*(.glue_7) /* glue arm to thumb code */

*(.glue_7t) /* glue thumb to arm code */

. = ALIGN(4);

} >FLASH



_textFlashB = LOADADDR(.text);


.text :

{

. = ALIGN(4);

_textRamB = .;


*(.text) /* .text sections (code) */

*(.text*) /* .text* sections (code) */

*(.glue_7) /* glue arm to thumb code */

*(.glue_7t) /* glue thumb to arm code */

*(.eh_frame)


KEEP (*(.init))

KEEP (*(.fini))


. = ALIGN(4);

_etext = .; /* define a global symbols at end of code */

_textRamE = .;

} >RAM AT> FLASH



_rodataFlashB = LOADADDR(.rodata);


.rodata :

{

. = ALIGN(4);

_rodataRamB = .;


*(.rodata) /* .rodata sections (constants, strings, etc.) */

*(.rodata*) /* .rodata* sections (constants, strings, etc.) */

. = ALIGN(4);

_rodataRamE = .;

} >RAM AT> FLASH



_armExtabFlashB = LOADADDR(.ARM.extab);


.ARM.extab : { 

. = ALIGN(4);

_armExtabRamB = .;


*(.ARM.extab* .gnu.linkonce.armextab.*) 


. = ALIGN(4);

_armExtabRamE = .;

} >RAM AT> FLASH



_armFlashB = LOADADDR(.ARM);


.ARM : {

. = ALIGN(4);

_armRamB = .;

__exidx_start = .;


*(.ARM.exidx*)


__exidx_end = .;


. = ALIGN(4);

_armRamE = .;

} >RAM AT> FLASH



_preinitFlashB = LOADADDR(.preinit_array);


.preinit_array :

{

. = ALIGN(4);

_preinitRamB = .;


PROVIDE_HIDDEN (__preinit_array_start = .);

KEEP (*(.preinit_array*))

PROVIDE_HIDDEN (__preinit_array_end = .);


. = ALIGN(4);

_preinitRamE = .;

} >RAM AT> FLASH



_initFlashB = LOADADDR(.init_array);


.init_array :

{

. = ALIGN(4);

_initRamB = .;


PROVIDE_HIDDEN (__init_array_start = .);

KEEP (*(SORT(.init_array.*)))

KEEP (*(.init_array*))

PROVIDE_HIDDEN (__init_array_end = .);


. = ALIGN(4);

_initRamE = .;

} >RAM AT> FLASH



_finiFlashB = LOADADDR(.fini_array);


.fini_array :

{

. = ALIGN(4);

_finiRamB = .;


PROVIDE_HIDDEN (__fini_array_start = .);

KEEP (*(SORT(.fini_array.*)))

KEEP (*(.fini_array*))

PROVIDE_HIDDEN (__fini_array_end = .);


. = ALIGN(4);

_finiRamE = .;

} >RAM AT> FLASH



/* used by the startup to initialize data */

_sidata = LOADADDR(.data);

_dataFlashB = LOADADDR(.data);


/* Initialized data sections goes into RAM, load LMA copy after code */

.data : 

{

. = ALIGN(4);

_dataRamB = .;

_sdata = .; /* create a global symbol at data start */


*(.data) /* .data sections */

*(.data*) /* .data* sections */


. = ALIGN(4);

_edata = .; /* define a global symbol at data end */

_dataRamE = .;

} >RAM AT> FLASH


_siccmram = LOADADDR(.ccmram);

_ccramFlashB = LOADADDR(.ccmram);


.ccmram :

{

. = ALIGN(4);

_ccmRamB = .;

*(.ccmram)

*(.ccmram*)


. = ALIGN(4);

_ccmRamE = .;

} >CCMRAM AT> FLASH



/* Uninitialized data section */

. = ALIGN(4);

.bss :

{

/* This is used by the startup in order to initialize the .bss secion */

_sbss = .; /* define a global symbol at bss start */

__bss_start__ = _sbss;

_bssRamB = .;

*(.bss)

*(.bss*)

*(COMMON)


. = ALIGN(4);

_ebss = .; /* define a global symbol at bss end */

__bss_end__ = _ebss;

_bssRamE = .;

} >RAM



/* User_heap_stack section, used to check that there is enough RAM left */

._user_heap_stack :

{

. = ALIGN(4);

PROVIDE ( end = . );

PROVIDE ( _end = . );

. = . + _Min_Heap_Size;

. = . + _Min_Stack_Size;

. = ALIGN(4);

} >RAM




/* Remove information from the standard libraries */

/DISCARD/ :

{

libc.a ( * )

libm.a ( * )

libgcc.a ( * )

}


.ARM.attributes 0 : { *(.ARM.attributes) }

}

kalbar666
Associate II
Posted on December 16, 2015 at 10:55

Startup file:


.section .text.Reset_Handler

.weak Reset_Handler

.type Reset_Handler, %function

Reset_Handler:

ldr sp, =_estack /* set stack pointer */


//copying procedures from flash to ram

bl copyFlashToRam


//clearing bss section

bl fillZeroBss


/* Call the clock system intitialization function.*/

bl SystemInit

/* Call static constructors */

bl __libc_init_array

/* Call the application's entry point.*/

bl main

bx lr 

.size Reset_Handler, .-Reset_Handler

And copying functions:


/**

* @brief Function is copying memory from FLASH to RAM.

*

* @param ramB: beginning of ram where flash memory should be stored

* @param flashB: beginning of copied flash memory

* @param flashE: end of copied flash memory

*

* @retval None

*/

__attribute__ ((__section__(''.startup'')))

void copyFunction(volatile uint32_t * ramB,

volatile uint32_t * ramE,

volatile uint32_t * flashB){


unsigned int ctr = 0;

uint32_t temp = 0xDEADBEEF;


while(ramB < 
ramE
){


//copy memory

*ramB = *flashB;


//at address 0x20000604 copying fails, therefore breakpoint

if(ramB == (volatile uint32_t *)(0x20000600)){

asm(''nop'');

}


if(*ramB != *flashB){

//I am trying to play with different sources of memory to copy from (FLASH, RAM) to no avail

asm(''nop'');

*
ramB
= 
0xDEADBEEF
;

*
ramB
= 
temp
;

ctr++;

}else{

//everything went correct, therefore keep copying

ramB++;

flashB++;

ctr
= 
0
;

}


if(ctr > 2){

//I give up, just get through with it

asm(''nop'');

ramB++;

flashB++;

}

}

}



/**

* @brief Function is copying memory from FLASH to RAM.

* @note This function is being called from startup file.

* @param None

* @retval None

*/

__attribute__ ((__section__(''.startup''))) void copyFlashToRam(void){


copyFunction(&_isrVectorRamB, &_isrVectorRamE, &_isrVectorFlashB);

copyFunction(&_textRamB, &_textRamE, &_textFlashB);

copyFunction(&_rodataRamB, &_rodataRamE, &_rodataFlashB);

copyFunction(&_armExtabRamB, &_armExtabRamE, &_armExtabFlashB);

copyFunction(&_armRamB, &_armRamE, &_armFlashB);

copyFunction(&_preinitRamB, &_preinitRamE, &_preinitFlashB);

copyFunction(&_initRamB, &_initRamE, &_initFlashB);

copyFunction(&_finiRamB, &_finiRamE, &_finiFlashB);


copyFunction(&_dataRamB, &_dataRamE, &_dataFlashB);


copyFunction(&_ccmRamB, &_ccmRamE, &_ccramFlashB);

}

kalbar666
Associate II
Posted on December 16, 2015 at 11:01

Section of interest from output.map:


.text 0x200005ac 0x808c load address 0x080003a8

0x200005ac . = ALIGN (0x4)

0x200005ac _textRamB = .

*(.text)

.text 0x200005ac 0x54 c:/eclipse/plugins/fr.ac6.mcu.externaltools.arm-none.win32_1.1.0.201503101257/tools/compiler/bin/../lib/gcc/arm-none-eabi/4.8.4/armv7e-m/fpu/crtbegin.o

*(.text*)

.text.main 0x20000600 0x60 ./src/main.o

0x20000600 main

.text.SystemClock_Config

0x20000660 0x98 ./src/main.o

0x20000660 SystemClock_Config

.text.MX_GPIO_Init

0x200006f8 0x1fc ./src/main.o

.text.safeFree

0x200008f4 0x40 ./src/privateDefines.o

0x200008f4 safeFree

.text.safeMalloc

Code of main() function in flash before copying:


080003fc: push {r7, lr}

080003fe: sub sp, #8

08000400: add r7, sp, #0

08000402: nop 

08000404: nop 

08000406: bl 0x8003cb8

0800040a: bl 0x800045c

0800040e: bl 0x8000778

08000412: b.n 0x8000416

Code of main() in RAM after copying:


main:

20000600: push {r7, lr}

20000602: sub sp, #8

20000604: add r7, sp, #0

76 asm(''nop'');

20000606: movs r4, #5

77 asm(''nop'');

20000608: nop 

82 HAL_Init();

2000060a: bl 0x20003ebc <
HAL_Init
>

86 SystemClock_Config();

2000060e: bl 0x20000660 <
SystemClock_Config
>

90 __SVC();

20000612: bl 0x2000097c <
__SVC
>

91 while((__get_CONTROL() & 0x01) != 0)

20000616: b.n 0x2000061a <
main
+26>

94 asm volatile (''NOP'');

kalbar666
Associate II
Posted on December 16, 2015 at 11:04

In the output from disassembly there is clearly a bug at line 6, where should be NOP not MOVS command.

I am not using any optimisations, I am using GCC 4.8.4 toolchain for ARM. This is a disassembled copyFunction() (maybe it will be of some help):


copyFunction:

080001d1: push {r7}

080001d3: sub sp, #28

080001d5: add r7, sp, #0

080001d7: str r0, [r7, #12]

080001d9: str r1, [r7, #8]

080001db: str r2, [r7, #4]

60 unsigned int ctr = 0;

080001dc: movs r3, #0

080001de: str r3, [r7, #20]

61 uint32_t temp = 0xDEADBEEF;

080001e0: ldr r3, [pc, #108] ; (0x8000250 <
copyFunction
+128>)

080001e2: str r3, [r7, #16]

63 while(ramB < 
ramE
){

080001e4: b.n 0x800023e <copyFunction+110>

66 *ramB = *flashB;

080001e6: ldr r3, [r7, #4]

080001e8: ldr r2, [r3, #0]

080001ea: ldr r3, [r7, #12]

080001ec: str r2, [r3, #0]

69 if(ramB == (volatile uint32_t *)(0x20000600)){

080001ee: ldr r2, [r7, #12]

080001f0: ldr r3, [pc, #96] ; (0x8000254 <
copyFunction
+132>)

080001f2: cmp r2, r3

080001f4: bne.n 0x80001f8 <
copyFunction
+40>

70 asm(''nop'');

080001f6: nop 

73 if(*ramB != *flashB){

080001f8: ldr r3, [r7, #12]

080001fa: ldr r2, [r3, #0]

080001fc: ldr r3, [r7, #4]

080001fe: ldr r3, [r3, #0]

08000200: cmp r2, r3

08000202: beq.n 0x800021a <
copyFunction
+74>

75 asm(''nop'');

08000204: nop 

76 *ramB = 0xDEADBEEF;

08000206: ldr r3, [r7, #12]

08000208: ldr r2, [pc, #68] ; (0x8000250 <
copyFunction
+128>)

0800020a: str r2, [r3, #0]

77 *ramB = temp;

0800020c: ldr r3, [r7, #12]

0800020e: ldr r2, [r7, #16]

08000210: str r2, [r3, #0]

78 ctr++;

08000212: ldr r3, [r7, #20]

08000214: adds r3, #1

08000216: str r3, [r7, #20]

08000218: b.n 0x800022a <
copyFunction
+90>

81 ramB++;

0800021a: ldr r3, [r7, #12]

0800021c: adds r3, #4

0800021e: str r3, [r7, #12]

82 flashB++;

08000220: ldr r3, [r7, #4]

08000222: adds r3, #4

08000224: str r3, [r7, #4]

83 ctr = 0;

08000226: movs r3, #0

08000228: str r3, [r7, #20]

86 if(ctr > 2){

0800022a: ldr r3, [r7, #20]

0800022c: cmp r3, #2

0800022e: bls.n 0x800023e <
copyFunction
+110>

88 asm(''nop'');

08000230: nop 

89 ramB++;

08000232: ldr r3, [r7, #12]

08000234: adds r3, #4

08000236: str r3, [r7, #12]

90 flashB++;

08000238: ldr r3, [r7, #4]

0800023a: adds r3, #4

0800023c: str r3, [r7, #4]

63 while(ramB < 
ramE
){

0800023e: ldr r2, [r7, #12]

08000240: ldr r3, [r7, #8]

08000242: cmp r2, r3

08000244: bcc.n 0x80001e6 <copyFunction+22>

93 }

08000246: adds r7, #28

08000248: mov sp, r7

0800024a: ldr.w r7, [sp], #4

0800024e: bx lr

08000250: bkpt 0x00ef

08000252: ; <
UNDEFINED
> instruction: 0xdead

08000254: lsls r0, r0, #24

08000256: movs r0, #0

Posted on December 16, 2015 at 13:09

Did you try this at default clock i.e. HCLK source HSI, no PLL?

JW
kalbar666
Associate II
Posted on December 16, 2015 at 13:13

This is just after power up on its default settings, without touching clocks, peripherals or anything chip related.

kalbar666
Associate II
Posted on December 16, 2015 at 15:41

I have got answer from other forum and it looks like that memory gets corrupted only at addresses, where breakpoints are being placed! Good thing is that it is not a code related thing, and code can work properly, but how to make a debugging in such an environment?