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

solved: Bootloader - remove or relocate startup code

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



Joined: 29 Aug 2008
Posts: 11

View user's profile Send private message

solved: Bootloader - remove or relocate startup code
PostPosted: Thu Mar 27, 2025 4:28 am     Reply with quote

Hi all,

i am using the USB-uC bootloader from JohnnyDrazzy. https://github.com/johnnydrazzi/USB-uC

The bootloader enumerates as usb thumb drive if there is no firmware present or a tact switch is pressed during powerup.

After dropping the new .hex file to the drive folder the firmware is updated and the PIC resets.
I like the idea updating the firmware just by drag and drop.

The bootloader i am using is written in assembly and fits completely in one flash page starting from address 0x00.
It jumps to fixed addresses for program start and interrupt table. It took a while to find out how to tell the CCS compiler but now it works perfectly.

Maybe there is a more elegant way:

Code:
#define void progVector(void)         // program vector for bootloader
#define void intVector(void)         // interrupt vector for bootloader

#build(interrupt=0x1f00)            // start address for interrupt service
#org 0x008, 0x7ff {}                  // do not use bootloader page

#org 0x800,0x803                           // jump vector for bootloader
void progVector() {goto_address(0x808);}

#org 0x804,0x807                           // jump vector for bootloader
void intVector() {goto_address(0x1f00);}


Last issue is that i have to remove the startup code from the .hex file manually. Otherwise it would overwrite the bootloader code.
Is there a way to tell the compiler to not do any startup code? I mean to put nothing in the address range of the first flash block?

Thanks in advance
Chris

Compiler version 5.015
Target PIC16F1459


Last edited by chrhartz on Fri Mar 28, 2025 11:49 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19761

View user's profile Send private message

PostPosted: Thu Mar 27, 2025 11:27 am     Reply with quote

Of course it is. You don't want most of what you show. Just a build statement,
with the reset vector, and the interrupt vector:

#build (reset=0x800, interrupt=0x1f00)

This builds the code starting at 0x800, with its interrupt location at 0x1F00.

Bit strange to stick the interrupts up so high, since it means the main code
will be split around this code. Normally the interrupts are put immediately
above the code start jump.

Itr is the jump to where you are declaring the code in your existing stuff
that will be located at the start of memory. Using the #build says to not
put anything below the reset location.
jeremiah



Joined: 20 Jul 2010
Posts: 1379

View user's profile Send private message

PostPosted: Thu Mar 27, 2025 1:36 pm     Reply with quote

I've run into situations where it still tries to put code below the reset location. So in the past I've had to add a #org statement as well. Something similar to:

Code:

#build (reset=0x800, interrupt=0x1f00)
#org 0x0000, 0x07FF {}
chrhartz



Joined: 29 Aug 2008
Posts: 11

View user's profile Send private message

PostPosted: Thu Mar 27, 2025 4:05 pm     Reply with quote

Thanks for the reply!

This will not compile, Segment fault:

Code:
#build (reset=0x800, interrupt=0x1f00)

#org 0x800,0x803
void progVector() {goto_address(0x808);}

#org 0x804,0x807
void intVector() {goto_address(0x1f00);}

#org 0x808
void main()


If i try it this way:

Code:
/***********************************************************************/

#build (reset=0x808, interrupt=0x1f00)

#org 0x800,0x803
void progVector() {goto_address(0x808);}

#org 0x804,0x807
void intVector() {goto_address(0x1f00);}

//#org 0x808
void main()


List file output:

