View previous topic :: View next topic |
Author |
Message |
lt2021_genie
Joined: 03 Jun 2021 Posts: 6
|
Bootloader works, but want modifications that break it |
Posted: Thu Jun 03, 2021 9:20 am |
|
|
I've implemented the bootloader successfully with compiler version 5.094. It loads a new application with no issue.
The problem is I'm trying to make some changes to the original code. I want to add to the application() function has some initialization code relating to leds just before the infinite loop to indicate to the user that no user application code has been loaded.
So I want to change this:
Code: |
#org LOADER_END+1,LOADER_END+3
void application(void) {
while(TRUE);
}
|
To this:
Code: |
#org LOADER_END+1,LOADER_END+3
void application(void) {
// set up led i/o - RA2/RA3
set_tris_a (0xc);
output_high (PIN_A2);
output_high (PIN_A3);
while(TRUE);
}
|
I have an error message relating to the isr() indicating "Out of ROM, A segment or the program is too large application". I tried increasing the #org end address, but it fails in the same way.
Any advice on how to correct this? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Thu Jun 03, 2021 12:12 pm |
|
|
Think about it.
The standard application is just a single entry. Hence fits in three
instructions. You now have perhaps 20 physical instructions. The space
allocated needs to go up to allow for this. Instead of +3, something
like +30. |
|
|
lt2021_genie
Joined: 03 Jun 2021 Posts: 6
|
|
Posted: Thu Jun 03, 2021 12:54 pm |
|
|
I did do that. All of the errors come back as:
Code: |
Compiling D:\project\TEST\system\css_sbl\css_serial_bootloader on 03-Jun-21 at 13:52
--- Info 300 "D:\project\TEST\system\css_sbl\css_serial_bootloader.c" Line 51(30,32): More info: Segment at 00000-00502 (0000 used)
--- Info 300 "D:\project\TEST\system\css_sbl\css_serial_bootloader.c" Line 51(30,32): More info: Segment at 00504-0FFFE (0000 used) Priv
--- Info 300 "D:\project\TEST\system\css_sbl\css_serial_bootloader.c" Line 51(30,32): More info: Attempted to create: 00500-0053E for #org
*** Error 126 "D:\project\TEST\system\css_sbl\css_serial_bootloader.c" Line 51(30,32): Invalid ORG range
1 Errors, 0 Warnings.
Build Failed.
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jun 04, 2021 1:20 am |
|
|
Really the bootloader is not designed to do this. The 'application' declaration
is meant to be a 'stub', telling the bootloader where the future function actually
'is', but containing nothing. It is possible to add a function here, but you have
to tweak all the memory declarations to do this.
Easier possibly to compile the application as a bootloadable problem, and
then import this at the end of the bootloader. This ought to work.
Trying to do it the way you are has huge problems. The 'main;' that is
loaded by a bootloader at the application location, won't physically be at that
location. Instead it'll have a single jump at this point to the code that will
sit higher in memory. This is done to leave the space for the interrupt
handlers. Now trying to load a whole 'program' here, if it is more than about
a couple of bytes, results in the locations reserved for the interrupt handlers
being overwritten. Result, won't work.
This is why the code that is added here has to be a correctly written complete
program with the jumps and spaces included.
The normal way to combine the bootloader and a program is to compile
both separately, and to #import the bootloader, into the main program.
This is the only 'tested' way that works that I know of. |
|
|
lt2021_genie
Joined: 03 Jun 2021 Posts: 6
|
|
Posted: Fri Jun 04, 2021 7:44 am |
|
|
I had a feeling this was the case, so I tried something else shown below just for reference for anyone else who may want to do the same thing. Thanks for the help.
Code: |
#include <18F26Q10.h>
#use delay( internal=32MHz )
#use rs232(baud=115200, xmit=PIN_C7, rcv=PIN_C6) //Text through the UART
#define PUSH_BUTTON PIN_B4
#define _BOOTLOADER
//#define BOOTLOADER_MODE2X
#include <bootloader.h>
#include <loader.c>
void app (void);
#org LOADER_END+1,LOADER_END+3
void app_init(void) {
app();
}
//-------------------------------------------------------------------------
void main (void) {
//-------------------------------------------------------------------------
// setup pull ups on B3/B4
port_b_pullups (0x18);
// setup i/o clear led
set_tris_a (~0x0c);
output_high (PIN_A2);
output_high (PIN_A3);
//delay_ms (100);
if(!input(PUSH_BUTTON))
{
output_low (PIN_A2);
printf("\r\nBootloader Version 1.0\r\n");
// Let the user know it is ready to accept a download
printf("\r\nWaiting for download...");
load_program();
}
printf("\r\nRunning loaded app...");
app_init();
}
//-------------------------------------------------------------------------
void app (void) {
//-------------------------------------------------------------------------
output_low (PIN_A2);
output_low (PIN_A3);
while(TRUE);
}
#int_global
//-------------------------------------------------------------------------
void isr (void) {
//-------------------------------------------------------------------------
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jun 04, 2021 8:20 am |
|
|
OK.
The problem with this is the 'app' here is actually inside the bootloader
memory space. So anything much larger will result in this running out of
space.
So long as it is kept really small this should work. |
|
|
lt2021_genie
Joined: 03 Jun 2021 Posts: 6
|
|
Posted: Thu Jul 01, 2021 11:59 am |
|
|
I have a follow-up question.
Using the #import method, what type of file would I be importing? The object file? A hex file? What compile settings would I use to create this file for the bootloader and the application?
From your post, I have to do the following.
1. Compile bootloader.c with following options:
Code: | "CCSC.exe" +FH +EXPORT bootloader.c |
2. Add to top of application.c source:
Code: | #import "bootloader.o" |
3. Compile application.c
This should then create a application.hex file that I can load?
Am i missing anything? I thought the +EXPORT produced relocatable code. Wouldn't that defeat the purpose of what we're doing? Or do I not use the export feature. When I do that I can only produce the final hex output and not the object file. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jul 02, 2021 12:28 am |
|
|
No, you #import the hex file.
Also ideally, modify the application getting rid of all the #fuses, and instead
having #fuses NONE.
If you don't do this you will get a complaint when the new hex file includes
the bootloader fuses (even though these will be (must be...)) the same as
the ones in the application.
So you add to the application (which you are compiling to use the
bootloader), so with :
#include <bootloader.h>
You then add:
#IMPORT (FILE=bootloader.hex,HEX,RANGE=0:LOADER_SIZE)
With obviously the file name of your bootloader.
This way it loads a normal .hex file. |
|
|
lt2021_genie
Joined: 03 Jun 2021 Posts: 6
|
|
Posted: Fri Jul 02, 2021 7:57 am |
|
|
Following your instructions, I successfully generated an application.hex file with the imported bootloader.hex. There's a warning from application.c compile. Should I be concerned? I've included the source for both below.
"Line 6(0,1): Memory not available at requested location"
bootloader.c
Code: |
#include <18F26Q10.h>
#use delay( internal=32MHz )
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7) //Text through the UART
#define _BOOTLOADER
//#define BOOTLOADER_MODE2X
#define PUSH_BUTTON PIN_B4
#include <bootloader.h>
#include <loader.c>
void app (void);
#org LOADER_END+1,LOADER_END+3
void application(void) {
while (TRUE);
}
//-------------------------------------------------------------------------
void main (void) {
//-------------------------------------------------------------------------
if(!input(PUSH_BUTTON))
{
output_low (PIN_A2);
printf("\r\nBootloader Version 1.0\r\n");
// Let the user know it is ready to accept a download
printf("\r\nWaiting for download...");
load_program();
}
printf("\r\nRunning loaded app...");
application();
}
#int_global
//-------------------------------------------------------------------------
void isr (void) {
//-------------------------------------------------------------------------
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
|
application.c
Code: |
#include <18F26Q10.h>
#include <bootloader.h>
#FUSES NONE
#IMPORT (FILE=bootloader.hex,HEX,RANGE=0:LOADER_SIZE)
#use delay(internal=32MHz)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7)
//-------------------------------------------------------------------------
void main (void) {
//-------------------------------------------------------------------------
int8 i = 0;
delay_ms(100);
printf("\r\nApplication Version 1.1\r\n");
// setup pull ups on B3/B4
port_b_pullups (0x18);
// setup i/o clear led
set_tris_a (~0x0c);
output_high (PIN_A2);
output_high (PIN_A3);
while(TRUE) {
// print incrementing count
printf("\n\r%3u ",++i);
// toggle green led
output_toggle (PIN_A3);
// wait 500ms
delay_ms(500);
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sun Jul 04, 2021 2:14 am |
|
|
That is perfectly OK.
All that is happening, is the main program is built to start after the
loader, and you are then 'importing' something that resides below it's
permitted memory range, so it warns you that this might be a problem.
If you load the resulting hex file, you will see that it is all correctly there
and where it should be.
The only problem you may get is with the fuses.
Problem is that the 'application' when you build it does not specify any
fuses. However the bootloader when loaded is told not to include the
fuses.
The behaviour of this depends on compiler version. Most seem to load
the fuses 'anyway', however some of the recent ones do not. So get
rid of #fuses NONE, which will ensure the fuses are set. You will still get
the same error, but it ensures that there are fuses included in the result. |
|
|
|