|
|
View previous topic :: View next topic |
Author |
Message |
John_Lintern
Joined: 30 Sep 2004 Posts: 14
|
ex_bootloader - problem using interrupts in application prog |
Posted: Tue Sep 06, 2005 9:12 am |
|
|
I have blown a PIC18F452 with the ex_bootloader.c example program supplied with CCS.
This works fine and I have successfully downloaded a simple application program via the RS232 which flashes an LED on and off.
I had to put "#include bootloader.h" in my application program, otherwise when I download the hex file it overwrites the bootloader (I think ?).
However, now I am trying to download a more complicated program which uses an interrupt, the serial comms interrupt #RDA.
I first tried to emulate my program on the ICE2000 and set a breakpoint for when a serial comms interrupt occurs (when a character is received).
But my program (or emulator) crashes and when I halt the emulator I get a 'stack overflow' error.
Yet if I remove the include "#include bootloader.h" the program runs fine on the ICE2000.
bootloader.h only contains the following code (note that I am using PCH)...
Code: |
#if defined(__PCM__)
#define LOADER_END 0x1FF
#define LOADER_SIZE 0x1BF
#elif defined(__PCH__)
#define LOADER_END 0x4FF
#define LOADER_SIZE 0x3FF
#endif
#ifndef _bootloader
#if defined(__PCM__)
#build(reset=LOADER_END+1, interrupt=LOADER_END+5)
#elif defined(__PCH__)
#build(reset=LOADER_END+2, interrupt=LOADER_END+8)
#endif
#org 0, LOADER_END {}
#endif
|
And below is my application program...
Code: |
#include <18F452.h>
#include <bootloader.h>
#use delay(clock=20000000)
#fuses NOWDT,HS, PUT, NOPROTECT, NODEBUG, NOLVP, NOCPD, NOWRT, NOBROWNOUT
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,BRGH1OK)
int r=0; // index count for received buffer array
char RxBuffer[10]; // buffer array to store received characters
#int_RDA
void RDA_isr(void)
{
output_low(PIN_B0); // <<<<ICE2000 breakpoint set here
if ((RxBuffer[r++]=getchar())== 0x1D) // store received character into receive buffer, test to see if a carriage return has been received (\r)
{
RxBuffer[--r]=0; // make the carriage return character a zero value
r=0; // reset index count for buffer array
if(RxBuffer[0]='R')
{
write_eeprom(0xFF,0xFF);
reset_cpu();
}
}
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(INT_RDA); // enable RS232 receive data interrupt
enable_interrupts(GLOBAL); // enable all global interrupts
do
{
output_low(PIN_B0);
delay_ms (100);
output_high(PIN_B0);
delay_ms (100);
}
while(TRUE);
}
|
From further investigation the following lines in bootloader.h seem to be the problem...
Code: |
#build(reset=LOADER_END+2, interrupt=LOADER_END+8)
#org 0, LOADER_END {}
|
Does anyone have any idea what is going on and how to correct it ? |
|
|
Ttelmah Guest
|
|
Posted: Tue Sep 06, 2005 4:33 pm |
|
|
The build instruction, tells the compiler where to put the interrupt handler. However you have to understand, that the interrupt will still cause a call to the _fixed_ hardware location. This is inside the area occupied by the loader. You need to add the instruction at this point, to re-vector the interrupt to the actual handler code. What is happening, is that the interrupt is causing a call to address 0x18, and running across part of the bootloader, resulting in a stack overflow.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 10, 2007 8:50 am |
|
|
What can you do to help that? I think I'm experiencing the same problem |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 10, 2007 9:13 am |
|
|
ex_bootloader.c, shows how to perform the required relocation.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 10, 2007 9:20 am |
|
|
I am doing that.
Code: | #int_global
void pass_interrupt (void)
{
#asm
goto LOADER_END+5
#endasm
} |
The bootloader is fine. I can download new code. The bootloader code does not get overwritten. New code runs fine _until_ an interrupt is launched. It launches 7 X OK (7 bytes received = 7X int_RDA; but after that interrupts seem disabled, they don't work anymore. Also some variables are badly initialised.
If I program the PIC without bootloader it runs fine. |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 10, 2007 9:42 am |
|
|
What PIC.
Note that the relocation, is different for a 18F,and a 16F chip, and must match what is in the 'build' instruction for the bootloaded program.
Are you using a 'working' compiler (ie., not a V4 compiler)?.
It does work.
I have used the example from bootload/bootloader, as the basis of loading code in half a dozen programs without problems. All my systems use interrupts.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 10, 2007 9:50 am |
|
|
I'm really sure my bootloader is OK:
bootloader.c
Code: | #include <16F877A.h>
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#define _bootloader
#include "bootloader.h"
#define LOADER_ADDR 0x0006
#org LOADER_ADDR, LOADER_END default
#use delay (clock=4000000)
#use rs232 (baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#include "loader.c"
void application (void);
#int_global
void pass_interrupt (void)
{
#asm
goto LOADER_END+5
#endasm
}
void main (void)
{
long timeout = 0;
int8 i, triggers_found = 0;
delay_us (50); // Transmit Buffer clearen
putc ('L');
for (i = 2; i > 0; i--)
{
// while ( !kbhit() && (++timeout < 50000) ) // 5 seconds
while ( !kbhit() && (++timeout < 0xFFFF) ) // 0xFFFF i.s.o. 50000 saves 5 bytes
delay_us (100);
if ( kbhit() )
{
if ( getc() == 170 )
triggers_found++;
else
break; // invalid char received, stop waiting.
}
else
break;
}
if ( triggers_found == 2 )
{
putc ('B');
real_load_program (); // I got rid off the load_program function as it is only used for bootloaders in high memory.
}
application (); // Jump to real application
}
#org LOADER_END+1,LOADER_END+100
void application(void) // Dummy functie, eigenlijk staat hier de échte main
{
while(TRUE);
} |
bootloader.h
Code: | #define LOADER_END 0x1FF
#define LOADER_SIZE 0x17F
#ifndef _bootloader
#build ( reset = LOADER_END+1 , interrupt = LOADER_END+5 )
#org 0, LOADER_END {}
#endif |
There has to be something with interrupts, as they seem disabled sudden.. |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 10, 2007 11:21 am |
|
|
Your ORG definitions are screwed. Look where the int handler is declared in the example, and the ORG statement in front of it. Loader address, cannot be 6. The int handler is here...
Write out a list of the ORG statements from the bootloader example, and make sure that your's copy the same layout, just with the sizes altered to your requirements, and also that the sizes actually 'work' in the memory area you allocate.
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jan 10, 2007 6:09 pm |
|
|
Quote: | Loader address, cannot be 6. The int handler is here... | There is no conflict. This interrupt handler is very short, only 2 bytes, located at addresses 4 and 5.
Reception of 7 characters is possible, so it seems like the RDA interrupt is working.
The problem is most likely somewhere in the application, perhaps caused by the memory map being different in the application with and without bootloader. |
|
|
Ttelmah Guest
|
|
Posted: Thu Jan 11, 2007 3:34 am |
|
|
I agree that there should not be an obvious conflict with the int handler as shown, but there are some potential ones. If the PIC concerned has a erratum on the int handler (requiring a trailing NOP), putting things this tight will cause problems. Also, though the relocation 'jump', is only two locations long, the global return, will get put into the next address. Though not 'used', this may cause loading problems. Unless you are needing to save every byte, putting things this tight, has the potential for problems.
The obvious possibility with seven successful operations, is stack growth. However I have to ask, why 'screw' with a working system?. The demo program does work, and there are so many little fiddles with it in the posted code, that unless you follow the implications of each, tracking it all through is hard. This is why I say 'draw out' the implications of each change, and what is going wrong, may then become obvious.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Fri Jan 12, 2007 4:04 am |
|
|
Hi,
this is the original ex_bootloader.c from CCS with very small modifications using their original loader.c. That program is causing the exact same problems:
* interrupts seem disabled after a certain point.
* variables are changed somewhere in the beginning of the program and I don't know why they are.
* the program without bootloader works fine
Might you have any suggestions?
Code: | #include <16F877A.h>
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#use delay(clock=4000000)
#org 0x06,0x11 default
#use rs232 (baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#define _bootloader
#include "bootloader.h"
#include <loader.c>
#org LOADER_END+1,LOADER_END+10
void application (void) // Dummy functie, eigenlijk staat hier de échte main
{
putc('A');
while(TRUE);
}
#ORG 0x12,0x6C
void main (void)
{
long timeout = 0;
putc ('B');
while ( !kbhit() && (++timeout < 50000) ) // 5 seconds
delay_us (100);
if ( kbhit() )
{
if ( getc() == 170 )
{
timeout = 0;
while ( !kbhit() && (++timeout < 50000)) // 5 seconds
delay_us (100);
if ( kbhit () )
if ( getc() == 170 )
{
putc ('B');
load_program ();
}
}
}
application (); // Jump to real application
}
#org default
#int_global
void isr (void)
{
#asm
goto LOADER_END+5
#endasm
} |
|
|
|
Ttelmah Guest
|
|
Posted: Fri Jan 12, 2007 5:15 am |
|
|
I'm sorry, but you have been leading us up the 'garden path'...
The obvious problem is in the main program, not the bootloader. The test is faulty for 'R'.
Further, even if this test was right, if an 'R' is received, and other data is coming in, the UART _will_hang. The reason, is that write_eeprom, takes typically 4mSec, which is four character times. On top of this, the test itself is coded, so it'll happen every time. This code cannot be running OK without the bootloader...
The hardware only buffers two characters, before OERR is set, and as written, the code to potentially clear this, has already been called, and is not called again, which will hang the chip. Code the interrupt handler as:
Code: |
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS)
//BRG10K, is only needed on chips that have the hadware fault here.
//ERRORS is needed if a getc, is to clear the UART if hung...
#bit RCIF=0xF9E.5
#int_RDA
void RDA_isr(void) {
do {
output_low(PIN_B0); // <<<<ICE2000 breakpoint set here
if ((RxBuffer[r++]=getchar())== 0x1D) {
// store received character into receive buffer, test to see
//if a carriage return has been received (\r)
RxBuffer[--r]=0;
// make the carriage return character a zero value
r=0; // reset index count for buffer array
if(RxBuffer[0]=='R') {
//Note the error here '=', not '=='
write_eeprom(0xFF,0xFF);
reset_cpu();
}
}
} while (RCIF);
//This will loop again if another character is waiting, and at the same
//time, clear the hardware error if it has occurred.
}
|
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Fri Jan 12, 2007 7:35 am |
|
|
I don't know if the TS still is following this actually? But the TS is not the same as me. I have a completely different main program.
I do have _alot_ of global variables; is that a problem when using bootloaders? |
|
|
BOB_SANTANA
Joined: 16 Oct 2006 Posts: 110 Location: HOVE, EAST SUSSEX
|
|
Posted: Fri Jan 12, 2007 9:37 am |
|
|
Chris
I can see you have problems with your bootloader
Do you really have to use Bootloader.c ,loader.c etc for your application
why not try some standard bootloader of the net
http://www.ccsinfo.com/forum/viewtopic.php?t=29339 _________________ BOB_Santana |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Fri Jan 12, 2007 11:06 am |
|
|
Yes I know, but I want to write my own bootloader so I can adapt the code to my own desires. Thanks for the advise!
Last edited by Christophe on Fri Jan 12, 2007 3:16 pm; edited 1 time in total |
|
|
|
|
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
|