Code:
0000:  MOVLW  20
0001:  MOVWF  05
0002:  MOVLW  02
0003:  MOVWF  04
0004:  MOVF   00,W
0005:  BTFSC  03.2
0006:  GOTO   015
0007:  MOVLW  0F
0008:  MOVWF  78
0009:  CLRF   77
000A:  DECFSZ 77,F
000B:  GOTO   00A
000C:  DECFSZ 78,F
000D:  GOTO   009
000E:  MOVLW  8F
000F:  MOVWF  77
0010:  DECFSZ 77,F
0011:  GOTO   010
0012:  NOP
0013:  DECFSZ 00,F
0014:  GOTO   007
0015:  RETURN
.................... 
.................... /***********************************************************************/
.................... // defines
.................... #define void progVector(void)
.................... #define void intVector(void)
.................... 
.................... // Output Pins
.................... #define PWM_LED_PIN      pin_C6      // 0 = LEDs disabled
.................... #define LED_STBY_PIN      pin_C7      // 0 = LED Stby enabled
.................... 
.................... //#build(interrupt=0x1f00)
.................... 
.................... //#org 0x008, 0x7ff {}
.................... 
.................... #build (reset=0x808, interrupt=0x1f00)
.................... 
.................... #org 0x800,0x803
.................... void progVector() {goto_address(0x808);}
*
0800:  MOVLW  08
0801:  MOVWF  0A
0802:  MOVWF  02
0803:  RETURN
.................... 
.................... #org 0x804,0x807
.................... void intVector() {goto_address(0x1f00);}
0804:  MOVLW  1F
0805:  MOVWF  0A
0806:  CLRF   02
0807:  RETURN
.................... 
.................... //#org 0x808
.................... void main()
*
0016:  MOVLW  3C
0017:  MOVLB  01
0018:  MOVWF  19
0019:  CLRF   18
001A:  MOVLB  03
001B:  CLRF   0C
001C:  CLRF   0D
001D:  CLRF   0E
001E:  MOVLB  02
001F:  CLRF   12
0020:  CLRF   11
0021:  CLRF   14
0022:  CLRF   13
.................... {
....................    output_high( PWM_LED_PIN );         // enable LEDs in general
0023:  MOVLB  01
0024:  BCF    0E.6
0025:  MOVLB  02
0026:  BSF    0E.6
....................                   
....................    while(TRUE)
....................    {
....................       output_high( LED_STBY_PIN );   // 
0027:  MOVLB  01
0028:  BCF    0E.7
0029:  MOVLB  02
002A:  BSF    0E.7
....................       delay_ms(1000);
002B:  MOVLW  04
002C:  MOVLB  00
002D:  MOVWF  21
002E:  MOVLW  FA
002F:  MOVWF  22
0030:  CALL   000
0031:  DECFSZ 21,F
0032:  GOTO   02E
....................       output_low(LED_STBY_PIN );      // 
0033:  MOVLB  01
0034:  BCF    0E.7
0035:  MOVLB  02
0036:  BCF    0E.7
....................       delay_ms(1000);
0037:  MOVLW  04
0038:  MOVLB  00
0039:  MOVWF  21
003A:  MOVLW  FA
003B:  MOVWF  22
003C:  CALL   000
003D:  DECFSZ 21,F
003E:  GOTO   03A
003F:  MOVLB  02
0040:  GOTO   027
....................    }
.................... }
.................... 
0041:  SLEEP


The output is completely weird. And there is code below 0x800. There should be absolutely nothing, this is reserved for the bootloader.

The Addresses 0x800 (program entry) and 0x804 (interrupt entry) are given by the bootloader.

So these are the first two commands of the user program. Everything else can be anywhere. Smile

I agree to jeremiah, i have tried a lot of things the last days and the compiler always puts code below 0x800.
dyeatman



Joined: 06 Sep 2003
Posts: 1950
Location: Norman, OK

View user's profile Send private message

PostPosted: Thu Mar 27, 2025 5:03 pm     Reply with quote

You are using what many in the CCS community consider a very old "early"
version compiler which may play into this. Have you tried a later version to
sere if it helps?
_________________
Google and Forum Search are some of your best tools!!!!
jeremiah



Joined: 20 Jul 2010
Posts: 1379

View user's profile Send private message

PostPosted: Thu Mar 27, 2025 5:41 pm     Reply with quote

chrhartz wrote:
Thanks for the reply!

This will not compile, Segment fault:

Code:
#build (reset=0x800, interrupt=0x1f00)

