View previous topic :: View next topic |
Author |
Message |
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
What registers should I save and restore...? (Interrupt) |
Posted: Sat Mar 06, 2021 8:22 pm |
|
|
What registers should I save and restore in a global interrupt handler?
The last time I used ASM code was about 2008 and as far I remember I always save WREG, STATUS, BSR and FSR0H:L and must be saved and restored in a right order.
Should I consider another register?
I don't know if CCS uses another registers Maybe FSR1H:L?
I just need to handle UART1 TX and RX on a PIC18F67J50 at high speed. _________________ Electric Blue |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sat Mar 06, 2021 8:41 pm |
|
|
Why not just let the compiler handle it ?
While the compiler defaults to saving a lot of registers, you can have it save just the 'minimum'.
I have to ask what you consider 'high speed' as I have used a variation of their ex_sisr.c for years in the 18f46k22 without any problems.
Jay |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Sat Mar 06, 2021 9:04 pm |
|
|
Is a bootloader firmware that must handle a GPRS modem to perform a FOTA update and since the bootloader only have a #int_global ISR.
I'm thinking in to use some routines(cloned in boot area) from the real program to handle the modem and those routines was created to run with interrupts.
I can make a inline code but is a lot to rework.
Something like this.(Is not finished)
Code: |
//Same variable declaration on boot and main program
#define BootMode 'B'
unsigned int8 isrMode;
#locate isrMode=0x0F3F
#int_global
void isr()
{
if(isrMode!=BootMode)
{
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
else
{
//Save context
#asm //From ex_glint.c
//store current state of processor
MOVWF save_w
SWAPF status,W
BCF status,5
BCF status,6
MOVWF save_status
// Save anything else your code may change
// You need to do something with PCLATH if you have GOTOs
#endasm
if(interrupt_active(INT_RDA)
{
SendGSM_TxBuffer();
}
else if(interrupt_active(INT_TBE)
{
SendGSM_TxBuffer();
}
//Restore context
#asm //From ex_glint.c
// restore processor and return from interrupt
SWAPF save_status,W
MOVWF status
SWAPF save_w,F
SWAPF save_w,W
#endasm
}
} |
_________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Mar 07, 2021 12:50 am |
|
|
The answer is, it depends what you use.
You need to look through the assembler for the code your interrupt
routine actually uses, and save every register used inside the routine
(and the W, status etc.).
However simpler, to just copy what the compiler does, and save every
register. That way nothing can be missed.
Remember you can 'use interrupts', without 'using interrupts', in the
bootloader, by simply not enabling the global interrupt, and instead polling
the interrupt flags in your routine. This then gets rid of the need to do
handling like you are trying to do.
Also remember that what you are showing, would mean that nothing at
all in the interrupt code in the loaded program can ever change. If you
change even one byte in an interrupt routines, the addresses will shift,
and result 'disaster', since these are hardwired into your bootloader
as shown. A way 'round' this is to use a jump table stored at a fixed location
in the 'main', that contains the addresses of the routines you want to use,
then the address in this table can be used instead of the direct jump. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sun Mar 07, 2021 6:10 am |
|
|
re: Quote: | since the bootloader only have a #int_global ISR |
If you only want interrupt from UART during the bootloader program code, then only enable it, you don't have to enable other interrupts from say timers ,SPI, I2C, etc.
'Global' allows whatever interrupts you want, it doesn't enable ALL of them.
While I don't use a bootloader, lots here do probably variations of the CCS supplied example. haven't seen too many posts about 'it doesn't work'. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Mar 07, 2021 7:23 am |
|
|
You are fractionally missing what he is trying to do.
He has the #int_global, to redirect the interrupts to the loaded program.
Standard code.
He is then adding a test inside this to see if he is in 'bootloader' mode
and if he is, instead use two interrupts (RDA, and TBE), with these then
actually calling routines that are inside his main code!....
As I've already outlined, there are huge potential problems with this.
|
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Sun Mar 07, 2021 10:12 am |
|
|
No, I'm not calling routines that are inside my main code, I have cloned them in the boot area; but yes, I'm adding a test inside this to see if is in 'bootloader' mode or not, so the isr jumps to bootloader isr or to main isr in normal mode. _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Mar 07, 2021 10:47 am |
|
|
OK. That makes things enormously easier!...
If the serial routines are using indexed accesses to buffers, then a lot
or registers will be involved. Expect to have to save perhaps 8 other
registers than W and status. |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Sun Mar 07, 2021 11:54 am |
|
|
Now I'm thinking in to do a superloop, as you suggested, so now I'm checking if is there some routines that takes too much time, like write in to the EEPROM. _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Mar 08, 2021 1:56 am |
|
|
If you look at the standard bootloader, this is 'why' it has to have handshaking.
It stops transmission, while the write takes place.
Understand, that using or not using the interrupt, makes no difference
to this. During a program memory write, the whole CPU halts. Complete
'non operation' during this. Whatever protocol you use to actually send the
data to be written, this has to be 'built in' to how it works.... |
|
|
|