Bootloader running from Flash

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
User8620
Level 2
Level 2
Hello,

My questioon is: Is it possible to run a Bootloader from flash memory?

My goal is to seperate the flash into 2 parts. One for the application and one for the Bootloader.
The bootloader should be able to recieve a program via CAN and write it into the application part of the flash.

In the ASC Bootloader example, it says, that the bootloader can only run from PSRAM. But the PSRAM is volatile, so the bootloader program has to be downloaded via the ASC or CAN BSL mode. (is that correct?)

My problem is that the Boot pins are not accesible later. So my bootloader has to be on the device from the beginning.

If it is possible, can I use the given functions from the ASC example to program the flash?

Thanks for you help.
0 Likes
78 Replies
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
Hi Oliver,

There is only 1 PMU (PMU0) which contain one PFLASH bank for XMC4500, thus it is not possible to program the flash at the same time while running the boot loader code.

Whereas for TriCore TC1798, there are 2 PMU (PMU0 and PMU1), so it is possible to locate the boot loader to PMU1 and flash program the PMU0.

Best Regards
Travis
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
oliver.blasius wrote:
Hello,

My questioon is: Is it possible to run a Bootloader from flash memory?

My goal is to seperate the flash into 2 parts. One for the application and one for the Bootloader.
The bootloader should be able to recieve a program via CAN and write it into the application part of the flash.

In the ASC Bootloader example, it says, that the bootloader can only run from PSRAM. But the PSRAM is volatile, so the bootloader program has to be downloaded via the ASC or CAN BSL mode. (is that correct?)

Travis: This is correct. The startup software which is factory programmed will detect boot pin status and transfer the boot loader code from the PC via ASC/CAN to the XMC PSRAM. After transfer the CPU will execute instruction from the PSRAM.

My problem is that the Boot pins are not accesible later. So my bootloader has to be on the device from the beginning.

Travis: It's OK. So you want to do flash programming at run time? eg. If you receive an instruction from CAN bus to start flash programming. You can embedded the bootloader into flash and copy to PSRAM. However you need a customize PC flash programming software to take care of the downloading of the hex code.

If it is possible, can I use the given functions from the ASC example to program the flash?

Travis: Maybe..

Thanks for you help.


Hi oliver,

Pls see my reply in red.
0 Likes
User8620
Level 2
Level 2
Thanks for the reply. It already helped me a lot.
Are there any examples available for copying from flash to PSRAM? or something similar?
And how exactly can I store the Bootloader on the flash?

Edit: I am using an XMC4500. I forgot to mention that in my opening post.
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
This development is quite tricky, however I am not discouraging you from doing so.

First of all you need to build a loader which is able to communicate with your host PC for hex downloading and also execute flash command instruction. The loader needs to be mapped to PSRAM during development stage. Once the loader software is stable, which means you can flash program the XMC successfully. Then the next thing you need to do is to convert the loader software into a const array from the hex file.

So during XMC run time, you can copy the const array (loader software) into RAM and start executing the loader software.
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
0 Likes
User6793
Level 4
Level 4
You don't need to have your whole booter in PSRAM, only the Flash002_* routines needed for erase & program.
Use __attribute__ ((section (".text.fastcode"))) for the methods to be copied to RAM by the .startup code.

You can use a similar approach in your app, so that it can load a new booter.

We have had good experience with the ABM fallback mode in BMI boot mode, keeping 2 copies of the booter if the update of the primary boot image is interrupted.
We keep our primary booter @0x0C000000 (loaded by JTAG in production), fallback booter @0x0C010000 and the application @0x0C020000.
Loading is done via a proprietary CAN protocol.
0 Likes
User8620
Level 2
Level 2
Thanks for the replies.
I already started to build a loader which communicates with the host via CAN. I am trying to use functions from the ASC bootloader example as much as possible.
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
OMR wrote:
You don't need to have your whole booter in PSRAM, only the Flash002_* routines needed for erase & program.
Use __attribute__ ((section (".text.fastcode"))) for the methods to be copied to RAM by the .startup code.

You can use a similar approach in your app, so that it can load a new booter.

We have had good experience with the ABM fallback mode in BMI boot mode, keeping 2 copies of the booter if the update of the primary boot image is interrupted.
We keep our primary booter @0x0C000000 (loaded by JTAG in production), fallback booter @0x0C010000 and the application @0x0C020000.
Loading is done via a proprietary CAN protocol.


Hi OMR,

Can you share how did you actually mapped the ABM header 0 to address 0x0C00FFE0?

I created a ABM header table as shown below below

const uint32_t ABM0[5] = { .............};

Best Regards
Travis
0 Likes
User6793
Level 4
Level 4
I just flashed it after generating it:

const uint32_t ABM0_HEADER_ADDRESS = 0x0c00ffe0;

unsigned int abm0[ABM_HEAD_WORDS];

