Hi everyone,
Context of the project
I'm working on a bootloader project based on RL78. I set my memory like this :
This idea is to jump from application to bootloader when I want to update the application and to jump from bootloader to application when I'm finished with the upload.
Major Issue
I'm able to start bootloader, flash the program, jump to application, jump to bootloader and flash program again. But this is ok like 50% of the time in DEBUG. The first start and flash is always working, the first jump is almost always working and after that it depends.
In release mode, it is even worse. I can start bootloader, flash the program and most of the time I can't even jump to the application
How did I code that ?
I'm based on the renesas FSL library and working on the R5F10DPJ microcontroller. To perform the bootswapping, I'm using this function :
void Flash_SwapBootCluster() { fsl_u08 fsl_status; UINT32 wait; // Open FSL and prepare all functions FSL_Open(); FSL_PrepareExtFunctions(); // Invert bootflag to start correct bootloader and close FSL fsl_status = FSL_InvertBootFlag(); while(fsl_status != FSL_OK) { fsl_status = FSL_InvertBootFlag(); } // Close FSL FSL_Close(); /* Delay */ wait = (UINT32)0; while(wait < (UINT32)10000) { wait++; } // Perform swapping of bootcluster fsl_status = FSL_SwapBootCluster(); while(fsl_status != FSL_OK) { fsl_status = FSL_SwapBootCluster(); } }
I start to be out of idea, am I doing something wrong with this boot swapping ?
Thanks in advance and have a good day !
Hello,
First of all your memory layout is a bit confusing.
There should be boot cluster 0 (for the one boot program) and boot program 1 (for the other boot program), if you want to use the boot swap mechanism. On top of them there should be the application(s).
The boot program must exist only inside the memory size of a boot cluster.
Regarding the boot swap, after calling FSL_InvertBootFlag you should issue a software reset so the boot swap takes place. The new bootloader is active after reset.
Hi, thanks for your answer
Concerning my memory organization, I aggre it wasn't very clear. In fact, there is 2 applications : The one handling the bootloading process to update the flash and the other one, the main application. Each of these application have their own boot (interrupt vector, ...)
Ok so calling the FSL_SwapBootCluster is not necessary since I already inverted boot flag. I just need to perform the reset then. I'll try this thanks !
According to RL78/D1A documentation, both watchdog reset + illegal instructions are software reset and this seems to be the purpose of FSL_ForceReset. But I followed your guidelines and removed the infinite loop to just let the FSL_ForceReset function
I also disabled on-chip debug through the option byte (0xC3)
Behavior is still the same : jump from bootloader to application blocks the MCU only in release mode
It could be due to RAM parity error. Please initialize RAM as I have mentioned on this post:
community.renesas.com/.../ram-parity-error-in-rl78-d1a-controller
Hi, thanks again for you answer.
I need to reserve SELFRAM for the FSL so I added this in the linker file :
-Z(CODE)SELFRAM=[FBF00-FC2FF]
Do you want me to update the linker file or directly the cstartup.s87 file ? (which is reading my linker file). I start to struggle how to organize my linker file between FSL segment, SelfRam for FSL_Write and RAM Initialization
I have this in my cstartup.s87 file :
; Init stack segment for as the generated code may sometimes ; access the 4th byte of a return address before it is initialized MOVW HL, #sfb(CSTACK) MOVW BC, #LWRD(sizeof(CSTACK)) CMP0 C SKZ INC B MOV A, #0xCD ; 0xCD to fool C-SPY's stack limit check loop_s: MOV [HL], A INCW HL DEC C BNZ loop_s DEC B BNZ loop_s MOV CS, #0
And, in my linker file :
//------------------------------------------------------------------------- // Stack segment. //------------------------------------------------------------------------- -Z(DATA)CSTACK+_CSTACK_SIZE=FC300-FFE1F
EDIT : This is only for the bootloader project, not the application
You can reserve self RAM are from this setting:
No need to modify the linker manually.
I'm on IAR,I don't have this option :/
I forgot this, apologies. Then update the linker file - not cstart file- and reserve area FBF00H- FC2FFH.
The self RAM area reservation is a different thing than RAM initialization. The self RAM is reserved for the flash libary while the RAM must be initialized so that a RAM parity error does not occur. Not all RAM areas are initialized in the startup.
Alright then I update this in both of my linker file :
//-Z(DATA)CSTACK+_CSTACK_SIZE=FC300-FFE1F -Z(DATA)CSTACK+_CSTACK_SIZE=FBF00-FFEE0 // Full RAM init
and
The first update will perform full RAM initialization according to the cstartup script that I don't need to modify.
The second update ensure that the SELFRAM is reserved
Am I right?
The RAM initialization happens during startup in the cstart file as I mentioned on the post I shared. The RAM initialization has nothing to do with linker file.
The cstart file will just fill the RAM with an initial value so any RAM parity errors are prevented.
The linker will reserve the self RAM area so that nothing else is placed there so the flash library can use this are for its operations.
My linker file is used to set the value of the stack, to process the RAM initialization through the assembly code you mentionned in the other post.
I reserved selfram in both of my linker script but still, everything works in debug and not in release, always blocked after the jump to application.
Maybe I can add more context to my project:
1. I'm flashing a first program, the bootloader, which needs to update the flash for the second program
2. To communicate with it, we use CAN bus. So after flashing the bootloader, I send data to flash the program (which is boot cluster 1 and application)
3. When finished, I jump from bootloader to application
4. I send a frame test to check if the application answers. In debug, it always answer. In release (which I program using a .s19 file on RFP), the frame I send is never received
Can you show what modifications have you done in the cstart file to initialize whole RAM ?
I did no modification.
My cstartup is like this (at least the part similar to the other post) :
?C_STARTUP: `@cstart`: __program_start: DI MOV A, #(_NEAR_CONST_LOCATION & 1) ; Near/Far, set mirror area MOV1 CY, A.0 MOV1 PMC.0, CY MOVW SP, #sfe(CSTACK) ; Init stack segment for as the generated code may sometimes ; access the 4th byte of a return address before it is initialized MOVW HL, #sfb(CSTACK) MOVW BC, #LWRD(sizeof(CSTACK)) CMP0 C SKZ INC B MOV A, #0xCD ; 0xCD to fool C-SPY's stack limit check loop_s: MOV [HL], A INCW HL DEC C BNZ loop_s DEC B BNZ loop_s MOV CS, #0
And, through the linker file, I update the CSTACK value:
//------------------------------------------------------------------------- // Stack segment. //------------------------------------------------------------------------- -Z(DATA)CSTACK+_CSTACK_SIZE=FBF00-FFEE0
The RAM will not be entirely initialized with the default cstart file.
Please modify according to this post:
https://community.renesas.com/automotive/rh850/f/rh850-forum/33274/ram-parity-error-in-rl78-d1a-controller
As you can see my cstart file covers the entire address range of RAM - not only stack.
Hi, I finally understook what you mean and I added a new cstartup file to both of my project and hardcoded values that you told me about. I also had to check 'Override default program entry'.
But, unfortunately, the process still doesn'r work in release mode :/
1. I added new cstartup + redo my linker file for the application. The application is able to communicate in debug. I flashed the application throught RFP and it is still communicating
2. I did the same with the bootloader, it works too
3. I start the bootloader in debug mode through IAR. I flash the application through CAN bus and then jump to application: the application is communicating
4. I flash the bootloader through RFP. I flash the application through CAN bus (and I can assure you that the bootloader is communication). Then I jump to application : Everything is blocked.
I'm running out of idea :/ Can a softreset (FSL_ForseReset in my case) block the MCU definitely?
What do you mean by 'added a new cstart file' ? The cstart file is only one. Just add the lines to initialize RAM in the existing cstart file:
If you pause the program after these lines you should see the RAM filled with 0xAA vaues.
cstart.zip
What I meant is that IAR is based, by default, on the cstartup.s87 located in installation folder. So I copy paste it to my project and modified it to avoid modifying the default file for other project.
Here is my cstartup file, for IAR
cstartup.zip
I modified those lines since it look the same as you for your startup file (In comment, after 'Adrien -', is the initial line)
; Init stack segment for as the generated code may sometimes ; access the 4th byte of a return address before it is initialized MOVW HL, #LWRD(0xBF00) ;Adrien - MOVW HL, #sfb(CSTACK) ; MOVW BC, #LWRD(0x3FE0) ;Adrien - MOVW BC, #LWRD(sizeof(CSTACK)) CMP0 C SKZ INC B MOV A, #0xCD ; 0xCD to fool C-SPY's stack limit check loop_s: MOV [HL], A INCW HL DEC C BNZ loop_s DEC B BNZ loop_s MOV CS, #0
I tried added your lines in my startup file but I got errors unfortunately. I'm quite a newbie in assembly :/
Sorry for taking a lot of your time with this issue
EDIT : I also tried another thing, set the RPERDIS flag to 1, to avoid reset link to RAM parity error
EDIT 2 : After reset, RPERDIS is reset to 0 and a parity error might happen before I set it again so it may be useless in my case then
EDIT 3 : Alright, RAM Initialization was the answer like you said. It was important to fill with 0xAA while my code was filling with 0xCD. Thanks a lot !
That's very good news.
One doubt about your last comment though. I do not think the value for RAM initialization is important to prevent RAM parity errors.
My guess is that your RAM was not fully initialized before but after you modified the cstart file as instructed, the RAM is now initialized with a random value (0xAA in this case) and the RAM parity errors are prevented.
If a reset will occur after a RAM parity error is controlled by RPERDIS bit:
So if you have this bit to its default value 0 and everything works as expected then no RAM parity errors occur during RAM access.
That's strange because everything is working fine since I only modified the 0xCD to 0xAA but I guess maybe something was not taken into account and then the RAM was not correctly initialized
So instead of 0xAA in the lines of code, you filled with 0xCD and it didn't work ?
Initially it was 0xCD ( I took the file from C:\IAR\IAR_Systems\Embedded_Workbench_7.0\rl78\src\lib ) and I saw that it was filled with CD. But nothing worked. Then I changed the value to 0xAA and it was working
Can you send a picture of this ?