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 CCS Technical Support

interrupt in bootloader

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
edgarp



Joined: 18 Jun 2024
Posts: 6

View user's profile Send private message

interrupt in bootloader
PostPosted: Fri Jun 28, 2024 5:42 pm     Reply with quote

device : 16F1939

compiler version: 5.116

from what I understood in this post,
https://www.ccsinfo.com/forum/viewtopic.php?t=60380
if you use the bootloader example the ISR would be placed at the application code area not bootloader's area, making the bootloader dependent on the application.

I would like to make it so that the interrupt is placed in the bootloader's area and make the application use the ISR placed on the bootloader.

to get it to work like this I Would like to know if the following configuration would be what you would expect to see.



Code:

#define LOADER_END 0x1ffF


#build(reset=LOADER_END+1)

 #org 0, 0x7FF {}
  #org 0x800, 0xFFF{}
 #org 0x1000, 0x17FF {}
 #org 0x1800, 0x1ffF {}



#IMPORT (FILE=Botlloader_interrupt_test.hex,HEX,RANGE=0:LOADER_SIZE)


BYTE next_in = 0;
BYTE global_flag =0;
BYTE JUMP_flag =0;

#byte global_flag = 40
#byte next_in = 44
#byte JUMP_flag = 48

//#define TICKS_PER_SECOND 10000
void main(void)
{
   unsigned int16 tick;
   
    printf("Application 1.2 running\r\n");
    enable_interrupts(INT_RDA);
    enable_interrupts(GLOBAL);
    tick = get_ticks();
   
   for(;;)
   {
      if (global_flag)
      {
        if ((get_ticks() - tick) >= TICKS_PER_SECOND/5)
        {
           tick = get_ticks();
           output_toggle(EXT_WATCHDOG_IO);
        }
      }
      else
      {
        if ((get_ticks() - tick) >= TICKS_PER_SECOND/10)
        {
            tick = get_ticks();
            output_toggle(EXT_WATCHDOG_IO);
        }
        if (JUMP_flag)
        {
//          application();
        }
     
      }   
   }
}



I would be using the flags set by the interrupt in the main loop.

the bootloader configuration would be like this :
Code:

#define _bootloader 1
#define LOADER_END 0x1ffF//


#org LOADER_END+1,LOADER_END+3
void application(void) {
  while(TRUE);


#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
BYTE global_flag =0;
BYTE JUMP_flag =0;

#byte global_flag = 40
#byte next_in = 44
#byte JUMP_flag = 48


#int_rda
void serial_isr()
{
   int t;
   buffer[next_in]=getc();
   t=next_in;
   if (  buffer[next_in] == 0x03)
   {
   global_flag =  ~global_flag;
   }
      if (  buffer[next_in] == 0x05)
   {
   JUMP_flag =  ~JUMP_flag;
   }
   
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==3)
     next_in=0;           // Buffer full !!
   
     printf("B");
}

}


void main(void)
{
   unsigned int16 tick;
   
    printf("Bootloader 1.1 running\r\n");
    enable_interrupts(INT_RDA);
    enable_interrupts(GLOBAL);
    tick = get_ticks();

   for(;;)
    {
        if (global_flag)
        {
          if ((get_ticks() - tick) >= TICKS_PER_SECOND/2)
          {
             tick = get_ticks();
             output_toggle(EXT_WATCHDOG_IO);
          }
        }
      else
      {
        if ((get_ticks() - tick) >= TICKS_PER_SECOND/4)
        {
            tick = get_ticks();
            output_toggle(EXT_WATCHDOG_IO);
        }
        if (JUMP_flag)
        {
             application();
        }
     
      }   
   }
}




I Kept things that are not relevant out of the code, but if it is easier to follow I could just post the whole file.

-would I need to make use of the #build(share_interrupts) directive at all?

-at the application code it the build directive is only setting the reset, would it be good to also set the interrupt like this ?
// #build(reset=LOADER_END+1, interrupt=4)


Thanks in advance for any help.
Edgar
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

Re: interrupt in bootloader
PostPosted: Fri Jun 28, 2024 7:39 pm     Reply with quote

I know a thing or two about bootloaders. The question to ask yourself is why do you need a bootloader to support interrupts?

A bootloader really has a single task - to bootload an image.

Adding interrupt capability in the bootloader, when unnecessary, just adds complexity and latency to the application. It typically requires remapping of interrupt vectors, and double jump on interrupt. The first to the interrupt handler of the bootloader and the second to the application.

The method I use is to reserve the bootloader vectors and the remainder of the first page of program memory for the application. The application is compiled ti reserve the program memory space used by the bootloader. This way the application image can run unchanged whether or not the bootloader is present. This greatly simplifies application development and debugging.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!


Last edited by asmallri on Wed Jul 03, 2024 6:19 pm; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sat Jun 29, 2024 5:32 am     Reply with quote

