View previous topic :: View next topic |
Author |
Message |
jychua
Joined: 27 Jul 2021 Posts: 14
|
Bootloader Example Understandings |
Posted: Wed Sep 15, 2021 11:32 am |
|
|
Hey all,
I have been trying to understand how bootloader is implemented using the CCS C Compiler (using PIC18F46Q10; compiler version 5.105). Here is what I have gathered so far, please correct any misunderstandings:
1. The recommended practice for fuses is to specify them in the bootloader project, and put #fuses NONE in the application project.
2. To modify the size of the bootloader, adjust the macro LOADER_END in bootloader.h. LOADER_END must be 1 minus a multiple of getenv("FLASH_ERASE_SIZE").
3. The function jump_to_isr internally adjusts the input parameter to align with the instruction word boundary.
4. A 2-instruction wide application stub after LOADER_END within the bootloader project tells the bootloader where to jump to application. By including bootloader.h in the application project (required), the reset element within the #build macro enables the compiler to replace the stub with the start of actual application.
Code: |
#org LOADER_END+1,LOADER_END+3
void application(void) {
while (TRUE);
}
|
5. Similar to item 4, within the bootloader project, the #int_global causes the jump_to_isr function to replace the compiler's interrupt dispatcher, which is located at the interrupt vector address. This effectively tells PC to jump to wherever jump_to_isr specifies when interrupts occur. By including bootloader.h in the application project, the interrupt element within the #build macro enables the compiler to place the actual interrupt handling function pointers at the location specified by jump_to_isr.
When interrupts occur, the PC first goes to the interrupt vector table, then gets redirected by jump_to_isr to reach the actual interrupt handling function.
Code: |
#int_global
//-------------------------------------------------------------------------
void isr (void) {
//-------------------------------------------------------------------------
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
|
Thank you for your time and help!
jychua |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Thu Sep 16, 2021 6:44 am |
|
|
1) Yes.
2) No. Try never to change things 'in' the supplied files. All you do is have
a define for LOADER_END, _before_ you load bootloader.h.
The key is that if the file finds this already defined, it uses the existing
definition.
So:
Code: |
#define LOADER_END 0x7FF
#include "bootloader.h"
|
Also you have your calculation the wrong way round. It wants to be a
multiple of FLASH_ERASE_SIZE - 1, not 1 - a multiple.
3) The processor only supports jumps to an instruction boundary.
If you look at the instruction set in the data sheet, the call, and goto
instructions put the target address into PC<20:1>. Note 20.1, not 20.0.
The executing instruction is always on an instruction boundary, so the new
address is also always on an instruction boundary.
4) The built program always starts with a jump to the actual code. This
has to happen to allow the code to jump 'round' the interrupt jumps that
are just above this. The 'stub' is just a dummy to maintain this same layout.
The loaded program also has this same layout.
5) Key here is that the jump_to_isr code replaces both vectors if needed.
So 'functions', not just 'function'. |
|
|
jychua
Joined: 27 Jul 2021 Posts: 14
|
|
Posted: Thu Sep 16, 2021 7:48 am |
|
|
Thank you for the clarifications! Sounds good to me. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Thu Sep 16, 2021 7:56 am |
|
|
Nice to have somebody actually trying to 'get their head round' how the
stuff works. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1346
|
Re: Bootloader Example Understandings |
Posted: Thu Sep 16, 2021 7:04 pm |
|
|
jychua wrote: |
1. The recommended practice for fuses is to specify them in the bootloader project, and put #fuses NONE in the application project.
|
I would also recommend that when you specify #use delay() that for the application you only use
Code: | #use delay(clock=XXXX) |
to avoid generating #fuses, but in the bootloader feel free to use the other parameters like internal/crystal/etc as those can generate #fuses |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Fri Sep 17, 2021 12:09 am |
|
|
Absolutely.
A very good point.
#use delay with just a 'clock', simply sets the clock. With almost any other
parameter (crystal, internal etc.), it generates fuses and/or PLL settings. |
|
|
jychua
Joined: 27 Jul 2021 Posts: 14
|
|
Posted: Fri Sep 17, 2021 2:32 pm |
|
|
Will do. Thanks for the input! |
|
|
|