Jump to content
Sign in to follow this  
robcarter

Bootloader Question

Recommended Posts

I have compiled the microchip bootloader AN1310 and set it to locate at address 0, with the application program moved to 0x200 using the linker -rb option. everytrhing works fine until the interrupts are enabled.

The problem I have is that the microchip interrupt routine saves pclath before resetting it to 0 and then jumping to 0x204, this in itself is not a problem until an interrupt occurs when the pc is in the high area of memory at this point the return from interrupt address will be wrong as the source boost compiler will have stored the wrong pclath value in its int routine.

I can't put a straight goto 0x200 at 0x4 as again pclath could have bits set so the routine wouldn't jump to the correct interrupt.

Is there a way of stopping the compiler generating the interrupt context saving code so i can write my own, or are the symbols used for context saving the same each time so I can access them wth some asm code, swap the correct pclath value over and then exit the interrupt with the correct pclath value.

btw i'm using pic 16F887

 

Share this post


Link to post
Share on other sites

 

Is there a way of stopping the compiler generating the interrupt context saving code so i can write my own, or are the symbols used for context saving the same each time so I can access them wth some asm code, swap the correct pclath value over and then exit the interrupt with the correct pclath value.

 

 

 

Just dealing with that last question, yes it's possible to do this and I just figured it out for a program I've been working on. What you do is to avoid telling the compiler that you have an interrupt, but locate your code at address 0x0004. If interrupts are enabled, we know that the PIC jumps to address 4, so anything that you've placed there will be executed. Here's a section of my program that contains the start of the interrupt, and you can see I've commented out the original "interrupt" designation and replaced it with my own function name called "rupt()". Note that you do have to call "rupt()" from somewhere, or it will look like dead code and won't compile, and obviously that call must be from a place in your program that won't actually execute. I always do a typedef so "byte" is an unsigned char.

 
void rupt(void)@4
//void interrupt(void)                                          // Interrupt from TMR1 only
{
byte i, mask;
byte fsr_sav, sta_sav;
byte w_sav@0x7F;
 
  asm
  {
    MOVWF _w_sav
    SWAPF _status, W
    //    BCF _status, 0x05                                   // Comment out because compiler
    //    BCF _status, 0x06                                   // adds these lines automatically
    MOVWF _sta_sav
  }
  fsr_sav = fsr;
 
  bit_clear(pir1, TMR1IF);                                  // Clear this interrupt's flag, no need to test because TMR1 is the only one
 

Share this post


Link to post
Share on other sites

Thanks, that's more or less what i ended up doing:

I added the following to the microchip bootloader (set to load at 0x0)

w_int equ 0x70
stat_int equ 0x71
pclath_temp equ 0x72

ORG 0x0004
InterruptVector:

movwf w_int ; copy w to temp register
swapf status,W ; swap status to be saved into w
clrf status ; bank 0, regardless of current bank, clears irp,rp1,rp0
movwf stat_int ; save status to bank zero status_temp register
movf pclath, W ; only required if using pages 1, 2 and/or 3
movwf pclath_temp ; save pclath into w
clrf pclath ; page zero, regardless of current page
goto 0x20b

Then I added this to my code:

volatile uchar w_int@0x70;
volatile uchar stat_int@0x71;
volatile uchar pclath_temp@0x72;

 

void int_handler(void) @0x204
{
asm{
movwf _w_int ; copy w to temp register
swapf _status,W ; swap status to be saved into w
clrf _status ; bank 0, regardless of current bank, clears irp,rp1,rp0
movwf _stat_int ; save status to bank zero status_temp register
movf _pclath, W ; only required if using pages 1, 2 and/or 3
movwf _pclath_temp ; save pclath into w
clrf _pclath ; page zero, regardless of current page
}

//the goto 0x20b jumps to here
// int code goes here

 

asm{
movf _pclath_temp, W ;restore pclath
movwf _pclath ;move w into pclath
swapf _stat_int,W ;swap status_temp register into w
;(sets bank to original state)
movwf _status ;move w into status register
swapf _w_int,F ;swap w_temp
swapf _w_int,W ;swap w_temp into w
retfie ; do not enable global.
}

}

and set the compiled code to start at 0x200 using -rb 0x200. I put the jump to the end of the int entry to avoid any problems with pclath.

I haven't tested this fully yet but it appears to work ok.

Share this post


Link to post
Share on other sites

I need to make an addition to the message I posted last month. Yes, you can subsitute your own code for the Boostc interrupt function. But if you do, you can't do it the way I showed. Where I failed was using local variables in my function, and when I thought about it (prompted by mysterious bugs) I realized that it had to be a mistake. The issue is that to the compiler, that block of code is just a function called from main(), and its local variables only have to be selected so as not to interfere with variables in use by main(). But in fact it's an interrupt which can be executed from anywhere, so any local variables used by any subroutines in the entire program (unless you have interrupts turned off) may confict with the variables in the interrupt. The only solution is to declare all the variables used by the interrupt either global or static. Not only this, but you have to inspect the disassembly file to see if the compiler has used scratchpad locations, and if there are any, you must re-write the code to cause them to go away, or else you have to save them at the start of the interrupt and then restore them. This is for the same reason as the elimination of local variables--the same memory bytes may be used elsewhere in the program. And although I didn't forget to do it, I didn't say it here--of course, any interrupt must end with a RETFIE instruction. So it's a technique that can work, but there are pitfalls along the way.

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...