#org 0x800,0x803
void progVector() {goto_address(0x808);}

#org 0x804,0x807
void intVector() {goto_address(0x1f00);}

#org 0x808
void main()


<snipped>

The output is completely weird. And there is code below 0x800. There should be absolutely nothing, this is reserved for the bootloader.

The Addresses 0x800 (program entry) and 0x804 (interrupt entry) are given by the bootloader.

So these are the first two commands of the user program. Everything else can be anywhere. Smile

I agree to jeremiah, i have tried a lot of things the last days and the compiler always puts code below 0x800.


A segmentation fault means the compiler crashed. Try this instead:
Code:

#fuses NONE
#build (reset=0x800, interrupt=0x0804)
#org 0x0000, 0x07FF {}

void main(){
   // your code here
}

leave out the progVector and intVector stuff and just use those. The #build() directive is generating those for you, so trying to generate them manually after might be causing conflicts. Notice the changes in address I made in the #build.

you shouldn't need to do the extra jump from 0x804 to 0x1F00. Let the compiler put the interrupts at 0x804

EDIT: Full example below using compiler version 5.105:
main.c:
Code:

#include <16F1459.h>

#fuses NONE
#build (reset=0x800, interrupt=0x0804)
#org 0x0000, 0x07FF{}

static volatile unsigned int g_count = 0;

#int_ra
void ra_isr(){
   g_count++;
}

void main(){
   unsigned int count;
   while(TRUE){
      count = g_count;
   }
}



generated HEX:
Code:

File Summary:
   Filename:       main.hex
   File Status:    Good
   Target Chip:    PIC16F1459
   File Type:      INHX8 (Intel Hex)
   Program Size:   53 Instructions (1%)
   Program Range:  0800-0835
   Checksum:       C3D3
   Config Size:    0 bytes
   Created:        27-Mar-25 19:47
   Addresses are:  Word addresses

Program Memory
   000800: 3188 2827 0000
   000804: 0183 3188 0020 0877
   000808: 00A0 0878 00A1 0879 00A2 087A 00A3 1D8B
   000810: 2813 180B 281C 0820 00F7 0821 00F8 0822
   000818: 00F9 0823 00FA 0009 3188 281E 0AA4 30FF
   000820: 0027 0613 0593 100B 3188 0020 2813 0023
   000828: 018C 018D 018E 0022 0192 0191 0194 0193
   000830: 0020 01A4 0824 00A5 2832 0063

;PIC16F1459
;CRC=1472  CREATED="27-Mar-25 19:47"


LST:
Code:

               ROM used:   53 words (1%)
                           Largest free fragment is 2048
               RAM used:   11 (1%) at main() level
                           22 (2%) worst case
               Stack used: 1 locations (0 in main + 1 for interrupts)
               Stack size: 16