if (sanityCheck(BOOT_START_ADDRESS)) {
unsigned char tmpBuf[FLASH002_PAGE_SIZE]; // minimum number of bytes to FLASH
Flash *flash = Flash::getInstance();

memcpy(tmpBuf, (unsigned char *)ABM0_BUFFER_ADDRESS, FLASH002_PAGE_SIZE); // copy flash contents into buffer

abm0[0] = ABM_MAGIC_KEY; // magic key
abm0[1] = BOOT_START_ADDRESS; // start address of code
abm0[2] = ABM_DEFAULT_SIZE; // Application length
abm0[3] = crc32Gen((unsigned int *)BOOT_START_ADDRESS, ABM_DEFAULT_SIZE); // CRC32 for application length
abm0[4] = crc32Gen(abm0, ABM_HEAD_SIZE-4); // CRC32 for above 4

memcpy(tmpBuf+0xe0, abm0, ABM_HEAD_SIZE); // copy ABM data into tmpBuf

// Program header in FLASH
if (flash->write((unsigned int)ABM0_BUFFER_ADDRESS, (unsigned char *)&tmpBuf, FLASH002_PAGE_SIZE) != 0) {
printf("\nFLASH write failed!\n");
return;
}
else {
if (flash->writeEnd() != 0) { // make sure last block is written to FLASH
printf("FLASH end write failed\n");
return;
}
else {
printf("\nABM0 header FLASHed OK\n");
setBMIWord();
}
}
return; // never copy freshly loaded primary booter as fallback, without at least one reset in between (in effect do a test run of the new booter!)
}
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
Hi OMR,

Thanks for the sharing. Do you run these code in the RAM?

Best Regards
Travis
0 Likes
User6793
Level 4
Level 4
The code I posted runs in FLASH, but the following functions in the FLASH0002.c app has the __attribute__ ((section (".text.fastcode"))) applied so that those FLASH routines runs from RAM:

status_t Flash002_EraseSector (uint32_t Address)
status_t Flash002_WritePage (uint32_t Address, const uint32_t pBuf[])
status_t Flash002_EraseUCB(uint32_t UserLevel)
status_t Flash002_DisableGlobalReadProtection(uint32_t PW0, uint32_t PW1)
status_t Flash002_DisableSectorWriteProtection(uint32_t UserLevel, uint32_t PW0, uint32_t PW1)
status_t Flash002_ResumeProtection()
status_t Flash002_ConfigureProtection(uint32_t UserLevel, uint32_t PW0, uint32_t PW1, FLASH002ProtectionFlags_Type ProtectionFlags)
status_t Flash002_VerifyProtection(uint32_t UserLevel, uint32_t PW0, uint32_t PW1, FLASH002ProtectionFlags_Type ProtectionFlags)
status_t Flash002_ConfigureBMI (const FLASH002BMIString_Type *BMIString)
status_t Flash002_ConfirmProtection (uint32_t UserLevel)

That is all of them I think 🙂
The .cstartup code copies all functions with fastcode attribute to RAM during startup.
0 Likes
User8620
Level 2
Level 2
Hi,

I successfully modified the ASC Bootloader example and it now programs the flash via a CAN protocol. (it still needs a lot of improvements, but works for now).

Now I have another question: Is it possible to have 2 programs in two separate parts of the flash?
I always want to make sure that I have a valid program. So if I have a valid program on the first part of the flash, I would program the second part of the flash with new code, validate the code and then start running the new code. In the next flashing process I would do the same with the first part of the flash.

Thanks,
Oliver
0 Likes
User6793
Level 4
Level 4
As I said in post #7:

We have had good experience with the ABM fallback mode in BMI boot mode, keeping 2 copies of the booter if the update of the primary boot image is interrupted.
We keep our primary booter @0x0C000000 (loaded by JTAG in production), fallback booter @0x0C010000 and the application @0x0C020000.


So yes, it is possible 🙂

Using the ABM fallback mode will let the ROM loader verify the crc32 of the first booter, and if it fails, it will automatically try the second one.
The boot code can jump to any code in the flash using code like this:

		PPB->VTOR = APP_START_ADDRESS;
asm(
"ldr sp, [%0]\n\t"
"ldr r0, [%0, #4]\n\t"
"bx r0"
:
: "r" (APP_START_ADDRESS)
:);


The code at APP_START_ADDRESS is 100% self contained, its memory layout starting with its own vector table. Of cause, any HW already set up will maintain its settings as the CPU is not reset.
It is also a good idea to disable any interrupts before making the switch.
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
Just a word of caution, that you don't overwrite the ABM header when you flash program your software into the flash.
0 Likes
User8620
Level 2
Level 2
Hi again,

So my bootloader is ready. In Dave I mapped it into the PSRAM.
How can I now exactly store the bootloader code in the flash and how can I copy it to RAM during runtime?

What do I need to do with the hex file of the bootloder code?
Do I only need the Data ? without the addresses?

Can you maybe give me a short example? Thanks in advance

Oliver
0 Likes
User6793
Level 4
Level 4
I would suggest at this stage to maybe stop using the IDE for building and set up a make system?
You will need a makefile and a .ld file (also called a scatter file I think)
In your makefile, you can generate all sorts of output formats where a binary format is a 1:1 mapping of what you need to put in FLASH.

