|
|
View previous topic :: View next topic |
Author |
Message |
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
Bootloader and PCW compiler: memory mapping |
Posted: Wed Jan 03, 2007 4:04 am |
|
|
Hi,
I'm trying to implement a bootloader.
I'm using the PCW compiler for the PIC16LF877A
What applies to this processor? PCM, PCH or none?
Code: | #if defined(__PCM__) // PIC16 compiler
#define LOADER_END 0x1FF // 511
#define LOADER_SIZE 0x1BF // 447
#elif defined(__PCH__)
#define LOADER_END 0x4FF
#define LOADER_SIZE 0x3FF
#endif |
tks
Last edited by Christophe on Mon Jan 08, 2007 2:50 am; edited 2 times in total |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 03, 2007 4:25 am |
|
|
PCM.
There are three 'core' compilers. PCB (12 chips), PCM (16 chips), and PCH (18 chips). The 'PCW' bit, is the windows IDE that goes on 'top' of the compiler.'PCW', is basically PCB, plus PCM, plus the windows
There is a 'slight' complexity, in that there are a few '12' chips, which require the PCM compiler, and the '14' chips which also use this compiler.
IDE. 'PCWH', is PCB, PCM, PCH, plus the IDE. Because you are selecting a '16' chip, the PCM compiler will be being used.
the code is written like this, so it'll work with any of the compilers, automatically scwitcing defintions, if you change processors.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Wed Jan 03, 2007 6:22 am |
|
|
Tks for your input. I'm trying to understand the CCS example. Can you guys help me?
bootloader.h:
Code: | //#if defined(__PCM__) // PIC16 compiler
#define LOADER_END 0x1FF // 511
#define LOADER_SIZE 0x1BF // 447
//#elif defined(__PCH__)
// #define LOADER_END 0x4FF
// #define LOADER_SIZE 0x3FF
//#endif
#ifndef _bootloader // Als bootloader ergens gedefinieerd is
// reset en interrupt vectoren verplaatsen, anders worden ze overschreven
//#if defined(__PCM__)
#build(reset=LOADER_END+1, interrupt=LOADER_END+5)
//#elif defined(__PCH__)
// #build(reset=LOADER_END+2, interrupt=LOADER_END+8)
//#endif
#org 0, LOADER_END {} // tussen geheugen 0 en LOADER_END => vrij anders wordt de bootloader overschreven
#endif |
bootloader.c :
Code: | #include <16F877A.h>
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#define BUZZ PIN_C3
#define RESET_IN PIN_E2
#define _bootloader
#include <bootloader.h>
#include <loader.c>
//#if defined(__PCM__) // PCM : 14 bit compiler
#org LOADER_END+1,LOADER_END+10 // Die functie start op loader_end + 1 tot loader_end + 10
//#elif defined(__PCH__) // PCH : PIC18 compiler
// #org LOADER_END+2,LOADER_END+20 // Die functie start op loader_end + 2 tot loader_end + 20
//#endif
void application(void) {
while(TRUE);
}
//#if defined(__PCH__) // Als PIC18 comiler
//#org 0x40,0x7F
//#else // 14 bit compiler
//#org 0x20,0x3F // De main staat tussen adres 0x20 en 0x3F
//#endif
void main(void) {
if(!input(PIN_B5))
{
load_program();
}
application();
}
/*
void main ()
{
int8 i;
delay_ms (1000);
while (kbhit()) // Zolang kbhit () FALSE is, lees een karakter van de seri�le poort
{ // kbhit () = TRUE : character has been received and is waiting in the hardware buffer for getc() to read
getc();
}
//for ( i = 0 ; i < 3 ; i++ ) // Loop until 3 X 170 is received
// {
do
{
} while (getc() != 170);
// }
// putc ('K'); // Let the user know it is ready to accept a download
// Load the program
load_program();
application();
}
*/
#ORG default // Vanaf
//#if defined(__PCM__)
#int_global
void isr(void) {
#asm
goto LOADER_END+5
#endasm
}
//#elif defined(__PCH__)
// #int_global
// void isr(void) {
// #asm
// goto LOADER_END+7
// nop
// nop
// nop
// nop
// nop
// nop
// goto LOADER_END+0x17
// #endasm
// }
//#endif |
1. If pin B0 is low, this program will write a new program to the flash. However, in this program, if pin B0 is high, function application () is called. Function application is between LOADER_END + 1 and LOADER_END + 10. And function application () actually does nothing!
How can I change this that the real program is started? Isn't the real program located between adress LOADER_END( + 5) and 1FFFh ?
2. The triggerpoint is B0 low. I want to change the triggerpoint to: RECEIVE 2 times 170dec in 5 seconds. How can I change that? What is extra needed for this?
3. What does the #int_global do?
4. The SIOW program sends the hex file. Is it hard to write your own PC tool that does that? What's the algorythm? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jan 03, 2007 9:02 am |
|
|
Quote: | How can I change this that the real program is started? Isn't the real program located between adress LOADER_END( + 5) and 1FFFh ? | The code as it is is correct, you don't have to change it. The real application starts at LOADER_END+1, and at LOADER_END+5 is your interrupt handler as defined in Code: | #build(reset=LOADER_END+1, interrupt=LOADER_END+5) |
The application you see here is a dummy, it is there for two reasons:
1) To make the compiler happy. There should always be a main() or the compiler will refuse to compile the bootloader code.
2) The bootloader will be the first program to be flashed into a new chip. Yes, this application code is at the same memory location where your real application is going to be loaded, but who cares overwriting a dummy application. You could modify this dummy application to flash a LED or something so you can check the bootloader was programmed correctly.
Quote: | 2. The triggerpoint is B0 low. I want to change the triggerpoint to: RECEIVE 2 times 170dec in 5 seconds. How can I change that? What is extra needed for this? | Have a look at the chapter 'How do I get getc() to timeout after a specified time? ' in the PICC manual. A small modification to that example should do the trick.
Quote: | 3. What does the #int_global do? | When an interrupt is generated the processor always jumps to the code at hardware address 0x0004 for a PIC16 (0x0008 for a PIC18). What you see here is a trick to pass the interrupt call on to the interrupt handler of your application.
The following code does the same and is easier to understand: Code: | #org 0x0005, 0x0009
void remap_interrupt()
{
goto_address( LOADER_END+5 );
} |
Quote: | 4. The SIOW program sends the hex file. Is it hard to write your own PC tool that does that? What's the algorythm? | SIOW is just a standard terminal emulator. Any other program that is capable of sending a specified text file over RS232 will do. Examples are: Hyperterm, Procomm, Terminal, etc.
To call it an algorithm is too much praise, the only thing SIOW does is taking the *.hex file (just plain ASCII text) and transmitting it to the PIC over RS-232. In order to prevent buffer overflow the bootloader in the PIC will send standard XON/XOFF flow control characters.
Writing your own program should be a piece of cake.
Understanding the contents of the *.hex file is not really required but could help. Search Google for 'Intel hex format'. |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Thu Jan 04, 2007 4:26 am |
|
|
Hi, thanks for the reply. I managed to get a little further. But It doesn't seem to download? This is my code:
bootloader.h:
Code: | //#if defined(__PCM__) // PIC16 compiler
#define LOADER_END 0x1FF // 511
#define LOADER_SIZE 0x1BF // 447
//#elif defined(__PCH__)
// #define LOADER_END 0x4FF
// #define LOADER_SIZE 0x3FF
//#endif
#ifndef _bootloader // Als bootloader ergens gedefinieerd is
// reset en interrupt vectoren verplaatsen, anders worden ze overschreven
//#if defined(__PCM__)
#build(reset=LOADER_END+1, interrupt=LOADER_END+5)
//#elif defined(__PCH__)
// #build(reset=LOADER_END+2, interrupt=LOADER_END+8)
//#endif
#org 0, LOADER_END {} // tussen geheugen 0 en LOADER_END => vrij anders wordt de bootloader overschreven
#endif |
bootloader.c:
Code: | #include <16F877A.h>
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#define _bootloader
#include <bootloader.h>
#include <loader.c>
#org LOADER_END+1,LOADER_END+10 // Die functie start op loader_end + 1 tot loader_end + 10
void application (void) // Dummy functie, eigenlijk staat hier de �chte main
{
putc ('A');
while(TRUE);
}
#org 0x20,0x3F // De main staat tussen adres 0x20 en 0x3F
void main ()
{
long timeout = 0;
while ( !kbhit() && (++timeout < 50000) ) // 5 seconds
delay_us (100);
if ( kbhit() )
{
if ( getc() == 170 )
{
timeout = 0;
while ( !kbhit() && (++timeout < 50000)) // 5 seconds
delay_us (100);
if ( kbhit () )
if ( getc() == 170 )
{
putc ('B');
load_program();
}
}
}
application(); // Jump to real application
}
#ORG default // Vanaf
#int_global
void isr(void)
{
#asm
goto LOADER_END+5
#endasm
} |
test.c:
Code: | #include <16F877A.h>
#device adc=10 *=16
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#define SIZE 25
#define LEESREGEL 0
#include "tones.c"
#include <bootloader.h>
const struct note
{
long tone;
long length;
} happy_bday[SIZE] = {
C_note[0],350, C_note[0],100, D_note[0],500, C_note[0],500, F_note[0],500, E_note[0],900,
C_note[0],350, C_note[0],100, D_note[0],500, C_note[0],500, G_note[0],500, F_note[0],900,
C_note[0],350, C_note[0],100, C_note[1],500, A_note[0],500, F_note[0],500, E_note[0],500, D_note[0],900,
Bb_note[0],350, Bb_note[0],100, A_note[0],500, F_note[0],500, G_note[0],500, F_note[0],1200};
void MAIN ()
{
int i;
//**************************** SIGNAAL BIJ RESET *****************************//
if ( !LEESREGEL ) // Als geen leesregel
output_low (PIN_C2); // - van de buzzer aan massa
setup_adc_ports (NO_ANALOGS); // ADC UIT
setup_adc (ADC_OFF);
setup_timer_1 (T1_DISABLED); // T1 uit
setup_timer_2 (T2_DISABLED,0,1); // T2 uit
setup_psp (PSP_DISABLED); // PSP UIT
setup_comparator (NC_NC_NC_NC); // COMPARATOR UIT
setup_vref (FALSE);
enable_interrupts (INT_RDA); // RDA interrupt enable
enable_interrupts (GLOBAL); // GLOBAL interrupt enable
while (TRUE)
{
for(i=0; i<SIZE; ++i)
{
generate_tone(happy_bday[i].tone,happy_bday[i].length);
delay_ms(75);
}
putc ('K');
delay_ms (500);
} //while (TRUE)
} //main |
1. I get a compiler error: OUT of ROM, a segment is too large. Probably the main segment is too large. If I want to change the #org values, I get an invalid org range error. Anyone? compiler 3.226
2. About the entering download mode using timeouts; is my code elegant or can it be written shorter?
tks!
Last edited by Christophe on Thu Jan 04, 2007 10:02 am; edited 1 time in total |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Thu Jan 04, 2007 10:00 am |
|
|
That invalid org range is seriously breakin' my balls here. I really hope someone of the pros can solve this one.. |
|
|
BOB_SANTANA
Joined: 16 Oct 2006 Posts: 110 Location: HOVE, EAST SUSSEX
|
|
Posted: Thu Jan 04, 2007 3:04 pm |
|
|
Try running the example programmes as they are and only change the application program example leave all the include file as they are this your bootloader.h
Code: |
//#if defined(__PCM__) // PIC16 compiler
#define LOADER_END 0x1FF // 511
#define LOADER_SIZE 0x1BF // 447
//#elif defined(__PCH__)
// #define LOADER_END 0x4FF
// #define LOADER_SIZE 0x3FF
//#endif
#ifndef _bootloader // Als bootloader ergens gedefinieerd is
// reset en interrupt vectoren verplaatsen, anders worden ze overschreven
//#if defined(__PCM__)
#build(reset=LOADER_END+1, interrupt=LOADER_END+5)
//#elif defined(__PCH__)
// #build(reset=LOADER_END+2, interrupt=LOADER_END+8)
//#endif
#org 0, LOADER_END {} // tussen geheugen 0 en LOADER_END => vrij anders wordt de bootloader overschreven
#endif
|
This is the original
Code: |
#if defined(__PCM__)
#define LOADER_END 0x1FF
#define LOADER_SIZE 0x1BF
#elif defined(__PCH__)
#define LOADER_END 0x4FF
#define LOADER_SIZE 0x3FF
#endif
#ifndef _bootloader
#if defined(__PCM__)
#build(reset=LOADER_END+1, interrupt=LOADER_END+5)
#elif defined(__PCH__)
#build(reset=LOADER_END+1, interrupt=LOADER_END+9)
#endif
#org 0, LOADER_END {}
#endif
|
_________________ BOB_Santana |
|
|
BOB_SANTANA
Joined: 16 Oct 2006 Posts: 110 Location: HOVE, EAST SUSSEX
|
|
Posted: Thu Jan 04, 2007 3:16 pm |
|
|
I have just complied your code without any errors and i didn't change anything just see below
Code: |
//#include <16F877A.h>
//#device adc=10 *=16
//#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
//#use delay(clock=4000000)
//#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#if defined(__PCM__)
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#define SIZE 25
#define LEESREGEL 0
#include "tones.c"
#include <bootloader.h>
const struct note
{
long tone;
long length;
} happy_bday[SIZE] = {
C_note[0],350, C_note[0],100, D_note[0],500, C_note[0],500, F_note[0],500, E_note[0],900,
C_note[0],350, C_note[0],100, D_note[0],500, C_note[0],500, G_note[0],500, F_note[0],900,
C_note[0],350, C_note[0],100, C_note[1],500, A_note[0],500, F_note[0],500, E_note[0],500, D_note[0],900,
Bb_note[0],350, Bb_note[0],100, A_note[0],500, F_note[0],500, G_note[0],500, F_note[0],1200};
void MAIN ()
{
int i;
//**************************** SIGNAAL BIJ RESET *****************************//
if ( !LEESREGEL ) // Als geen leesregel
output_low (PIN_C2); // - van de buzzer aan massa
setup_adc_ports (NO_ANALOGS); // ADC UIT
setup_adc (ADC_OFF);
setup_timer_1 (T1_DISABLED); // T1 uit
setup_timer_2 (T2_DISABLED,0,1); // T2 uit
setup_psp (PSP_DISABLED); // PSP UIT
setup_comparator (NC_NC_NC_NC); // COMPARATOR UIT
setup_vref (FALSE);
enable_interrupts (INT_RDA); // RDA interrupt enable
enable_interrupts (GLOBAL); // GLOBAL interrupt enable
while (TRUE)
{
for(i=0; i<SIZE; ++i)
{
generate_tone(happy_bday[i].tone,happy_bday[i].length);
delay_ms(75);
}
putc ('K');
delay_ms (500);
} //while (TRUE)
} //main |
_________________ BOB_Santana |
|
|
BOB_SANTANA
Joined: 16 Oct 2006 Posts: 110 Location: HOVE, EAST SUSSEX
|
|
Posted: Thu Jan 04, 2007 3:28 pm |
|
|
i used your bootloader.c and Test.c exactly as you have it and was able to complier the program
what version are you using ? _________________ BOB_Santana |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jan 04, 2007 5:38 pm |
|
|
Christophe wrote: | That invalid org range is seriously breakin' my balls here. I really hope someone of the pros can solve this one.. | It is possible that the use of TAB characters in the line containing the #org statement is causing your "Invalid ORG range" error message.
This is a known error in the v3.249 CCS preprocessor, check also the last few messages in thread http://www.ccsinfo.com/forum/viewtopic.php?t=20971
This compiler error would explain why a copy/paste of the code from the forum (no TABs) is working while your original but identical code (with TABs) fails. |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Fri Jan 05, 2007 2:02 am |
|
|
Tks for the support. Still I don't manage to compile. My compiler version is 3.226 and I removed all tabs and comments after #org. Any help? Can somebody try to compile this?
bootloader.h:
Code: | #define LOADER_END 0x1FF
#define LOADER_SIZE 0x1BF
#ifndef _bootloader
#build ( reset = LOADER_END+1 , interrupt = LOADER_END+5 )
#org 0, LOADER_END {}
#endif |
bootloader.c
Code: | #include <16F877A.h>
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)
#define _bootloader
#include "bootloader.h"
#include "loader.c"
#org LOADER_END+1,LOADER_END+10
void application (void) // Dummy functie, eigenlijk staat hier de �chte main
{
putc ('A');
while(TRUE);
}
#org 0x20, 0x80
void main (){
long timeout = 0;
while ( !kbhit() && (++timeout < 50000) ) // 5 seconds
delay_us (100);
if ( kbhit() )
{
if ( getc() == 170 )
{
timeout = 0;
while ( !kbhit() && (++timeout < 50000)) // 5 seconds
delay_us (100);
if ( kbhit () )
if ( getc() == 170 )
{
putc ('B');
load_program();
}
}
}
application(); // Jump to real application
}
#ORG default
#int_global
void isr(void)
{
#asm
goto LOADER_END+5
#endasm
} |
|
|
|
Guest
|
|
Posted: Fri Jan 05, 2007 3:41 am |
|
|
What version of Mplab are you using?
Try re-installing CCS and the CCS software that calls Mplab |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Fri Jan 05, 2007 3:43 am |
|
|
Anonymous wrote: | What version of Mplab are you using?
Try re-installing CCS and the CCS software that calls Mplab |
I'm using CCS pcwh v3.226. I don't think reinstalling would help honestly. |
|
|
Guest
|
|
Posted: Fri Jan 05, 2007 4:54 am |
|
|
Suit Youeself
BTW the code complies here |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Fri Jan 05, 2007 4:55 am |
|
|
Anonymous wrote: | Suit Youeself
BTW the code complies here |
thanks, version? |
|
|
|
|
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
|