cancel
Showing results for 
Search instead for 
Did you mean: 

Bootloader. Load program with stack on CCM

Posted on October 26, 2015 at 20:39

This code snippet is from STM32 IAP example. It is common for most bootloaders.

// Check if valid stack address (RAM address) then jump to user application

    if( ((*(__IO uint32_t*)MAIN_PROGRAM_START_ADDRESS) & 0x2FFE0000 ) == 0x20000000 )

I can't understand what is

0x2FFE0000

.

It works fine while stack is located in default RAM. But I have relocate it to core-coupled memory (C

CM

). The next snippet is part of mdk-arm scatter file:

    RW_IRAM2 0x10000000 0x00010000  {  ; Core-coupled memory (CCM). No DMA avaliable.

        .ANY (CCM_DATA)

        startup_stm32f4xx.o (STACK)     ; reallocating the STACK to the CCM

    }

How should 1st snippet be changed?

#ccm #stack #bootloader
7 REPLIES 7
Posted on October 26, 2015 at 21:46

It's using a mask to see if the stack falls within 128KB of SRAM at 0x20000000

It's a bit of a half-assed test, and you can change it too whatever you want, and will work for YOUR design choices. Ideally it should just make sure it is 32-bit aligned and not 0xFFFFFFFF (ie erased state of FLASH)

// Check if valid stack address (RAM address) then jump to user application

    if( ((*(__IO uint32_t*)MAIN_PROGRAM_START_ADDRESS) & 0xFFFE0000 ) == 0x10000000 )

As the value 0x10010000 is valid for 64KB of CCM RAM, as the stack is auto-decremented before use.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 27, 2015 at 12:54

I dont know any reason to put main stack into else address than end of RAM. Please explain. So my code will look like:

     uint32_t stack_pointer = *(__IO uint32_t*)MAIN_PROGRAM_START_ADDRESS;

     if( stack_pointer == 0x10010000 || stack_pointer == 0x20020000 )
Posted on October 27, 2015 at 16:54

Pretty sure the way Keil places the stack, it's *not* a the end of the load region, but rather immediately after the statics and heap.

Look at the .MAP file.

I'm not here to argue about how the tools work, or how you think or would like them to work. The purpose of the test is to sanity check that the image will start without faulting the processor immediately.

Read the manuals. Understand the processor. Make your own determinations.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 27, 2015 at 22:41

Your right. So resuming

     volatile uint32_t *stack_pointer = (volatile uint32_t*)MAIN_PROGRAM_START_ADDRESS;

     if( *stack_pointer &

0x2FFE0000 == 0x20000000

)

the same as

    if( 0x20000000<=*stack_pointer &&

*stack_pointer

<=0x20020000 )

I think second snippet is more clear to understand without additional comments, but first is faster to execute.

Posted on October 27, 2015 at 23:08

O. NO. Playing with bit-masks is not good idea. Big chance to make mistake

0x2FFE_0000 & 7000_0000 = 0x2000_0000  // will pass. NOT a RAM

0xFFFE_0000 & 1002_0000 = 0x1000_0000  // will pass. NOT a RAM

Mask

0x2FFE_0000

should be changed to

0xFFFE_0000

to check 128k of memory and

0xFFFF_0000

to check 64k of CCM RAM.

Code in example is WRONG. And it does not check what you say properly!

I prefer more clear code for human but not so fast to execute:

if( ((0x10000000 <= *stack_pointer && *stack_pointer < 0x10010000)  // in CCM RAM region

        || (0x20000000 <= *stack_pointer && *stack_pointer < 0x20020000))  // in regular RAM region

        && *stack_pointer % 4 == 0 )  // is 32-bit word aligned

I believe somebody will find it useful.

UPD. Fixed code.

Posted on October 28, 2015 at 00:20

0xFFFE_0000 & 1002_0000 = 0x1002_0000

I prefer to sign the image, and check that it's intact, before jumping to it.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 28, 2015 at 12:43

{
unsigned long initsp =*stack_pointer;
if ( ((initsp & 3) == 0) && // is 32-bit word aligned
(((initsp > 0x10000000) && (initsp <= 0x10010000)) || // in CCM RAM region 64KB
((initsp > 0x20000000) && (initsp <= 0x20020000))) ) // in regular RAM region 128KB
{
// Transfer Control
}
}

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