Hello
Iam now make the S12ZVC64-bootloader. when I download the S19 file into the MCU .the programe will die . I couldnot find the reason .Could you help me solve the problem. The attachment is my codes.
Original Attachment has been moved to: S12ZVC_Boot.zip
Original Attachment has been moved to: S12ZVC-app.zip
Hi Xiaohui,
1.
Your app prm linker file contains:
VECTOR 0 app_entry
Please comment it out. The last sector of Flash is occupied by Bootloader and application cannot write reset vector at this place.
2.
Your APPLICATION_START_ADD value in bootloader is configured 0xFF0000. But, this address do not refer to _Startup() function in your application. Your application starts at address 0xFF002E - see app map file. Unfortunately the default placement of _Startup() function depends on used number of variables. The initial variable values with DoZeroOut() and DoCopyDown() finctions are placed into memory prior _Startup() function.
So, you have to somehow manage that _Startup() function will be placed into flash as first (see attached example of app Start12z.c file) or your pointer to _Startup() function must be dynamically modified according to app code update (see attached example of app prm linker file which contains jump to _Startup() function in first few bytes of flash).
I hope it helps you.
Have a great day,
Radek
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
xiaohui wang,
I took a look at the bootloader code and the application. In the bootloader function Jump_Main_Application() you are creating a function pointer with the "hard coded" address 0xff0000. However, I can see looking at the S-Record file (159357.sx) that a value of 0xBAFF00 is stored at 0xff0000. It looks like the address to which you want to jump actually begins at 0xff0001 (i.e. 0xFF0004).
Remember, pointers, including function pointers, in the S12Z are three bytes not four.
Best Regards,
Gordon
Hi Gordon,
You are right. This is just the workaround. The default S12Z CW project do not place _Startup() function as the first object into flash - the init structure, DoZeroOut() and DoCopyDown() are placed as first. Therefore the application _Startup() address vary on a number of used variables in the application. That behavior is quite annoying in the case of a solution with separate bootloader and application projects.
The workaround: The application start address in bootloader is hard coded as the first byte of flash. The application linker file is modified that first byte of flash will be 0xBA (asm JMP instruction), followed by a vector to the application _Startup() function. So, bootloader's jump to the first byte of flash will cause another jump to the application _Startup() function. This workaround consumes 4bytes from flash and 1.5 bus cycle for an additional jump.
The another possible solution (probably better) is to reorganize code in application Start12z.c file that _Startup() function will be placed into flash as first.
See my post above with both workarounds.
Best regards
Radek
Hi Xiaohui,
As I can see, you implemented both workarounds that I proposed. Using just one of them is enough.
The part of your code in bootloader:
case 0xFD:
{ data[0]=0xC1;bootCAN_send(bootupID, data, 1);
DisableInterrupts;
CAN0CTL0 = 0x01; // MSCAN in initialization mode
while (!(CAN0CTL1_INITAK));
Jump_Main_Application();
for(;;) ;
}break;
The bootCAN_send() function just fill TX buffer and schedule transmitting data.
The CAN0CTL0 = 0x01; command will abort all receiving and transmitting action on MSCAN module.
I would like to recommend switch MSCAN module into sleep mode prior enter into initialization mode. That will manage that MSCAN will wait until all TX buffers are empty and no RX message is receiving. In that case, the CAN bus will be not rushed by corrupted messages.
For example:
CAN0CTL0_SLPRQ = 1; //sleep mode request
while(CAN0CTL1_SLPAK == 0); //wait for acknowledge of sleep mode
CAN0CTL0 = 0x01; // MSCAN in initialization mode
while (!(CAN0CTL1_INITAK));
You may also try to clear CAN flags or disable CAN interrupt prior that operation.
I hope it helps you.
Have a great day,
Radek
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hello
I tried modified my app started address 0xFF0004. if I use CAN received interrupt .it could work normally.if Iused API interrupt to light a led ,it couldnot work ,because machine exception interrupt 5U will happen . because MMCECL_ERR=1, means access to an illegal address.Is there any way to avoid this problem .
Hi Xiaohui,
I shortly checked your code, but unfortunately I cannot see any obvious issue for what it shuld not work.
Just few notes:
You placed vector table at address 0xFFF010. In that case, you should exclude this area from ROM avialble for linker use. The default CW project do not report warning about memory overlapping.
The CPMUAPIR register is 16bit register.
However, nothing from that should not have any influence on your vector table and their functionality.
Are you sure, that you bootloader programmed vector table?
Did your vector table works when you load your app directly, without bootloader?
I hope it helps you.
Have a great day,
Radek
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I'm guessing that the problem is related to the fact that the code you are copying to RAM is compiled and linked for execution out of Flash, not RAM. In addition, there is an easier way to perform the copy operation and then reference the two functions in RAM. I'm attaching a modified project that implements what I'll briefly describe.
First in the SEGMENTS section of your .prm file, you'll want to replace
SHADOW_RAM_S = READ_WRITE 0x001000 TO 0x0011FF; // 512 for functions that will be copied to RAM
with:
SHADOW_ROM_S = READ_ONLY 0xFFFC00 TO 0xFFFDFF RELOCATE_TO 0x001000; // 512 for funtions that will be copied to RAM
and remove "SHADOW_ROM_S" from /* non-paged FLASHs */
This will tell the linker to place the code in Flash from 0xFFFC00 TO 0xFFFDFF but to link it to address 0x001000.
Remove:
SHADOW_RAM INTO SHADOW_RAM_S; /* Reserve Shadow ROM to copy flash related functions here */
from the PLACEMENTS section.
Next, replace your Copy_Shadow() function with:
/*************************************************************************************/
#define __SEG_START_REF(a) __SEG_START_ ## a
#define __SEG_END_REF(a) __SEG_END_ ## a
#define __SEG_SIZE_REF(a) __SEG_SIZE_ ## a
#define __SEG_START_DEF(a) extern char __SEG_START_REF(a) []
#define __SEG_END_DEF(a) extern char __SEG_END_REF( a) []
#define __SEG_SIZE_DEF(a) extern char __SEG_SIZE_REF( a) []
__SEG_START_DEF(SHADOW_ROM);
__SEG_END_DEF(SHADOW_ROM);
__SEG_SIZE_DEF(SHADOW_ROM);
/*************************************************************************************/
static void CopyCodeToRAM(void)
{
/* Variable Declarations */
uchar *Src;
uchar *Dst;
uint SegSize;
uint x;
/* Begin Function CopyCodeToRAM() */
Src = (uchar *)__SEG_START_REF(SHADOW_ROM); /* RAM code resides in Flash */
Dst = (uchar *)0x001000; /* copied to RAM */
SegSize = (uint)__SEG_SIZE_REF(SHADOW_ROM);
for (x = 0; x < SegSize; x++) /* just copy a byte at a time */
*Dst++ = *Src++;
} /* end CopyCodeToRAM */
/*************************************************************************************/
The macros are used to obtain the SHADOW_ROM section start address and its size from linker defined symbols.
Finally, you no longer need the function pointers FTMRZ_Erase_Flash_RAM and FTMRZ_Prog_Phrase_RAM to call the functions. instead you can directly reference the two functions that were copied into RAM via their names i.e. FTMRZ_Erase_Flash(); and FTMRZ_Prog_Phrase(); because the code was linked to their relocated addresses in RAM.
Hopefully I've not missed describing any of the modifications I made to your project, but the modified project is attached. I couldn't completely test this out, but I could do enough via the debugger in a target system to see that the functions were being called in RAM.
Hope this helps.
Best Regards,
Gordon
hello,
i'm working with ZVM MCU, and develop bootloader, use the same strategy for this application.
I met a issue that: i can successfully implement the funtion in RAM - FTMRZ_Erase_Flash_RAM()
and can return back, but died at the line - u8flashErased = 1; /* Indicate that flash has been erased */.
why have this issue?
waiting for your feedback ,thanks.