*
0800:  MOVLP  08
0801:  GOTO   027
0802:  NOP
*
0804:  CLRF   03
0805:  MOVLP  08
0806:  MOVLB  00
0807:  MOVF   77,W
0808:  MOVWF  20
0809:  MOVF   78,W
080A:  MOVWF  21
080B:  MOVF   79,W
080C:  MOVWF  22
080D:  MOVF   7A,W
080E:  MOVWF  23
080F:  BTFSS  0B.3
0810:  GOTO   013
0811:  BTFSC  0B.0
0812:  GOTO   01C
0813:  MOVF   20,W
0814:  MOVWF  77
0815:  MOVF   21,W
0816:  MOVWF  78
0817:  MOVF   22,W
0818:  MOVWF  79
0819:  MOVF   23,W
081A:  MOVWF  7A
081B:  RETFIE
081C:  MOVLP  08
081D:  GOTO   01E
.................... #include <16F1459.h>
.................... //////////// Standard Header file for the PIC16F1459 device ////////////////
.................... ///////////////////////////////////////////////////////////////////////////
.................... ////        (C) Copyright 1996, 2020 Custom Computer Services          ////
.................... //// This source code may only be used by licensed users of the CCS C  ////
.................... //// compiler.  This source code may only be distributed to other      ////
.................... //// licensed users of the CCS C compiler.  No other use, reproduction ////
.................... //// or distribution is permitted without written permission.          ////
.................... //// Derivative programs created using this software in object code    ////
.................... //// form are not restricted in any way.                               ////
.................... ///////////////////////////////////////////////////////////////////////////
.................... #device PIC16F1459
....................
.................... #list
....................
....................
.................... #fuses NONE
.................... #build (reset=0x800, interrupt=0x0804)
.................... #org 0x0000, 0x07FF{}
....................
.................... static volatile unsigned int g_count = 0;
....................
.................... #int_ra
.................... void ra_isr(){
....................    g_count++;
081E:  INCF   24,F
081F:  MOVLW  FF
0820:  MOVLB  07
0821:  XORWF  13,W
0822:  ANDWF  13,F
0823:  BCF    0B.0
0824:  MOVLP  08
0825:  MOVLB  00
0826:  GOTO   013
.................... }
....................
.................... void main(){
0827:  MOVLB  03
0828:  CLRF   0C
0829:  CLRF   0D
082A:  CLRF   0E
082B:  MOVLB  02
082C:  CLRF   12
082D:  CLRF   11
082E:  CLRF   14
082F:  CLRF   13
0830:  MOVLB  00
0831:  CLRF   24
....................    unsigned int count;
....................    while(TRUE){
....................       count = g_count;
0832:  MOVF   24,W
0833:  MOVWF  25
0834:  GOTO   032
....................    }
.................... }
....................
0835:  SLEEP
chrhartz



Joined: 29 Aug 2008
Posts: 11

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 4:32 am     Reply with quote

Thank you, no compile errors!

List output is a bit different but it looks good so far:

Code:
CCS PCM C Compiler, Version 5.015, 5967               28-Mrz-25 11:22

               Filename:   E:\Data\Work\mcm-solutions\10-Inch Plotter v4\Firmware Test\Test.lst

               ROM used:   48 words (1%)
                           Largest free fragment is 2048
               RAM used:   11 (1%) at main() level
                           22 (2%) worst case
               Stack used: 1 locations (0 in main + 1 for interrupts)
               Stack size: 16

*
0800:  MOVLP  08
0801:  GOTO   022
0802:  NOP
*
0804:  CLRF   03
0805:  MOVLP  08
0806:  MOVLB  00
0807:  MOVF   77,W
0808:  MOVWF  20
0809:  MOVF   78,W
080A:  MOVWF  21
080B:  MOVF   79,W
080C:  MOVWF  22
080D:  MOVF   7A,W
080E:  MOVWF  23
080F:  BTFSS  0B.3
0810:  GOTO   013
0811:  BTFSC  0B.0
0812:  GOTO   01C
0813:  MOVF   20,W
0814:  MOVWF  77
0815:  MOVF   21,W
0816:  MOVWF  78
0817:  MOVF   22,W
0818:  MOVWF  79
0819:  MOVF   23,W
081A:  MOVWF  7A
081B:  RETFIE
081C:  MOVLP  08
081D:  GOTO   01E
.................... #include <16F1459.h>
.................... //////////// Standard Header file for the PIC16F1459 device ////////////////
.................... ///////////////////////////////////////////////////////////////////////////
.................... ////        (C) Copyright 1996, 2013 Custom Computer Services          ////
.................... //// This source code may only be used by licensed users of the CCS C  ////
.................... //// compiler.  This source code may only be distributed to other      ////
.................... //// licensed users of the CCS C compiler.  No other use, reproduction ////
.................... //// or distribution is permitted without written permission.          ////
.................... //// Derivative programs created using this software in object code    ////
.................... //// form are not restricted in any way.                               ////
.................... ///////////////////////////////////////////////////////////////////////////
.................... #device PIC16F1459
.................... 
.................... #list
.................... 
.................... 
.................... #fuses NONE
.................... #build (reset=0x800, interrupt=0x0804)
.................... #org 0x0000, 0x07FF{}
.................... 
.................... static volatile unsigned int g_count = 0;
.................... 
.................... #int_ra
.................... void ra_isr(){
....................    g_count++;
081E:  INCF   24,F
081F:  BCF    0B.0
0820:  MOVLP  08
0821:  GOTO   013
.................... }
.................... 
.................... void main(){
0822:  CLRF   24
0823:  MOVLB  03
0824:  CLRF   0C
0825:  CLRF   0D
0826:  CLRF   0E
0827:  MOVLB  02
0828:  CLRF   12
0829:  CLRF   11
082A:  CLRF   14
082B:  CLRF   13
....................    unsigned int count;
....................    while(TRUE){
....................       count = g_count;
082C:  MOVLB  00
082D:  MOVF   24,W
082E:  MOVWF  25
082F:  GOTO   02D
....................    }
.................... }
0830:  SLEEP


