CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

ex_bootloader - problem using interrupts in application prog
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
John_Lintern



Joined: 30 Sep 2004
Posts: 14

View user's profile Send private message Send e-mail

ex_bootloader - problem using interrupts in application prog
PostPosted: Tue Sep 06, 2005 9:12 am     Reply with quote

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







PostPosted: Tue Sep 06, 2005 4:33 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 10, 2007 8:50 am     Reply with quote

What can you do to help that? I think I'm experiencing the same problem
Ttelmah
Guest







PostPosted: Wed Jan 10, 2007 9:13 am     Reply with quote

ex_bootloader.c, shows how to perform the required relocation.

Best Wishes
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Wed Jan 10, 2007 9:20 am     Reply with quote

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







PostPosted: Wed Jan 10, 2007 9:42 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 10, 2007 9:50 am     Reply with quote

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







PostPosted: Wed Jan 10, 2007 11:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 10, 2007 6:09 pm     Reply with quote

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







PostPosted: Thu Jan 11, 2007 3:34 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jan 12, 2007 4:04 am     Reply with quote

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







PostPosted: Fri Jan 12, 2007 5:15 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jan 12, 2007 7:35 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jan 12, 2007 9:37 am     Reply with quote

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 Smile
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Fri Jan 12, 2007 11:06 am     Reply with quote

BOB_SANTANA wrote:
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


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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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