Skip to main content
Florian Delizy
Associate
November 1, 2017
Question

stm32f072 can not remap memory: SYSCFG CFGR1 has no effect

  • November 1, 2017
  • 5 replies
  • 3441 views
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
This topic has been closed for replies.

5 replies

Steve Krattiger
Associate II
November 2, 2017
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

Tesla DeLorean
Guru
November 2, 2017
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 VenmoUp vote any posts that you find helpful, it shows what's working..
Florian Delizy
Associate
November 2, 2017
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?

Tesla DeLorean
Guru
November 2, 2017
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 VenmoUp vote any posts that you find helpful, it shows what's working..
Florian Delizy
Associate
November 2, 2017
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.

Florian Delizy
Associate
November 2, 2017
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.

Tesla DeLorean
Guru
November 2, 2017
Posted on November 02, 2017 at 20:25

Seems I have to uphill ski this...

The LR contains a special value EXC_RETURN, part of that value indicates which stack is being used, thus you must inspect it to determine where to look, not hard code PSP.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Babefdjc.html

 

What value is in LR at the SVC_Handler entry?

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Florian Delizy
Associate
November 3, 2017
Posted on November 03, 2017 at 02:33

ok, after reading this:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Babefdjc.html

 

I understand what you told me, it gives you the stack type, not the return address. (sorry for my confusion).

and in that specific case, the exception should get the stack from MSP not PSP. (Also, I don't hardcode PSP in any way, this is standard cmsis RTX code that you see here.)

Anyway, to answer: stepping instruction by instruction, right after the SVC instruction, lr becomes 0xfffffff9 (thread info, stack on MSP).

The SVC_HANDLER code from RTX is trying to fetch the stack off PSP instead. Since I did not modify this, there must be a configuration somewhere that was changed to get this stack from the wrong place. How do you change this? (must be something I did not deinit or set wrong in the bootloader then). (I am checking where the control could have been set wrong in the begining).

Florian Delizy
Associate
November 3, 2017
Posted on November 03, 2017 at 03:42

After some check, I found that I inverted by accident two calls so that I called an svc before callingosKernelInitialize() it was causing the control to be set wrong. It now crashes somewhere else (randomly) and it looks like an interrupt issue again.

To answer the initial question, since the svc call actually jumps to the right address (stored in RAM not on flash 0x8000000), it seems that really the interrupt vector had been remapped (at least the core takes it that way), but debugger and thread program still read 0x0 to be pointed at the flash.

My MCU seems to be in an intermediate state where the exception really reads 0x0 at the place it should be mapped to (RAM start), but the rest of the execution (and the debug probe memory reading) seems to ignore the mapping. This is very odd, I did not think it was possible…

Is there anything that could cause this?

My jump code now looks like this:

 __disable_irq();
 // Must reset al the EXTI* registers to 0
 NVIC_DisableIRQ(SysTick_IRQn);
 for (int i=0; i <32; i++) {
 NVIC_DisableIRQ(static_cast<IRQn_Type>(i));
 NVIC_ClearPendingIRQ(static_cast<IRQn_Type>(i));
 }
 // Prepare for flash remap depending on the address start
 __DSB();
 __ISB();
 __HAL_RCC_AHB_FORCE_RESET();
 __HAL_RCC_SYSCFG_CLK_ENABLE();
 __HAL_RCC_AHB_RELEASE_RESET();
 __DSB();
 switch (reinterpret_cast<uintptr_t >(isr)) {
 case FLASH_BASE:
 __HAL_SYSCFG_REMAPMEMORY_FLASH();
 break;
 case SYSTEM_FLASH_BASE:
 __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
 break;
 case SRAM_BASE:
 __HAL_SYSCFG_REMAPMEMORY_SRAM();
 break;
 default:
 *sramISR = *isr;
 __HAL_SYSCFG_REMAPMEMORY_SRAM();
 break;
 }
 __DSB();
 __ISB();
 HAL_DeInit();
 HAL_RCC_DeInit();

 __enable_irq();
 __set_MSP(isr->_estack);
 __DSB();
 __ISB();
 // Then perform the jump
 asm volatile ( 
 'bx %0'
 : /* no output */ 
 : 'r' (isr->Reset_Handler)
 : /* no clobber */
 );
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

The bootloader does not use Rtx (so does not modify the control SysTick->CTRL register).

The code now fails on a Hard Fault in the application __svcKernelStart, but I can not reproduce it when stepping over with the debugger, (it fails somewhere else instead)…

Must still be something wrong in the bootloader, but not quite sure what just yet.