obj/%.bin: obj/%.elf
@echo "########## Creating BIN file $@ from $<"
@$(OBJCOPY) --output-target=binary $< $@


Setting up a make system is not trivial though. We had a consultant working on it for more than a week

Travis might have a simpler solution 🙂
0 Likes
Obelix
Employee
Employee
Welcome! First reply posted
OMR wrote:
I just flashed it after generating it:

const uint32_t ABM0_HEADER_ADDRESS = 0x0c00ffe0;

unsigned int abm0[ABM_HEAD_WORDS];

if (sanityCheck(BOOT_START_ADDRESS)) {
unsigned char tmpBuf[FLASH002_PAGE_SIZE]; // minimum number of bytes to FLASH
Flash *flash = Flash::getInstance();

memcpy(tmpBuf, (unsigned char *)ABM0_BUFFER_ADDRESS, FLASH002_PAGE_SIZE); // copy flash contents into buffer

abm0[0] = ABM_MAGIC_KEY; // magic key
abm0[1] = BOOT_START_ADDRESS; // start address of code
abm0[2] = ABM_DEFAULT_SIZE; // Application length
abm0[3] = crc32Gen((unsigned int *)BOOT_START_ADDRESS, ABM_DEFAULT_SIZE); // CRC32 for application length
abm0[4] = crc32Gen(abm0, ABM_HEAD_SIZE-4); // CRC32 for above 4

memcpy(tmpBuf+0xe0, abm0, ABM_HEAD_SIZE); // copy ABM data into tmpBuf

// Program header in FLASH
if (flash->write((unsigned int)ABM0_BUFFER_ADDRESS, (unsigned char *)&tmpBuf, FLASH002_PAGE_SIZE) != 0) {
printf("\nFLASH write failed!\n");
return;
}
else {
if (flash->writeEnd() != 0) { // make sure last block is written to FLASH
printf("FLASH end write failed\n");
return;
}
else {
printf("\nABM0 header FLASHed OK\n");
setBMIWord();
}
}
return; // never copy freshly loaded primary booter as fallback, without at least one reset in between (in effect do a test run of the new booter!)
}


Hi,

I am working on a similar project - I am trying to execute a Bootloader from PSRAM. I am able to copy the bootloader to the PSRAM but i cannot start it with the Alternative Boot Mode. I think I have a problem with the header Generation - the manual of the XMC4500 doesn't say anything about the CRC32 settings, besides the polynom. Could you please tell me the CRC settings (seed value, Reflection of the Input/Output data?, XOR of the ouput?)? Do you also use the CRC (FCE) Engine of the XMC?

Thanks,

Best regards,
Gerald
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
Hi Obelix,

My previous TriCore TC1767 Alternate Boot mode Example use this software CRC which is similar to the hardware CRC. Please take care of the word size as one missing byte is good to make this CRC mismatch.




/***********************************************************
* Coding supply by verification team
*
***********************************************************/
uword crc_gen (uword *data, uword size)
{
uword crc = 0xFFFFFFFF;
for(uword i=0; i uword word = *(data+i);
uword feedback =
((crc & (1 << 31)) ? 1 : 0) ^
((crc & (1 << 30)) ? 1 : 0) ^
((crc & (1 << 29)) ? 1 : 0) ^
((crc & (1 << 27)) ? 1 : 0) ^
((crc & (1 << 26)) ? 1 : 0) ^
((crc & (1 << 24)) ? 1 : 0) ^
((crc & (1 << 23)) ? 1 : 0) ^
((crc & (1 << 21)) ? 1 : 0) ^
((crc & (1 << 20)) ? 1 : 0) ^
((crc & (1 << 19)) ? 1 : 0) ^
((crc & (1 << 15)) ? 1 : 0) ^
((crc & (1 << 9)) ? 1 : 0) ^
((crc & (1 << 8)) ? 1 : 0) ^
((crc & (1 << 5)) ? 1 : 0);

crc = ((word ^ ((crc & 0x7fffffff) << 1)) & 0xfffffffe) | (feedback ^ ((word & 1) ? 1 : 0));
}

return crc;

}


uword Calculate_WordSize (uword start, uword end)
{
uword size;

size = (end-start);
size = size >> 2;

return size;
}

