|
|
View previous topic :: View next topic |
Author |
Message |
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
CCS bootloader at the _TOP_ of the memory |
Posted: Tue Jan 23, 2007 8:42 am |
|
|
Hi,
I've been implementing the CCS bootloader without succes so far. I've implemented the CCs bootloader that is at the beginning of the memory, but I'm experiencing problems with my main program and just can't find what's the problem there. Almost read every bootloader topic overhere! You can read that here:
http://www.ccsinfo.com/forum/viewtopic.php?t=29503
Now I want to put the bootloader on top of the memory. I'm using a PICLF877A with pcwh v3.226. This is my BOOTLOADER_HIGH code:
Code: | #include <16F877A.h>
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#include "bootloader_high.h"
#org LOADER_ADDR, LOADER_END default
#use delay (clock = 4000000)
#use rs232 (baud = 9600, parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#include "my_loader.c"
void main (void);
void application (void);
void main (void)
{
long timeout = 0;
int8 i, triggers_found = 0;
delay_us (50); // Transmit Buffer clearen
putc ('L');
for ( i = 2; i > 0 ; i-- )
{
while ( !kbhit() && (++timeout < 0xFFFF) ) // 0xFFFF i.s.o. 50000 saves 5 bytes
delay_us (100);
if ( kbhit() )
{
if ( getc() == 170 )
triggers_found++;
else
break; // invalid char received, stop waiting.
}
else
break;
}
if ( triggers_found == 2 )
real_load_program ();
application ();
}//main
#org 0x0200,0x0300
void application(void) // Dummy functie, eigenlijk staat hier de échte main
{
while (TRUE);
} |
bootloader_high.h
Code: | #define LOADER_END getenv("PROGRAM_MEMORY")-1
#define LOADER_SIZE 0x1BF // 0x17F
#define LOADER_ADDR LOADER_END-LOADER_SIZE |
Code: | 0000: MOVLW 18
0001: MOVWF 0A
0002: GOTO 7A1
0003: NOP |
These are the 4 first instructions. What do they do? There is nothing on adress 7A1; still the bootloader starts off. Where does the bootloader begin?
Last edited by Christophe on Wed Jan 24, 2007 4:32 am; edited 3 times in total |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 24, 2007 2:01 am |
|
|
anybody?
I want to create this:
However the beginning of 'goto start' where is that? Normally that is adress 0000h ? |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 24, 2007 3:30 am |
|
|
This is what the #build instruction does.
It defines where the compiler wil put it's 'start' jump. Similarly, the 'interrupt' entry, defines where the interrupt code jump will be placed.
Just build your main code, with something like:
#build (reset=0x40, interrupt=0x44)
Then your bootloder can just jump to 0x40, to goto the 'main' code.
Unless your bootloader is itself using interrupts, why not consider allowing enough space before the 'main', for the 'main' interrupt handler to be put in the normal location?. You can then just use something like:
#build (reset=0x200)
Which will leave the space for the standard interrupt handler. The bootloader will just need to have it's 'main' org'ed up to the high location in memory (the standard compile will then automatically place the required jump to this), and jump back to the 'reset' location when required.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 24, 2007 3:48 am |
|
|
in my main:
Code: |
#include <C:\Documents and Settings\christophe.seyen\My Documents\Hardware\PIC\BOOTLOADER_HIGH\Bootloader_high.h>
#org LOADER_ADDR, LOADER_END {}
#build (reset=0x200) |
this gives:
Code: | 0200: MOVLW 10
0201: MOVWF 0A
0202: GOTO 1ED
0203: NOP |
However my main is at 11ED. What is going wrong here?
Quote: | .................... //*********************************** Main ***********************************//
.................... void MAIN ()
.................... {
*
11ED: CLRF 04 |
The program should run normally, doesn't it?
edit: What does this do? When is this executed?
Code: |
// somewhere above
UserBootVectorAddr=label_address(UserBootVector);
UserBootVector:
#asm
MOVLW 0x00
MOVWF 0x0A
GOTO 0x00
NOP
NOP
#endasm
} |
(infos: http://www.sparkfun.com/tutorial/Bloader/bloader-5-vectors.htm ) |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 24, 2007 5:46 am |
|
|
The code at 0x200, _is_ a jump to 11ED. This is just how the processor works. The 'jump' instruction, can only contain 11 bits of the target address. Your 'target', needs 13bits. What is done, is that an offset (the '10), is pre-stored into another register, which gets added to the upper bits of the target address, when the next 'jump' occurs.
The compiler sticks the physical 'main' higher up in memory, since it'll always put things like the timer code, RS232 code, etc, in front of it.
The user boot vector jump, is a similar thing, loading the extra bytes.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 24, 2007 6:22 am |
|
|
Some questions on my program.
1. How can I make sure that when download mode is not activated, the _downloaded_ program starts off? Why does the bootloader program starts off at first?
2. Does loader.c can be used on high memory bootloaders?
Can you help me understand what this code does. I see this statement a lot in upper memory bootloaders.
Code: | unsigned int16 UserBootVectorAddr; // holds the address of our new boot vector
if (input(RUN_BUTTON) ) { // download mode activated
UserBootVectorAddr=label_address(UserBootVector);
// download code
UserBootVector:
#asm
MOVLW 0x00
MOVWF 0x0A
GOTO 0x00
NOP
NOP
#endasm
}// main |
This is the full listing: It is the gogo bootloader I want to understand. I want to use the CCS loader.c to write my own high memory bootloader. The gogo bootloader does not work with hyperterminal. loader.c does.
Code: | /////////////////////////////////////////////////////////////////////////////
//
// =================================================
//
// This code is released under the GPL license. Read the attached license
// for full information but here's the basic points:
// - Use it freely
// - Let others use your new/modified code freely too
// - So, please release the source
//
// =================================================
//
// PIC Boot Loader for the 16F877A MCU
// V. 1.0 Nov 22, 2006
// By Arnan (Roger) Sipitakiat
// http://www.gogoboard.org
//
// This code is designed for the GoGo board
// but it should work with any 877A PIC device.
//
// The loader will start when pin B7 is set high during
// power-up.
//
// The loader occupies memory addresses between 0x1e50-0x1fff (0.4k)
// User code must not use this memory segment.
// in CCS, you can use the following command to reserve the memory space
// #ORG 0x1e50, 0x1fff {}
//
// Note that the configuration bits can't be changed. Whatever is used
// here is what the user's program is stuck with.
//
/////////////////////////////////////////////////////////////////////////////
#include <16F877A>
#device ADC=10 *=16
#case
#fuses HS,NOWDT,NOPROTECT, BROWNOUT, NOLVP, PUT
#use DELAY(clock=4000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)
// define possible reply bytes
#define READY_FOR_NEXT 0x11
#define FINISH_FLAG 0x55
#define BOOTLOADER_OVERWRITE 0x80
#define LOADER_BEGIN 0x1E40
#define LOADER_END 0x1FFF
#define SerBufferSize 45 // serial input buffer size
#define RUN_BUTTON PIN_B7
#define RUN_LED PIN_B6
#define USER_LED PIN_D0
// #org tells the compiler where to put the procedures in memory
#ORG LOADER_BEGIN, LOADER_END auto=0 default
// a slim version of atoi().
// converts ascii text to integer
// i.e. '1' = 1, 'A' = 10
unsigned int a2i(unsigned char asciiByte) {
if (asciiByte >= 'A' && asciiByte <F> just skip.
}
// else if data overlaps the bootloader code -> halt
else if ((writeAddr >= LOADER_BEGIN) && (writeAddr <LOADER_END> data is in program area
else {
for (i=0; i<recLen ;i++) {
// (*) Modifing the Boot Vector
// The first four commands in memory are called the boot
// vector. It resets the board and points to the address of
// the main function.
// Each HEX file has their own version of these commands. But
// since we always want the boot loader to run before the
// user code, we must not overwrite the loader's boot vertor.
// Instead, we move the user's boot vector to another location
// within the boot loader's program area
// (see label "UserBootVector" below).
// This 'if' command detects user's boot vector and redirects it
// The boot vector is at address 0x0000 - 0x0003
if ((writeAddr < 0x004) && (i<4) )
write_program_eeprom(UserBootVectorAddr + i, Buffer[i]);
else
write_program_eeprom(writeAddr + i, Buffer[i]);
}
}
// Tells the PC to send the next line
putc(READY_FOR_NEXT);
}
}
// Tells the PC that we are finished
putc(FINISH_FLAG);
for (j=0;j<255;j++) {
for (i=0;i<255;i++) {}; // this loop gives the chip time to finish
// sending the serial byte before resetting it self.
// I did not use delay_ms() because I have had
// some strange problems with it.
}
}
// This is a reboot command written in Assembly.
// these four commands will be overwritten with the boot vector we obtain
// from the HEX file.
// See (*) above for more info.
UserBootVector:
#asm
MOVLW 0x00
MOVWF 0x0A
GOTO 0x00
NOP
NOP
#endasm
}
#ORG default |
|
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 24, 2007 8:50 am |
|
|
I'm able to download the code and the code starts off. However when I reset, the bootloader restarts. How can I enter my program again after a reset? |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 24, 2007 9:25 am |
|
|
Aargh....
The _bootloader_, _must_ always load. This is how it works...
You need to write _it_ to test for some factor at boot (an external pin, or a character on the serial etc.), and then if this is not in the state to trigger 'bootloading', jump to the main code. This is what pin B5, does on the CCS example.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 24, 2007 9:39 am |
|
|
After 2 weeks of studying bootloaders, I allready knew that.. Probably my question was posed not clear.
I managed to get the bootloader to work... Tks 4 all the support.
The trick was understanding this line:
Code: | UserBootVectorAddr=label_address(UserBootVector); |
it gets the adress where a piece of code resides.
That piece of code is resetting the PIC.
When downloading a program, the RESET VECTOR of the hex file is overwritten on those locations. So that means that instead of that code overthere being executed, the _to be downloaded_ program's resetvector is executed and jumps to its main! |
|
|
|
|
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
|