There can be an advantage to doing this, but it does bring potential
issues.
So (for example), imagine you have a very well written neat serial
handler, and are using no other interrupts. Provided you are 100%
certain that this will never need to change, using it in both the
bootloader and the main code could make a lot of sense. Now the
issues are that first this implies you are stuck with the handlers in
the bootloader. If any fault is found, you have to program the whole
chip, and that you are restricted to only using the interrupts for which
the bootloader has handlers.
However you then have to realise a very simple thing. Your code never
actually 'uses' an interrupt handler. It only uses the variables that connect
'to' it. So in the example of the serial ISR, you have the buffered gutc
routine, which reads from the buffer, and updates the counters, and the
interrupt handler itself, then handles putting the data into this buffer.
So you can use the routine in the bootloader, by simply declaring these
same variables in the main code, and #locating these to the locations
used in the bootloader, then enabling the interrupt. Have a duplicate
buffered getc routine, and the bootloader ISR will then handle this
interrupt.
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Sat Jun 29, 2024 6:10 am     Reply with quote

You have not convinced me but maybe this is because I use common CPU boards across multiple projects. The bootloaders, once installed, stay on the board irrespective of the project / application. I would rarely ever changed the bootloader unless I am using encryption in which case I have to accommodate different encryption keys and mechanisms.

Having a dependency between the bootloaders and applications is, in my opinion just creating a problem down the track.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sat Jun 29, 2024 9:35 am     Reply with quote

For 99% of situations, I'd say you are right. The 1%, is the odd situation,,
where (for example), you are very restricted on space, and have just
enough room in the allocated page for the bootloader, to have this extra
handling, which then saves space for the main program.
I did this decades ago, when dealing with an early PIC, and was very
short of space, but needed to offer bootloader updates for the main code.
In recent years, where I will always if possible use a chip larger than I
actually need, I have never had to do it again.... Very Happy
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Sun Jun 30, 2024 6:53 pm     Reply with quote

Ttelmah wrote:
For 99% of situations, I'd say you are right. The 1%, is the odd situation,,
where (for example), you are very restricted on space, and have just
enough room in the allocated page for the bootloader, to have this extra
handling, which then saves space for the main program.
I did this decades ago, when dealing with an early PIC, and was very
short of space, but needed to offer bootloader updates for the main code.
In recent years, where I will always if possible use a chip larger than I
actually need, I have never had to do it again.... Very Happy


I agree - this would be a valid use case but, for anyone designing a new product that needs to do this, it is an indication that they should have spent a few more cents to buy the next variant of the processor with the amount flash to support the what if ...
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
edgarp



Joined: 18 Jun 2024
Posts: 6

View user's profile Send private message

Re: interrupt in bootloader
PostPosted: Tue Jul 02, 2024 10:26 am     Reply with quote

asmallri wrote:
I know a thing or two about bootloaders. The question to ask yourself is why do you need a bootloader to support interrupts?

A bootloader really has a single task - to bootload an image.

Adding bootloader capability in the bootloader, when unnecessary, just adds complexity and latency to the application. It typically requires remapping of interrupt vectors, and double jump on interrupt. The first to the interrupt handler of the bootloader and the second to the application.

The method I use is to reserve the bootloader vectors and the remainder of the first page of program memory for the application. The application is compiled ti reserve the program memory space used by the bootloader. This way the application image can run unchanged whether or not the bootloader is present. This greatly simplifies application development and debugging.


this bootloader uses encrypted firmware over a proprietary protocol which the application also uses, it is transmitted over I2C to an slave device.

Latency or complexity is not a priority for this task but we would like to make the bootloader completely standalone from application.
edgarp



Joined: 18 Jun 2024
Posts: 6

View user's profile Send private message

PostPosted: Tue Jul 02, 2024 10:41 am     Reply with quote

Ttelmah wrote:
There can be an advantage to doing this, but it does bring potential
issues.
So (for example), imagine you have a very well written neat serial
handler, and are using no other interrupts. Provided you are 100%
certain that this will never need to change, using it in both the
bootloader and the main code could make a lot of sense. Now the
issues are that first this implies you are stuck with the handlers in
the bootloader. If any fault is found, you have to program the whole
chip, and that you are restricted to only using the interrupts for which
the bootloader has handlers.
However you then have to realise a very simple thing. Your code never
actually 'uses' an interrupt handler. It only uses the variables that connect
'to' it. So in the example of the serial ISR, you have the buffered gutc
routine, which reads from the buffer, and updates the counters, and the
interrupt handler itself, then handles putting the data into this buffer.
So you can use the routine in the bootloader, by simply declaring these
same variables in the main code, and #locating these to the locations
used in the bootloader, then enabling the interrupt. Have a duplicate
buffered getc routine, and the bootloader ISR will then handle this
interrupt.


yes, this is a risk we are willing to take, extensive testing will be done to try to avoid this to happen.

We would like to keep the bootloader completely standalone from the application incase the application memory area gets corrupted. That's why we would like to put the interrupt on the bootloader and make the application use the variables hooked to it. do you have any comments on the code itself ?specially the set up of the interrupt.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Wed Jul 03, 2024 1:33 am     Reply with quote

I have to reiterate Andrews comment. There is honestly no reason to use
the interrupt in the bootloader. So just poll the serial here, and use interrupts
only in the main code. It is much neater and less likely to give issues.
If you do decide to embed an ISR, there is nothing special involved at all
just enable the interrupt in the main, and have a copy of the bgetc routine
here that references the variables #located at the locations use in the
bootloader.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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