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

Bootloader with two apps flashing pattern

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



Joined: 13 Dec 2024
Posts: 2

View user's profile Send private message

Bootloader with two apps flashing pattern
PostPosted: Fri Dec 13, 2024 4:59 am     Reply with quote

Hi,

I'm trying to prepare bootloader on PIC18F46K20 with two app slots. As target application will do OTA upgrade's, it'll save life when something go wrong during flashing so we can fallback to previous working slot.

I've expanded bootloader example from CCS to have two app slots:

device_bootloader.c
Code:
#include <stdio.h>
#include <stdint.h>
#include <string.h>


//#define BOOTLOADER_MODE2X
#define BOOTLOADER_AT_START

#include <bootloader.c>

#define APP_A_START 0x0800
#define APP_B_START 0x8000

#org APP_A_START+1,APP_A_START+2
void application_A(void) {
  while(TRUE);
}

#org APP_B_START+1,APP_B_START+2
void application_B(void) {
  while(TRUE);
}

static uint8_t APP_SEL = 0;
void main(void) {
   set_tris_b(0b11111011);     // Set port B I/O pins directions
   delay_ms(100);
   printf("\r\nBootloader Version 1.0\r\n");

   if(!MODE_SW){
       APP_SEL = 1;
       printf("\r\nAPP A\r\n");
   } else {
       APP_SEL = 2;
       printf("\r\nAPP B\r\n");
   }
   if(!RATE_SW)
   {
      printf("\r\nUpgrade...\r\n");

      // Let the user know it is ready to accept a download
      printf("\r\nWaiting for download...");
      load_program();
   }
   printf("\r\nLaunching program...\r\n");
   if(APP_SEL == 1){
          application_A();
   }
   if(APP_SEL == 2){
          application_B();
   }
}

#int_global
void isr(void) {
   if(APP_SEL == 1){
          jump_to_isr(APP_A_START+8);
   }
   if(APP_SEL == 2){
          jump_to_isr(APP_B_START+8);
   }
}


Flashing apps via SIOW.exe is working totally fine. When I've compiled version for slot A (with adresses setted here as LOADER_END) it's putting into slot A and loading correctly, when I've compiled version for slot B it's putting into slot B and also loading correctly.

device_app.c

Code:
#define LOADER_END 0x07FF
#define APP_A_END 0x7FFF

#build(reset=LOADER_END+1:LOADER_END+8, interrupt=LOADER_END+9:LOADER_END+16)
#org 0, LOADER_END {}

#org default
#org LOADER_END+17, 0x7FFF
void main(void)
{
   delay_ms(100);
   fprintf(STD_PORT,"APP started\r\n");
   while(1){
       fprintf(STD_PORT,"Hello\r\n");
       delay_ms(1000);
   }
}


Header (same for app and bootloader):

Code:
#include <18F46K20.h>
#device pic18f46k20
#device CCS4
#device ADC=10

#case // symbols case sensitive
#device HIGH_INTS=TRUE
#device PASS_STRINGS=IN_RAM
#device ADC=10

#ifdef __DEBUG
#device ICD=TRUE
#FUSES HS,NOPROTECT,NOPUT,NOLVP,NOMCLR,NOWDT,DEBUG
#use delay(clock=64000000)
#else
#FUSES HS,NOPROTECT,NOPUT,NOLVP,NOMCLR,NOWDT,NODEBUG, INTRC_IO
#use delay(clock=64000000,restart_wdt)
#endif


Idea I want to achieve is to compile app without slot awareness so no matter which slot will be flashed app will be loaded into its adress correctly. First thing in my mind tell me "hey just offset APP_A adresses by 0x7800 when flashing B!", it even looked fine in hex viewer, then I realised that it doesn't affect any asm goto statements.

Is there any way to achieve that solution?

Peace,
Marcin
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Fri Dec 13, 2024 5:55 am     Reply with quote

No,
Code works at the address it is complied for. It won't work at a different
address. Calls, and absolute jumps are to specific locations.
Many larger processors can be generated to support relative jumps across
the whole of memory, but the PIC does not support this.
So it needs to be compiled for where it is meant to go.
mpopko



Joined: 13 Dec 2024
Posts: 2

View user's profile Send private message

PostPosted: Fri Dec 13, 2024 6:14 am     Reply with quote

Ttelmah wrote:
No,
Code works at the address it is complied for. It won't work at a different
address. Calls, and absolute jumps are to specific locations.
Many larger processors can be generated to support relative jumps across
the whole of memory, but the PIC does not support this.
So it needs to be compiled for where it is meant to go.


So we have no other option than to build slot A and slot B hexes and push correct ones on demand.

Thanks for clarification!
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Fri Dec 13, 2024 10:30 am     Reply with quote

I developed something similar quite some time ago. The PCBA had a dedicated memory which stored what you refer to as 'slots'. An OTA update would interact with the current running application, and it would simply place the update in an unused/old slot. Once complete, it would then trigger a processor reset which would invoke the bootloader.

The bootloader's job was pretty easy - examine the external memory to see if a new image had been placed there. If so, download that new image into the application space.

If you want it to be 'bulletproof' you have to place a lot of thought into these images and tagging them as 'new/to be loaded', 'reliability unsure', 'proven/active', and 'unreliable'. This is necessary for the bootloader to be able to automatically detect if there was a problem with the previous update and to be able to automatically 'roll back' the application to a known good version in the event of something bad happening. The application itself has to have the ability to mark itself as 'proven/active' as long as certain conditions are met: watchdog doesn't activate for x cycles / all code paths exercised in situ.
allenhuffman



Joined: 17 Jun 2019
Posts: 554
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Dec 13, 2024 6:38 pm     Reply with quote

mpopko wrote:

So we have no other option than to build slot A and slot B hexes and push correct ones on demand.


The first OS I learned on was Microware's OS-9/6809. It was fully position independent, and I thought the whole world was that way ;-) We had to do something similar on our system with an 'A' and 'B' build, with the firmware updated pushing whichever file was needed.

Our PIC24 system had one vector table at the start, so when loading 'B' it would load the app portion, then update the IVT with jumps to 'B'. The fall-back to 'A' stuff was never implemented, so I have been doing a similar bootloader the past week or so (based on work I researched in this forum three years ago).

Pity PIC doesn't have the kind of following Arduino has, or we'd have tons of wikis, YouTube videos, blogs, etc. that would already have figured all this out ;-)

Good luck!
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
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