0 Likes
User6793
Level 4
Level 4
We ended up generating the CRC32 on the chip, as Infineon was unable to provide us with a SW CRC32 routine producing the same result as the HW CRC32 generator in XMC4500.
Our first idea was to have the make system generating the ABM headers, but we ended up doing it all in our application.
Here are some snippets to get you started if you decide to take this route: (ref #18 as well)

unsigned int Booter::crc32Gen(unsigned int *memPtr, unsigned int size)
{
unsigned int result = 0;
#if (!IS_BOOTER)
crc32Init();
crc32Chunk(memPtr, size);
result = crc32Res();
#endif
return result;
}

void Booter::crc32Init(void) // HW CRC generator, init for chunk
{
#if (!IS_BOOTER)
SCU_RESET->PRCLR2 = SCU_RESET_PRCLR2_FCERS_Msk;
while((SCU_RESET->PRSTAT2 & SCU_RESET_PRSTAT2_FCERS_Msk))
;

FCE->CLC = 0;
while((FCE->CLC & FCE_CLC_DISS_Msk))
;

FCE_KE0->CFG = 0;
FCE_KE0->CRC = 0;
#endif
}

void Booter::crc32Chunk(unsigned int *memPtr, unsigned int size) // HW CRC generator, chunk data
{
#if (!IS_BOOTER)
size >>=2; // /4 since memPtr is a word pointer

for (uint32_t i=0; i FCE_KE0->IR = *memPtr++;
}
#endif
}

unsigned int Booter::crc32Res(void) // HW CRC generator, final chunk result
{
unsigned int result = 0;
#if (!IS_BOOTER)
result = FCE_KE0->RES;
result = FCE_KE0->RES; // must be read twice, or else the result is wrong!
#endif
return result;
}


When copying the orignal booter to the fallback address, the following vectors need to be tweaked:

// adjust 0x0800xxxx vectors to 0x0801xxxx
for (unsigned int *i=(unsigned int *)tmpBuf; i<(unsigned int *)(tmpBuf+FLASH_BUFFER_SIZE); i++)
if ((*i >= BOOT_START_ADDRESS) && (*i < (BOOT_START_ADDRESS+BOOT_MAX_SIZE))) {
*i |= 0x00010000;
mods08++;
}

// adjust 0x0c00xxxx vectors to 0x0c01xxxx
for (unsigned int *i=(unsigned int *)tmpBuf; i<(unsigned int *)(tmpBuf+FLASH_BUFFER_SIZE); i++)
if ((*i >= BOOT_LOAD_ADDRESS) && (*i < (BOOT_LOAD_ADDRESS+BOOT_MAX_SIZE))) {
*i |= 0x00010000;
mods0c++;
}
0 Likes
User8620
Level 2
Level 2
Hi,

I have found a problem with my Bootloader. Programs that use no Interrupts work fine.
But interrupts never occure in programs that have interrupts enabeled. How can I fix that? I read the ASC bootloader example pdf, but there it never says anything about interrupts.
Can someone help me?
0 Likes
User6793
Level 4
Level 4
Have a look at post #14 in this thread 🙂
0 Likes
User9011
Level 1
Level 1
Thanks to OMR, we now found the solution! 🙂

If there are interrupts used in the bootloader, it is not possible to use them in the application.
So we just rewrote the bootloader without any interrupts and it worked with the jump descriped by OMR in post #14.
0 Likes
User6793
Level 4
Level 4
Just for completeness I want to add this information.
NAR's statement about interrupts in the bootloader is not 100% accurate.

We have 3 programs loaded at all times. Two booters, one primary and one fallback and our App.

We have a CLI command for jumping to the fallback booter, and I find that I can jump from our primary booter to the fallback booter and then jump to the fallback booter from the fallback booter itself many times with no errors.

But, when starting our App and then jumping to our fallback booter, it seems that it dies after a while, or interrupts are not served, so this must be what you are seeing too.
This is normally no problem for us since the jump from booter to App is OK, and jump the other way is normally done through a reset.

So, what is the difference between our booter and App?

This is what I can think of:

1. The App start kicking the HW watchdog.
2. The App uses SPI
3. The App uses POSQE
4. The App sets up NMI from our power monitor
5. The App sets up PWM
6. The App sets up much more GPIO (polled)

They both use:
1. UART (interrupt driven)
2. CAN (interrupt driven)
3. I2C (polled)
4. HW timer slice for our us timetick (interrupt driven)

So, my guess is that one of the resources used by the App is preventing the jump to be successful, so look in the reference manual if it possible to issue peripheral reset or disable commands just prior to doing the jump after disabling the global interrupt flag.
0 Likes
Not applicable
Hi ,
I am working similar project now. I try to separate Bootcode & appcode to two hex files. In Bootcode, just only have communication with Host(PC) to transmit updated appcode.hex.
When I transmit a small appcode that only have Can communication function code, it's can work now. But when I transmit a bigger one, it can't execute downloaded appcode.
Do you have some idea or suggestion??

Thanks,

Best regards,
Peter.K
0 Likes
Not applicable
Did you read back and check if the downloaded hex code are correct?
Are they place at the correct address?
0 Likes
Not applicable
Hi Jackson,
Yes, I have used debugger tool to check my hex code are correct and no data lose.
I think maybe appcode need to modify something.
0 Likes
Not applicable
OMR wrote:
The code I posted runs in FLASH, but the following functions in the FLASH0002.c app has the __attribute__ ((section (".text.fastcode"))) applied so that those FLASH routines runs from RAM:

status_t Flash002_EraseSector (uint32_t Address)
status_t Flash002_WritePage (uint32_t Address, const uint32_t pBuf[])
status_t Flash002_EraseUCB(uint32_t UserLevel)
status_t Flash002_DisableGlobalReadProtection(uint32_t PW0, uint32_t PW1)
status_t Flash002_DisableSectorWriteProtection(uint32_t UserLevel, uint32_t PW0, uint32_t PW1)
status_t Flash002_ResumeProtection()
status_t Flash002_ConfigureProtection(uint32_t UserLevel, uint32_t PW0, uint32_t PW1, FLASH002ProtectionFlags_Type ProtectionFlags)
status_t Flash002_VerifyProtection(uint32_t UserLevel, uint32_t PW0, uint32_t PW1, FLASH002ProtectionFlags_Type ProtectionFlags)
status_t Flash002_ConfigureBMI (const FLASH002BMIString_Type *BMIString)
status_t Flash002_ConfirmProtection (uint32_t UserLevel)

That is all of them I think 🙂
The .cstartup code copies all functions with fastcode attribute to RAM during startup.


Where do you specify this attribute? is there any help file which shows how to handle this attribute? I do not want a fallback bootloader.. Can I make the program to jump to my bootloader location after startup? If yes how? Also like you I want to execute the flash routines from RAM. Please help me on this.
0 Likes
User6793
Level 4
Level 4
The attribute is specified in the scatterfile xxxx.ld as supplied to the linker.

MEMORY
{
FLASH_1_cached(RX) : ORIGIN = 0x08020000, LENGTH = 0xa0000-0x20000
FLASH_1_uncached(RX) : ORIGIN = 0x0C020000, LENGTH = 0xa0000-0x20000
PSRAM_1_FASTCODE(!RX): ORIGIN = 0x10000000, LENGTH = 0x1000
PSRAM_1_HEAP(!RX) : ORIGIN = 0x10001000, LENGTH = 0xf000
DSRAM_1_system(!RX) : ORIGIN = 0x20000000, LENGTH = 0x10000
DSRAM_2_comm(!RX) : ORIGIN = 0x30000000, LENGTH = 0x8000-32-256
DSRAM_2_bdat(!RX) : ORIGIN = 0x30000000+0x8000-32-256, LENGTH = 32
DSRAM_2_panic(!RX) : ORIGIN = 0x30000000+0x8000-256, LENGTH = 256
}

.fastcode : AT(LOADADDR(.startup) + SIZEOF(.startup))
{
__fastcode_start = .;
/* functions with __attribute__ ((section (".text.fastcode")))*/
*(.text.fastcode)
__fastcode_end = .;
} >PSRAM_1_FASTCODE
__fastcode_load = LOADADDR (.fastcode);
__fastcode_size = __fastcode_end - __fastcode_start;


At startup it is copied from FLASH to RAM by the startup_XMC4500.s assembly routine:

__Xmc4500_Program_Loader:
.fnstart
/* Memories are accessible now*/

/* DATA COPY */
/* R0 = Start address, R1 = Destination address, R2 = Size */
LDR R0, =__fastcode_load
LDR R1, =__fastcode_start
LDR R2, =__fastcode_size
BL __COPY_FLASH2RAM


In the C files, just add this attribute for every function you want to run from RAM:

__attribute__ ((section (".text.fastcode")))
status_t Flash002_EraseSector (uint32_t Address)
{
.
.
}

__attribute__ ((section (".text.fastcode")))
status_t Flash002_WritePage (uint32_t Address, const uint32_t pBuf[])
{
.
.
}


No help file, as we use the GNU tool chain. Google is your friend.

If you don't want a fallback booter, updating the booter itself is a risky business.

The mentioned assembly file startup_XMC4500.s contains the vector tables. This would normally point to code that ultimately calls main() in your booter C code:

__Xmc4500_interrupt_vector_cortex_m:
.long __Xmc4500_stack /* Top of Stack */
.long __Xmc4500_reset_cortex_m /* Reset Handler */
.
.
/* Reset Handler */

.thumb_func
.globl __Xmc4500_reset_cortex_m
.type __Xmc4500_reset_cortex_m, %function
__Xmc4500_reset_cortex_m:
.fnstart

/* C routines are likely to be called. Setup the stack now */
/* This is already setup by BootROM,hence this step is optional */
LDR SP,=__Xmc4500_stack

/* Clock tree, External memory setup etc may be done here */
LDR R0, =SystemInit
BLX R0

/*
SystemInit_DAVE3() is provided by DAVE3 code generation engine. It is
weakly defined here though for a potential override.
*/
LDR R0, =SystemInit_DAVE3
BLX R0

B __Xmc4500_Program_Loader
.
.
.

ending up calling your main() in C:
/* Reset stack pointer before zipping off to user application, Optional */
LDR SP,=__Xmc4500_stack
MOV R0,#0
MOV R1,#0
LDR PC, =main
.pool
.cantunwind
.fnend
.size __Xmc4500_Program_Loader,.-__Xmc4500_Program_Loader


As you see, not entirely trivial, but at least I hope you can benefit somewhat from my comments 🙂
0 Likes
Not applicable
OMR wrote:
The attribute is specified in the scatterfile xxxx.ld as supplied to the linker.

MEMORY
{
FLASH_1_cached(RX) : ORIGIN = 0x08020000, LENGTH = 0xa0000-0x20000
FLASH_1_uncached(RX) : ORIGIN = 0x0C020000, LENGTH = 0xa0000-0x20000
PSRAM_1_FASTCODE(!RX): ORIGIN = 0x10000000, LENGTH = 0x1000
PSRAM_1_HEAP(!RX) : ORIGIN = 0x10001000, LENGTH = 0xf000
DSRAM_1_system(!RX) : ORIGIN = 0x20000000, LENGTH = 0x10000
DSRAM_2_comm(!RX) : ORIGIN = 0x30000000, LENGTH = 0x8000-32-256
DSRAM_2_bdat(!RX) : ORIGIN = 0x30000000+0x8000-32-256, LENGTH = 32
DSRAM_2_panic(!RX) : ORIGIN = 0x30000000+0x8000-256, LENGTH = 256
}

.fastcode : AT(LOADADDR(.startup) + SIZEOF(.startup))
{
__fastcode_start = .;
/* functions with __attribute__ ((section (".text.fastcode")))*/
*(.text.fastcode)
__fastcode_end = .;
} >PSRAM_1_FASTCODE
__fastcode_load = LOADADDR (.fastcode);
__fastcode_size = __fastcode_end - __fastcode_start;


At startup it is copied from FLASH to RAM by the startup_XMC4500.s assembly routine:

__Xmc4500_Program_Loader:
.fnstart
/* Memories are accessible now*/

/* DATA COPY */
/* R0 = Start address, R1 = Destination address, R2 = Size */
LDR R0, =__fastcode_load
LDR R1, =__fastcode_start
LDR R2, =__fastcode_size
BL __COPY_FLASH2RAM


In the C files, just add this attribute for every function you want to run from RAM:

__attribute__ ((section (".text.fastcode")))
status_t Flash002_EraseSector (uint32_t Address)
{
.
.
}

__attribute__ ((section (".text.fastcode")))
status_t Flash002_WritePage (uint32_t Address, const uint32_t pBuf[])
{
.
.
}


No help file, as we use the GNU tool chain. Google is your friend.

If you don't want a fallback booter, updating the booter itself is a risky business.

The mentioned assembly file startup_XMC4500.s contains the vector tables. This would normally point to code that ultimately calls main() in your booter C code:

__Xmc4500_interrupt_vector_cortex_m:
.long __Xmc4500_stack /* Top of Stack */
.long __Xmc4500_reset_cortex_m /* Reset Handler */
.
.
/* Reset Handler */

.thumb_func
.globl __Xmc4500_reset_cortex_m
.type __Xmc4500_reset_cortex_m, %function
__Xmc4500_reset_cortex_m:
.fnstart

/* C routines are likely to be called. Setup the stack now */
/* This is already setup by BootROM,hence this step is optional */
LDR SP,=__Xmc4500_stack

/* Clock tree, External memory setup etc may be done here */
LDR R0, =SystemInit
BLX R0

/*
SystemInit_DAVE3() is provided by DAVE3 code generation engine. It is
weakly defined here though for a potential override.
*/
LDR R0, =SystemInit_DAVE3
BLX R0

B __Xmc4500_Program_Loader
.
.
.

ending up calling your main() in C:
/* Reset stack pointer before zipping off to user application, Optional */
LDR SP,=__Xmc4500_stack
MOV R0,#0
MOV R1,#0
LDR PC, =main
.pool
.cantunwind
.fnend
.size __Xmc4500_Program_Loader,.-__Xmc4500_Program_Loader


As you see, not entirely trivial, but at least I hope you can benefit somewhat from my comments 🙂



Hey OMR

Thank you for the reply. I think I understand what your trying to say. But few more questions:

1) I only have a .sct file and no LD file in my project. What are your views on that. I tried changing the extension to LD but i think sct and ld are the same. Can you share your XMC4500 sct or LD file with me please?
2) Can you explain a bit more in detail about your fallback boot mode strategy.
3) Can you share your flash library with me. I feel i do not have the latest one as some routines described by you are not defined in my library.

