cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f072 can not remap memory: SYSCFG CFGR1 has no effect

Florian Delizy
Associate II
Posted on November 01, 2017 at 18:44

Hi,

I am trying to write a generic bootloader for STM32F072, I read countless reports on this forum (and other on the Internet), that basically states the following procedure:

  1. disable interrupts
  2. Install the partition ISR (first 48 words) into SRAM base (0x2000000)
  3. use SYSCFG CFGR1 to remap 0x0 to point to SRAM base (0x20000000)
  4. read the 2nd word of the ISR and jump to it (application will have to re-enable interrupts

So that is basically what I am doing, but after checking using a debug probe (JLink), it seems that even if I remap the 0x0 to point to SRAM, in fact, the setting has no effect. Here is the content of a quick debug session (using gdb):

gdb$ x /1xw 0x40010000
0x40010000:0x00000003
gdb$ x /48xw 0x0
0x0:0x200040000x08000e290x080005090x0800050b
0x10:0x000000000x000000000x000000000x00000000
0x20:0x000000000x000000000x000000000x08000e75
0x30:0x000000000x000000000x08000e750x0800050f
0x40:0x08000e750x08000e750x08000e750x08000e75
0x50:0x08000e750x08000e750x08000e750x08000e75
0x60:0x08000e750x08000e750x08000e750x08000e75
0x70:0x08000e750x08000e750x08000e750x08000e75
0x80:0x08000e750x08000e750x08000e750x08000e75
0x90:0x08000e750x08000e750x08000e750x08000e75
0xa0:0x08000e750x08000e750x08000e750x08000e75
0xb0:0x08000e750x08000e750x08000e750x08000e75
gdb$ x /48xw 0x20000000
0x20000000:0x200040000x08018d290x0800c2510x0800c25b
0x20000010:0x000000000x000000000x000000000x00000000
0x20000020:0x000000000x000000000x000000000x080020c1
0x20000030:0x000000000x000000000x080021370x08002143
0x20000040:0x08018d750x08018d750x08018d750x08018d75
0x20000050:0x08018d750x080031f50x080031d50x080031a9
0x20000060:0x08018d750x08018d750x08018d750x08018d75
0x20000070:0x08018d750x08018d750x08018d750x08018d75
0x20000080:0x08018d750x08018d750x08018d750x08018d75
0x20000090:0x08018d750x08018d750x08018d750x08018d75
0x200000a0:0x08018d750x08018d750x08018d750x08018d75
0x200000b0:0x08018d750x08018d750x55aa55aa0x55aa55aa�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

So basically as you can see in this copy/paste the SYSCFG CFGR1 two LSB bits are 1 (so 0x0 should point to SRAM), but the content of 0x0 and 0x20000000 addresses are different ?? How could that be?

Here is the relevant part of the code that set the CFGR1 bits:

 __disable_irq();
 *sramISR = *isr; // copy isr to sram ISR (0x20000000)
 __HAL_RCC_AHB_FORCE_RESET();
 __HAL_RCC_SYSCFG_CLK_ENABLE();
 __HAL_RCC_AHB_RELEASE_RESET();
 __HAL_SYSCFG_REMAPMEMORY_SRAM();
 // Breakpoint right here to check in gdb.
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

What am I doing wrong? any insight would be greatly appreciated.

#remap #memory-remap #stm32f7-hal #embedded-bootloader #stm32f07
12 REPLIES 12
Steve Krattiger
Associate III
Posted on November 02, 2017 at 18:05

Hi Florian,

Try the following.   Add the __DSB() and __ISB() statements around your remap call.   This was suggested to me by someone in the community here, and got my code working on an STM32L052 earlier this year.

  // Remap system flash to boot area

  __DSB();

  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();

  __DSB();

  __ISB();

-SteveK

Posted on November 02, 2017 at 18:06

This worked on my STM32F072B-DISCO

int main(void)

{

memcpy((void *)0x20000000, (void *)0x08000000, 0xC0);

*((uint32_t *)0x20000000) = 0x20001234; // Something to recognize

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

SYSCFG->CFGR1 = 3;

/* Infinite loop */

while (1)

{

}

}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Florian Delizy
Associate II
Posted on November 02, 2017 at 18:16

@Steve Krattiger: I just tried to add __DSB()/__ISB() call but no luck.

@Clive One: thanks, but I use only the HAL, I guess that RCC_APB2PeriphClockCmd must be part of the MX lib maybe?

Another very strange thing, after I jump at the right address, the application dies in a HardFault, but the handler called is the correct one … (in the application space, not in the bootloader space).

It is as if the vector read during an exception would be a different one than outside of exception code…  Could it be the debug probe not reading properly the memory or something?

To try this, I added a simple code that checks that *(uint32_t*) 0x04 == *(uint32*) 0x20000004 but that code also fails (so the uC does seem to read the same thing as the probe). 

I am quite lost there, any other suggestion?

Posted on November 02, 2017 at 18:58

 ,

 ,

Yeah very strange, perhaps it is some GNU/OCD probe nonsense, I'm using Keil.

I'm a SPL proponent ,

RCC->,APB2ENR |= RCC_APB2ENR_SYSCFGEN, // equivalent ,

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE),

Clock must be enabled for SYSCFG registers to function

