|
|
View previous topic :: View next topic |
Author |
Message |
Keith Guest
|
Bootloader changes application behavior |
Posted: Sat Dec 02, 2006 4:34 pm |
|
|
My application (written using PCH v 4.014) for PIC 18F4580 behaves differently when run with my bootloader than without. Can someone tell me how the bootloader is changing the execution context of the application?
<< NOTE: As best I can tell, the application behaves as expected when INT_RDA and INT_TBE are not used, but when they are used, it behaves anomalously. When I run it without the bootloader, it always behaves as expected. In both tests, I'm comparing the exact same application hex file, once loaded via a programmer, and once loaded via the bootloader. The bootloader and application have the same FUSES. >>
My bootloader is checking the value in a byte of EEPROM to decide whether or not to execute the application. Here are the instructions:
Code: |
ORG 0000
GOTO decision
...
decision:
MOVFF INTCON,@@C0
BCF INTCON.GIE/GIEH
CLRF EEADR
BCF EECON1.CFGS
BCF EECON1.EEPGD
BSF EECON1.RD
MOVF EEDATA,W
BTFSC @@xC0.7
BSF INTCON.GIE/GIEH
SUBLW 11
BNZ skip
GOTO 1000 ; Application Main
skip:
GOTO 0872 ; Bootloader Main
|
The bootloader does not use interrupts, but the application does. The bootloader remaps the interrupt vector to 0x1008, which is what the application expects. [i.e. #build(reset=0x1000, interrupt=0x1008) ]
Any suggestions would be appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Dec 02, 2006 5:13 pm |
|
|
I did a bootloader for a project several years ago. I haven't done one
since then, so I'm not completely up-to-date on it. But I remember
taking care to make sure that the bootloader code didn't use any CCS
library functions. That's because you can't guarantee that the library
code will be in the same place when you install a new user program.
I didn't use any code that comes from explicitly invoked libraries such
as #use rs232(), and I also didn't use any code from implicit libraries,
such as integer math operations. This means library routines such as
@MUL88, etc. You can see that code in the .LST file if you comment
out the #nolist statement in the PIC's .H file.
So I wrote my own putc() and getc() routines, and other ones as well,
to reside in the bootloader area.
To solve your problem, I would look for any functions or RAM that are
used in common between the user code and the bootloader.
Somewhere, there will be a conflict. It might be in library functions,
or perhaps user functions, or maybe scratch variables in RAM, or user
RAM. I don't know the structure of your program, but I would guess
that somehow, one part of your program is "stepping on" another part
(in terms of RAM) or that some function is no longer at the expected
address. |
|
|
Keith Guest
|
|
Posted: Sat Dec 02, 2006 9:53 pm |
|
|
Thanks for your response. I should have noted that the bootloader program resides between 0x0000 and 0x0FFF, and that the application program resides between 0x1000 abd 0x7FFF -- so the only code they share is the few instructions I quoted.
CCS library functions are duplicated -- the bootloader has a "putc" and the application has a "putc", but they do not reside at the same place, and only one is ever used after a reset. It's like a dual-boot PC -- you can have Linux and Windows on the same PC. They both use RAM, but they don't conflict with each other because you have to reset the computer to change to the other.
--- Therefore, the only possible interaction is that the instructions I listed change the cpu's execution state before starting the application program. Or somehow the configuration registers are different (but I think they should be the same because I'm using the same FUSES).
I think the solution must be to understand what assumptions the C-compiler makes about the CPU's initial execution state. |
|
|
Ttelmah Guest
|
|
Posted: Sun Dec 03, 2006 4:47 am |
|
|
You need to add an interrupt relocation 'jump' to the bootloader.
In the _bootloader_, you need:
Code: |
#int_global
void relocate(void) {
jump_to_isr(0x1008);
}
|
The 'build' statement, tells the compiler to write the ISR handler at the specified address. However you also need code to 'reserve' the hardware location from being overwritten by the bootloader, and to physically 'jump' to the new ISR handler. The declaration above does this. Unless you do this, part of the bootloader code can sit over the hardware interrupt jump location, giving totally unpredictable results, and you will never actually call the required routines...
Best Wishes |
|
|
|
|
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
|