my emails ID is c_sgopak@qti.qualcomm.com Please share if possible. Will be of great help 😉

Thanks
0 Likes
Not applicable
OMR wrote:
The attribute is specified in the scatterfile xxxx.ld as supplied to the linker.

MEMORY
{
FLASH_1_cached(RX) : ORIGIN = 0x08020000, LENGTH = 0xa0000-0x20000
FLASH_1_uncached(RX) : ORIGIN = 0x0C020000, LENGTH = 0xa0000-0x20000
PSRAM_1_FASTCODE(!RX): ORIGIN = 0x10000000, LENGTH = 0x1000
PSRAM_1_HEAP(!RX) : ORIGIN = 0x10001000, LENGTH = 0xf000
DSRAM_1_system(!RX) : ORIGIN = 0x20000000, LENGTH = 0x10000
DSRAM_2_comm(!RX) : ORIGIN = 0x30000000, LENGTH = 0x8000-32-256
DSRAM_2_bdat(!RX) : ORIGIN = 0x30000000+0x8000-32-256, LENGTH = 32
DSRAM_2_panic(!RX) : ORIGIN = 0x30000000+0x8000-256, LENGTH = 256
}

.fastcode : AT(LOADADDR(.startup) + SIZEOF(.startup))
{
__fastcode_start = .;
/* functions with __attribute__ ((section (".text.fastcode")))*/
*(.text.fastcode)
__fastcode_end = .;
} >PSRAM_1_FASTCODE
__fastcode_load = LOADADDR (.fastcode);
__fastcode_size = __fastcode_end - __fastcode_start;