I'd perhaps cross check what hardware I've got mounted on the board.

//****************************************************************************

void CORECheck(void) //

mailto:sourcer32@gmail.com

 ,

{

 ,

uint32_t cpuid = SCB->,CPUID,

 ,

uint32_t var, pat,

printf('CPUID %08X DEVID %03X\n', cpuid, DBGMCU->,IDCODE &, 0xFFF),

pat = (cpuid &, 0x0000000F),

 ,

var = (cpuid &, 0x00F00000) >,>, 20,

if ((cpuid &, 0xFF000000) == 0x41000000) // ARM

 ,

{

 ,

switch((cpuid &, 0x0000FFF0) >,>, 4)

 ,

{

 ,

case 0xC20 : printf('Cortex M0 r%dp%d\n', var, pat), break,

 ,

case 0xC60 : printf('Cortex M0+ r%dp%d\n', var, pat), break,

 ,

case 0xC21 : printf('Cortex M1 r%dp%d\n', var, pat), break,

 ,

case 0xC23 : printf('Cortex M3 r%dp%d\n', var, pat), break,

 ,

case 0xC24 : printf('Cortex M4 r%dp%d\n', var, pat), break,

 ,

case 0xC27 : printf('Cortex M7 r%dp%d\n', var, pat), break,

default : printf('Unknown CORE\n'),

 ,

}

 ,

}

 ,

else

 ,

printf('Unknown CORE IMPLEMENTER\n'),

 ,

}

//****************************************************************************

STM32F072B

CPUID 410CC200 DEVID 448

Cortex M0 r0p0

Check also the startup code, here it remaps flash..

, Reset handler routine

 ,

Reset_Handler PROC

 ,

EXPORT Reset_Handler [WEAK]

 ,

IMPORT __main

 ,

IMPORT SystemInit

LDR R0, =__initial_sp , set stack pointer

 ,

MSR MSP, R0

,,Check if boot space corresponds to test memory

LDR R0,=0x00000004

 ,

LDR R1, [R0]

 ,

LSRS R1, R1, ♯ 24

 ,

LDR R2,=0x1F

 ,

CMP R1, R2

 ,

 ,

BNE ApplicationStart

 ,

 ,

,, SYSCFG clock enable

 ,

 ,

LDR R0,=0x40021018

 ,

LDR R1,=0x00000001

 ,

STR R1, [R0]

 ,

 ,

,, Set CFGR1 register with flash memory remap at address 0

LDR R0,=0x40010000

 ,

LDR R1,=0x00000000

 ,

STR R1, [R0]

 ,

ApplicationStart

 ,

LDR R0, =SystemInit

 ,

BLX R0

 ,

LDR R0, =__main

 ,

BX R0

 ,

ENDP
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Florian Delizy
Associate II
Posted on November 02, 2017 at 20:10

Well in case of an exception, LR is a not the return pointer. It is not set by the SVC instruction, in fact the exception creates a stack on its own pointed by PSP. al the return information is pushed there.

Posted on November 02, 2017 at 19:31

I checked the startup code (assembly) and SystemInit, nothing sets the SYSCFG register.

I would vote for a JLink probe nonsense if the code executed on the board did not break at the point where the check happened. Nothing on the connected hw can cause anything with an internal register, so that is also clearly an issue with my code (or with the uC but I doubt it very much).

looking at the code you were shown,

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

is the exact equivalent of:

__HAL_RCC_SYSCFG_CLK_ENABLE();

so the clock is ok. (Also I can read the CFGR1 value, and it did change from 0 to 0x3, so the writing is probably happening just fine).

I tried to do the switch as the first instruction of my main() but still no improvement. What I can not explain is that.

Investigating further, after the application jump, the application fails at the first svc call (it seems that PSP is not set properly for some reason. It is not set to the $pc but to 0xfffffffc instead). I wonder what it has to do with the remap (if anything). I will have to dig more on how PSP is set to see if that can be linked.

Posted on November 02, 2017 at 19:36

LR is a special value, you'd have to fish the PC off the stack.

Don't transfer control to the app from an IRQ or System Handler 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 02, 2017 at 19:50

Yeah, I saw that everywhere, I am not transferring control from an IRQ/System Handler, directly from the main loop (in fact in the first calls).

The process goes like this:

[System boot] -> call Reset_Handler -> [Init RCC] -> main() -> transfer.

Not sure what you mean for LR, yeah I know it is a special value and the PC is fetched off the stack, but that should be pointed by PSP right? and PSP is pointing to -4 which is odd… RTX SVC_Handler breaks when trying to retrieve the SVC♯ off the PSP value:

MRS R0,PSP // Get PSP (value is 0xfffffffc)

LDR R1,[R0,&sharp24] // Load saved PC from stack (r1 is now 0x0)

SUBS R1,R1,&sharp2 // Point to SVC instruction (r1 is now -2: 0xfffffffe)

LDRB R1,[R1] // Load SVC number <- dies here.

it seems that the push caused by the SVC instruction (which really should be pushing an exception stack) actually pushes anything but that :/.

Maybe the jump messed up with that but I feel like this is very unlikely :/

Posted on November 02, 2017 at 19:55

LR is the link register, don't you need to use that to determine WHICH stack the frame is on?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..