 |
 |
View previous topic :: View next topic |
Author |
Message |
chrhartz
Joined: 29 Aug 2008 Posts: 11
|
solved: Bootloader - remove or relocate startup code |
Posted: Thu Mar 27, 2025 4:28 am |
|
|
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: 19762
|
|
Posted: Thu Mar 27, 2025 11:27 am |
|
|
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
|
|
Posted: Thu Mar 27, 2025 1:36 pm |
|
|
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
|
|
Posted: Thu Mar 27, 2025 4:05 pm |
|
|
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.
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
|
|
Posted: Thu Mar 27, 2025 5:03 pm |
|
|
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
|
|
Posted: Thu Mar 27, 2025 5:41 pm |
|
|
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.
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
|
|
Posted: Fri Mar 28, 2025 4:32 am |
|
|
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!
Thanks,
Chris |
|
 |
jeremiah
Joined: 20 Jul 2010 Posts: 1379
|
|
Posted: Fri Mar 28, 2025 6:34 am |
|
|
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: 19762
|
|
Posted: Fri Mar 28, 2025 8:01 am |
|
|
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
|
|
Posted: Fri Mar 28, 2025 10:17 am |
|
|
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: 19762
|
|
Posted: Fri Mar 28, 2025 10:35 am |
|
|
That's good, but he was locating the interrupt handler at 1F00. No sign of
804 anywhere?. |
|
 |
chrhartz
Joined: 29 Aug 2008 Posts: 11
|
|
Posted: Fri Mar 28, 2025 11:49 am |
|
|
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!
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
|
|
Posted: Fri Mar 28, 2025 4:23 pm |
|
|
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
|
|
Posted: Fri Mar 28, 2025 4:24 pm |
|
|
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!
Chris |
Awesome, I'm glad it worked for ya!! |
|
 |
|
|
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
|