At startup it is copied from FLASH to RAM by the startup_XMC4500.s assembly routine:

__Xmc4500_Program_Loader:
.fnstart
/* Memories are accessible now*/

/* DATA COPY */
/* R0 = Start address, R1 = Destination address, R2 = Size */
LDR R0, =__fastcode_load
LDR R1, =__fastcode_start
LDR R2, =__fastcode_size
BL __COPY_FLASH2RAM


In the C files, just add this attribute for every function you want to run from RAM:

__attribute__ ((section (".text.fastcode")))
status_t Flash002_EraseSector (uint32_t Address)
{
.
.
}

__attribute__ ((section (".text.fastcode")))
status_t Flash002_WritePage (uint32_t Address, const uint32_t pBuf[])
{
.
.
}


No help file, as we use the GNU tool chain. Google is your friend.

If you don't want a fallback booter, updating the booter itself is a risky business.

The mentioned assembly file startup_XMC4500.s contains the vector tables. This would normally point to code that ultimately calls main() in your booter C code:

__Xmc4500_interrupt_vector_cortex_m:
.long __Xmc4500_stack /* Top of Stack */
.long __Xmc4500_reset_cortex_m /* Reset Handler */
.
.
/* Reset Handler */

.thumb_func
.globl __Xmc4500_reset_cortex_m
.type __Xmc4500_reset_cortex_m, %function
__Xmc4500_reset_cortex_m:
.fnstart