I will try this out with my real application! Smile

Thanks,
Chris
jeremiah



Joined: 20 Jul 2010
Posts: 1379

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 6:34 am     Reply with quote

No problem. Just make sure to enable interrupts if you end up actually using any, my example omitted that and some other basic things as I was more focused on getting the code into the correct locations rather than having runtime correct code.

Also keep in mind that version 5.015 was a bit buggy, so you may have to work around some of that.
Ttelmah



Joined: 11 Mar 2010
Posts: 19761

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 8:01 am     Reply with quote

One 'caveat'.
He needs to put the program interrupt handler, where his bootloader wants
these to be. Check where the bootloader wants these. 0x804 is more normal
and will run better, but it is critical that it matches what the bootloader
is setup to use.
jeremiah



Joined: 20 Jul 2010
Posts: 1379

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 10:17 am     Reply with quote

Based on the code provided by the OP, the bootloader expects 0x0804. That's where the user's jump vector is "org"ed
Ttelmah



Joined: 11 Mar 2010
Posts: 19761

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 10:35 am     Reply with quote

That's good, but he was locating the interrupt handler at 1F00. No sign of
804 anywhere?.
chrhartz



Joined: 29 Aug 2008
Posts: 11

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 11:49 am     Reply with quote

I have taken the example from jeremiah and it worked with my simple led blink program.
Tried then the way more complex program that does usb hid, cdc, ir-remote control decoding, some i2c sensor stuff. It worked perfectly! Very Happy

The PIC is the sidekick of a RPi CM5 for a marine navigation display. It controls the power supply, display driver, backlight, sensor buttons and ir-remote.
All button or ir-commands are sent as keyboard codes to the Pi. I am not using any GPIOs so the whole thing is completely independent of the OS.
The RPi is running Android AOSP and it is really nice that the user now can change the PICs software at any time without any risk and without additional software or pc.

Thank you all!
Chris
jeremiah



Joined: 20 Jul 2010
Posts: 1379

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 4:23 pm     Reply with quote

Ttelmah wrote:
That's good, but he was locating the interrupt handler at 1F00. No sign of
804 anywhere?.


Take a look at the 2nd #org:
Code:

#org 0x800,0x803                           // jump vector for bootloader
void progVector() {goto_address(0x808);}

#org 0x804,0x807                           // jump vector for bootloader
void intVector() {goto_address(0x1f00);}


The OP was trying to make their own jump vectors located at 0x800 and 0x804, hence my suggestion above (since #build does that for ya). The 0x1F00 was just a number of happenstance relative to the problem.
jeremiah



Joined: 20 Jul 2010
Posts: 1379

View user's profile Send private message

PostPosted: Fri Mar 28, 2025 4:24 pm     Reply with quote

chrhartz wrote:
I have taken the example from jeremiah and it worked with my simple led blink program.
Tried then the way more complex program that does usb hid, cdc, ir-remote control decoding, some i2c sensor stuff. It worked perfectly! Very Happy
Chris


Awesome, I'm glad it worked for ya!!
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