|
|
View previous topic :: View next topic |
Author |
Message |
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
bootloader interrupts |
Posted: Thu Nov 12, 2015 9:45 pm |
|
|
Hello, I am trying to use bootloader in my pic18LF2685, but I'm having trouble using interruption. what should I do so that interrupts work? I researched and told me that I need for a code before, but do not know how to find these codes (#org, #build, etc).
Can anyone help me? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Nov 13, 2015 1:48 am |
|
|
The CCS example bootloader, contains the code to allow interrupts to work in the main.
Generally, don't use interrupts in the bootloader. If you look at the USB bootloader, it _polls_ the USB. Similarly the serial in the bootloader is polled.
It is possible to use interrupts in both, but then you are going to have to write the code so that it switches interrupt handlers, routing the interrupts to the bootloader handler when the bootloader is used, and to the main code the rests of the time. This involves more time overhead for the interrupts....
There is another way, but this then involves a lot more custom code.
For interrupts like serial, what you can do is write a generic serial handler ISR, writing to a circular buffer at a fixed/defined RAM location (with the pointers also at fixed locations). Include this in your bootloader code, and use #byte to locate duplicate variables in the main code. Remove the interrupt re-vectoring code from the bootloader. It then becomes the bootloader's ISR, that handles the serial interrupts for both the bootloader and the main code. Downside is that if you ever want to change the interrupt code, the bootloader can no longer change this. However with a well written generic buffer handler, this is efficient, and save space. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Fri Nov 13, 2015 7:26 am |
|
|
Ttelmah wrote: | The CCS example bootloader, contains the code to allow interrupts to work in the main.
Generally, don't use interrupts in the bootloader. If you look at the USB bootloader, it _polls_ the USB. Similarly the serial in the bootloader is polled.
It is possible to use interrupts in both, but then you are going to have to write the code so that it switches interrupt handlers, routing the interrupts to the bootloader handler when the bootloader is used, and to the main code the rests of the time. This involves more time overhead for the interrupts....
There is another way, but this then involves a lot more custom code.
For interrupts like serial, what you can do is write a generic serial handler ISR, writing to a circular buffer at a fixed/defined RAM location (with the pointers also at fixed locations). Include this in your bootloader code, and use #byte to locate duplicate variables in the main code. Remove the interrupt re-vectoring code from the bootloader. It then becomes the bootloader's ISR, that handles the serial interrupts for both the bootloader and the main code. Downside is that if you ever want to change the interrupt code, the bootloader can no longer change this. However with a well written generic buffer handler, this is efficient, and save space. |
The bootloader is code for interrupts work?
Because my interruptions functioned and now no longer work?
I put the bootloader on my pic, then recorded my code that worked on it, the code ran, but the interruptions not worked.
I found this code on the Internet to put after the #fuses but not worked.
Code: |
#build (reset = 0x800, 0x808 = interrupt)
#ORG 0x00, 0x7FF {}
|
|
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Fri Nov 13, 2015 7:39 am |
|
|
I will modify the original bootloader for him to catch the new program the external EEPROM memory. I do not know then how do you know which codes (#ORG and #BUILD) I have to in order to work. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Nov 13, 2015 8:55 am |
|
|
There are two parts to what is needed.
The first is in the bootloader, and is this small section of code:
Code: |
#int_global
void isr(void) {
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
|
This adds to the bootloader, the code to re-vector the interrupts into the loaded program. It's the last part of ex_bootloader.c.
Then the compiled program to be loaded, has to be told to use this. This is done for you if you include bootloader.h (look at ex_bootload.c), which shows how to structure a program to be loaded 'with' the bootloader.
bootloader.h, should be included both by the bootloader, and by the code that is to be bootloaded. For the former, there has to be a "#define _bootloader" before loading it.
If your bootloader is a different size to the CCS one, then #define LOADER_END to the required size before you load bootloader.h.
bootloader.h, handled the #org, and the #build for you. It handles the different positions needed for all the different processor types, and automatically sets up the interrupt re-vectoring (except for the little handler shown), automatically calculating all the values based on processor type, LOADER_END, and whether this is the loader, or the loaded program. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Fri Nov 13, 2015 11:02 am |
|
|
Ttelmah wrote: | There are two parts to what is needed.
The first is in the bootloader, and is this small section of code:
Code: |
#int_global
void isr(void) {
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
|
This adds to the bootloader, the code to re-vector the interrupts into the loaded program. It's the last part of ex_bootloader.c.
Then the compiled program to be loaded, has to be told to use this. This is done for you if you include bootloader.h (look at ex_bootload.c), which shows how to structure a program to be loaded 'with' the bootloader.
bootloader.h, should be included both by the bootloader, and by the code that is to be bootloaded. For the former, there has to be a "#define _bootloader" before loading it.
If your bootloader is a different size to the CCS one, then #define LOADER_END to the required size before you load bootloader.h.
bootloader.h, handled the #org, and the #build for you. It handles the different positions needed for all the different processor types, and automatically sets up the interrupt re-vectoring (except for the little handler shown), automatically calculating all the values based on processor type, LOADER_END, and whether this is the loader, or the loaded program. |
Hello, I understood almost everything.
did not understand the part of the (#define LOADER_END)
when I put (#define LOADER_END) My code accuses mistake!
error:
my code:
Code: |
#include "18LF2685.h"
#device ADC = 16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES BBSIZ1K //1K words Boot Block size
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PROTECT //Code protected from reads
#use delay(crystal = 20000000)
#use rs232(baud = 115200, parity = N, xmit = PIN_C6, rcv = PIN_C7, bits = 8) //, stream = Modem)
#use i2c(Master, Fast, sda = PIN_C4, scl = PIN_C3)
#define LOADER_END
#include <bootloader.h>
#include "ds1307.c"
#include "mc342.c"
#include "24025.c"
#include "STRING.h"
|
my bootloader:
Code: |
#include "18LF2685.h"
#device ADC = 16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES BBSIZ1K //1K words Boot Block size
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PROTECT //Code protected from reads
#use delay(crystal = 20000000)
#use rs232(baud = 115200, parity = N, xmit = PIN_C6, rcv = PIN_C7, bits = 8) //, stream = Modem)
#use i2c(Master, Fast, sda = PIN_C4, scl = PIN_C3)
#define PUSH_BUTTON PIN_B3
#define _bootloader
#include <bootloader.h>
#include <loader.c>
#if defined(__PCM__)
#org LOADER_END+1,LOADER_END+2
#elif defined(__PCH__)
#org LOADER_END+2,LOADER_END+4
#endif
void application(void) {
while(TRUE);
}
void main(void) {
if(!input(PUSH_BUTTON))
{
printf("\r\nBootloader Version 1.0\r\n");
// Let the user know it is ready to accept a download
printf("\r\nWaiting for download...");
load_program();
}
//application(); <<<<<<<<< look, is wrong???????
}
#int_global
void isr(void) {
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Nov 13, 2015 3:04 pm |
|
|
You have to define LOADER_END, to the size needed for your loader.....
It is set automatically to the size needed by the CCS code, but if your code is larger you have to set it to clear your loader.
It has to be set for both the loader and the code. Must be the same in both. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Fri Nov 13, 2015 3:08 pm |
|
|
Ttelmah wrote: | You have to define LOADER_END, to the size needed for your loader.....
It is set automatically to the size needed by the CCS code, but if your code is larger you have to set it to clear your loader.
It has to be set for both the loader and the code. Must be the same in both. |
I understand, but I still have two doubts!
1- How do I know which size I need for my loader? how to measure?
2- I define the bootloader just as I define in my code? #include before? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Nov 13, 2015 3:17 pm |
|
|
Compile the loader.
Look how big it is.
Set LOADER_END to the end of the next program page boundary for your chip (for your chip has to be a multiple of 64 bytes -1). So 0, 63, 127 etc.. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Fri Nov 13, 2015 3:24 pm |
|
|
Ttelmah wrote: | Compile the loader.
Look how big it is.
Set LOADER_END to the end of the next program page boundary for your chip (for your chip has to be a multiple of 64 bytes -1). So 0, 63, 127 etc.. |
I understand, you can give me an example?
look at this picture with file size.
in this case, how do i?
you forgot to answer my second question.
2- I define the bootloader just as I define in my code? #include before? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sat Nov 14, 2015 2:20 am |
|
|
_Look at the examples_.
Study what they do.
Understand that they are not 'magic', or 'hiding anything'. They show exactly the order that things have to be defined to work.
The way to find the real size of the program, is to look at the .lst file generated. Easier than trying to work it out from file sizes.
If you (for example), compile the example bootloader (for a PIC18), you see at the end of the lst file:
Code: |
0372: RCALL 0500
.................... }
....................
.................... #int_global
.................... void isr(void) {
0374: SLEEP
|
The 'sleep' is always the last instruction, so we know it ends at 374.
Then if we look at bootloader.h, and what it does if the size is not defined, we see:
Code: |
#elif defined(__PCH__)
#define FLASH_SIZE getenv("FLASH_ERASE_SIZE")
#if ((0x500 % FLASH_SIZE) == 0) //IF 0x500 is even flash boundary
#define LOADER_END 0x4FF
#else
|
So it is actually setting it to 0x4FF by default, if this is a flash page boundary (for your chip it would be). They could actually get away with using 0x3FF.
So they are not trying to make the size as small as possible (this allows a little bit of space to expand without having to change things). However the 'odds' are that if your loader is doing more than just handling the serial a little differently, the size will be larger than this.... |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Sat Nov 14, 2015 10:07 am |
|
|
Ttelmah wrote: | _Look at the examples_.
Study what they do.
Understand that they are not 'magic', or 'hiding anything'. They show exactly the order that things have to be defined to work.
The way to find the real size of the program, is to look at the .lst file generated. Easier than trying to work it out from file sizes.
If you (for example), compile the example bootloader (for a PIC18), you see at the end of the lst file:
Code: |
0372: RCALL 0500
.................... }
....................
.................... #int_global
.................... void isr(void) {
0374: SLEEP
|
The 'sleep' is always the last instruction, so we know it ends at 374.
Then if we look at bootloader.h, and what it does if the size is not defined, we see:
Code: |
#elif defined(__PCH__)
#define FLASH_SIZE getenv("FLASH_ERASE_SIZE")
#if ((0x500 % FLASH_SIZE) == 0) //IF 0x500 is even flash boundary
#define LOADER_END 0x4FF
#else
|
So it is actually setting it to 0x4FF by default, if this is a flash page boundary (for your chip it would be). They could actually get away with using 0x3FF.
So they are not trying to make the size as small as possible (this allows a little bit of space to expand without having to change things). However the 'odds' are that if your loader is doing more than just handling the serial a little differently, the size will be larger than this.... |
I think I understand.
I have to open my .lst file and look at the number of SLEEP.
I convert this number to decimal and arredondo to the next higher multiple of 64 -1. correct?
in the example below, had been my #define: #define LOADER_END 0x3BF ???
hex> dec
394> 916
next multiple of 64
916> 960
960-1 = 959
dec> hex
959> 3BF
this thinking correct?
Code: |
00390: MOVWF FF8
00392: RCALL 006C
.................... //application();
....................
.................... }
....................
.................... #int_global
.................... void isr(void) {
00394: SLEEP
.................... jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
*
00008: GOTO 0508
0000C: NOP
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sat Nov 14, 2015 11:28 am |
|
|
You might as well just leave it at the default, if your bootloader is this small. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Sat Nov 14, 2015 2:59 pm |
|
|
Ttelmah wrote: | You might as well just leave it at the default, if your bootloader is this small. |
but I will also modify the bootloader for him to read the code through external EEPROM memory. understood?
it is small now, but it will get big.
It is small but not working. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sun Nov 15, 2015 9:39 am |
|
|
If you are going to be modifying it, you need to decide _now_ how large your bootloader is likely to be, when you have finished, and allocate enough space for this. Otherwise you are going to have to re-compile all the code you intend to use, when you change the bootloader. It is pointless to be adjusting the size to fit the current bootloader.... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|