/* C routines are likely to be called. Setup the stack now */
/* This is already setup by BootROM,hence this step is optional */
LDR SP,=__Xmc4500_stack

/* Clock tree, External memory setup etc may be done here */
LDR R0, =SystemInit
BLX R0

/*
SystemInit_DAVE3() is provided by DAVE3 code generation engine. It is
weakly defined here though for a potential override.
*/
LDR R0, =SystemInit_DAVE3
BLX R0

B __Xmc4500_Program_Loader
.
.
.

ending up calling your main() in C:
/* Reset stack pointer before zipping off to user application, Optional */
LDR SP,=__Xmc4500_stack
MOV R0,#0
MOV R1,#0
LDR PC, =main
.pool
.cantunwind
.fnend
.size __Xmc4500_Program_Loader,.-__Xmc4500_Program_Loader


As you see, not entirely trivial, but at least I hope you can benefit somewhat from my comments 🙂


Hi OMR,

I am using the flash routines and not executing it from RAM. the address which program block is executing is 0x08000ECC and it is able to program the sector beginning from 0x8010000. How is this possible. I am able tto read the data which i am programming. Please tell how is this happening. I am totally confused.

Sarath
0 Likes
Not applicable
OMR wrote:
The attribute is specified in the scatterfile xxxx.ld as supplied to the linker.

MEMORY
{
FLASH_1_cached(RX) : ORIGIN = 0x08020000, LENGTH = 0xa0000-0x20000
FLASH_1_uncached(RX) : ORIGIN = 0x0C020000, LENGTH = 0xa0000-0x20000
PSRAM_1_FASTCODE(!RX): ORIGIN = 0x10000000, LENGTH = 0x1000
PSRAM_1_HEAP(!RX) : ORIGIN = 0x10001000, LENGTH = 0xf000
DSRAM_1_system(!RX) : ORIGIN = 0x20000000, LENGTH = 0x10000
DSRAM_2_comm(!RX) : ORIGIN = 0x30000000, LENGTH = 0x8000-32-256
DSRAM_2_bdat(!RX) : ORIGIN = 0x30000000+0x8000-32-256, LENGTH = 32
DSRAM_2_panic(!RX) : ORIGIN = 0x30000000+0x8000-256, LENGTH = 256
}

.fastcode : AT(LOADADDR(.startup) + SIZEOF(.startup))
{
__fastcode_start = .;
/* functions with __attribute__ ((section (".text.fastcode")))*/
*(.text.fastcode)
__fastcode_end = .;
} >PSRAM_1_FASTCODE
__fastcode_load = LOADADDR (.fastcode);
__fastcode_size = __fastcode_end - __fastcode_start;


At startup it is copied from FLASH to RAM by the startup_XMC4500.s assembly routine:

__Xmc4500_Program_Loader:
.fnstart
/* Memories are accessible now*/

/* DATA COPY */
/* R0 = Start address, R1 = Destination address, R2 = Size */
LDR R0, =__fastcode_load
LDR R1, =__fastcode_start
LDR R2, =__fastcode_size
BL __COPY_FLASH2RAM


In the C files, just add this attribute for every function you want to run from RAM:

__attribute__ ((section (".text.fastcode")))
status_t Flash002_EraseSector (uint32_t Address)
{
.
.
}

__attribute__ ((section (".text.fastcode")))
status_t Flash002_WritePage (uint32_t Address, const uint32_t pBuf[])
{
.
.
}


No help file, as we use the GNU tool chain. Google is your friend.

If you don't want a fallback booter, updating the booter itself is a risky business.

The mentioned assembly file startup_XMC4500.s contains the vector tables. This would normally point to code that ultimately calls main() in your booter C code:

__Xmc4500_interrupt_vector_cortex_m:
.long __Xmc4500_stack /* Top of Stack */
.long __Xmc4500_reset_cortex_m /* Reset Handler */
.
.
/* Reset Handler */

.thumb_func
.globl __Xmc4500_reset_cortex_m
.type __Xmc4500_reset_cortex_m, %function
__Xmc4500_reset_cortex_m:
.fnstart

/* C routines are likely to be called. Setup the stack now */
/* This is already setup by BootROM,hence this step is optional */
LDR SP,=__Xmc4500_stack

/* Clock tree, External memory setup etc may be done here */
LDR R0, =SystemInit
BLX R0

/*
SystemInit_DAVE3() is provided by DAVE3 code generation engine. It is
weakly defined here though for a potential override.
*/
LDR R0, =SystemInit_DAVE3
BLX R0

B __Xmc4500_Program_Loader
.
.
.

ending up calling your main() in C:
/* Reset stack pointer before zipping off to user application, Optional */
LDR SP,=__Xmc4500_stack
MOV R0,#0
MOV R1,#0
LDR PC, =main
.pool
.cantunwind
.fnend
.size __Xmc4500_Program_Loader,.-__Xmc4500_Program_Loader


As you see, not entirely trivial, but at least I hope you can benefit somewhat from my comments 🙂


Also i do not have a ld file. I have .sct scatter file. the above syntax throws in an error. Any idea how to handle this.

Sarath
0 Likes
User6793
Level 4
Level 4
What tool chain do you use?

I just Googled 'scatterfile' and found this: http://infocenter.arm.com/help/topic/com.arm.doc.kui0101a/armlink_babddhbf.htm

Might help you out.
0 Likes
Not applicable
OMR wrote:
What tool chain do you use?

I just Googled 'scatterfile' and found this: http://infocenter.arm.com/help/topic/com.arm.doc.kui0101a/armlink_babddhbf.htm

Might help you out.


Hi OMR

Thanks for your reply!!

I am using Keil Microvision toolchain version 5.

Anyways, Do you have any comments on my earlier question ? I am able to program the flash while executing code from flash. is it possible to program/erase a page from another sector while executing code from other sector? I am confused. Can you please give me your thoughts?

Sarath
0 Likes
Not applicable
OMR wrote:
What tool chain do you use?

I just Googled 'scatterfile' and found this: http://infocenter.arm.com/help/topic/com.arm.doc.kui0101a/armlink_babddhbf.htm

Might help you out.


If possible can you please share your email ID. will be of great help. thanks 🙂
0 Likes
Not applicable
Hey OMR

Thanks! I am able to write to flash without any speciall commands. I do not know why. But I am not able to jump to the code location. Can you please advice me on this?

Sarath
0 Likes
Not applicable
Also i am totally confused by the behavior of flash. I am just using the flash library to program and erase and it does it ..without running it from RAM. Can you please try it. I also ran the code without debugger connected and yet it flashed. Can you come up with any explanation for such a behavior?

Sarath
0 Likes
Not applicable
Hi OMR

here are some more details:

Booter start address: 0x08000000
App start address: 0x08004000

APP sw hex has been generated using a different Keil Project with the standard Startup sftware provided . But when I try to make the jump from booter to app at the end the program counter does not mae the jump but stays in the booter section. I have build the app sw using 0x08004000 start address in the app scatter file. what other precautions should I take. I am not using any special boot modes.

Sarath
0 Likes
Not applicable
Obelix wrote:
Hi,

I am working on a similar project - I am trying to execute a Bootloader from PSRAM. I am able to copy the bootloader to the PSRAM but i cannot start it with the Alternative Boot Mode. I think I have a problem with the header Generation - the manual of the XMC4500 doesn't say anything about the CRC32 settings, besides the polynom. Could you please tell me the CRC settings (seed value, Reflection of the Input/Output data?, XOR of the ouput?)? Do you also use the CRC (FCE) Engine of the XMC?

Thanks,

Best regards,
Gerald


How did you write to flash just those 5 bytes?? Which flash API did you use?

Sarath
0 Likes
User6793
Level 4
Level 4
I have no experience with the Kiel tool chain, but if you look in the ,map file produced by the linker, you might find that the flash routines have RAM addresses?
It could also be that the newer FLASH library works some magic behind the scenes, or that it worked by chance because you where executing code from a different sector?
I don't have the time to dig into this, but maybe someone from Infineon could chime in?

How do you jump from your booter to the application?
I have included the code needed to make the jump in a previous post.
If you want to write just 5 bytes, you must read the whole contents of the target sector into RAM, modify the 5 bytes in RAM, erase the sector, and write it back.
0 Likes