![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
Self programming code relocation |
Posted: Tue Apr 18, 2006 9:29 am |
|
|
CCS-V3.249
I have a program that Rcv data, process packets, and if the data is a new program it stores it in FRAM at 0-0x7FFF. I have a self programming function that worked when #org'd at the end of memory. I need help in trying to move it to the protected begining of memory.
I am getting invalid org range when I try moving PrgmPIC to low mem.
Code: | #include <18F452.H>
#case
#use delay(clock=40000000)
#fuses h4,nowdt,noprotect,nolvp
#use rs232(baud=19200,xmit=PIN_C0,invert,stream=DEBUG,disable_ints) // stderr(same as debug)
#zero_ram
//------------------------------------------------------------------//
#ifndef hi
#define hi(x) (*(&x+1)) //data held at addr of x + 1
#define lo(x) (*(&x)) //data held at addr of x
#endif
void main_app(void);
#separate
void PrgmPIC(void);
int8 int_count_tmr3,RX_BUF[64];
void main(void){
main_app();
}
void main_app(void){
set_tris_c(0xFF);set_tris_a(0);set_tris_b(0);set_tris_d(0);set_tris_e(0);
setup_adc_ports(NO_ANALOGS);
setup_timer_3(T3_INTERNAL|T3_DIV_BY_8);
set_timer3(0);
int_count_tmr3 = 20;
enable_interrupts(INT_TIMER3);
enable_interrupts(GLOBAL);
fprintf(DEBUG,"Rx packet\n\r");
fprintf(DEBUG,"Process packet\n\r");
fprintf(DEBUG,"If program data save in FRAM\n\r");//FRAM addr 0-0x7FFF
fprintf(DEBUG,"Now ProgPIC\n\r");//ProgPIC is in protected Boot area
PrgmPIC();
fprintf(DEBUG,"Reset_CPU\n\r");
fprintf(DEBUG,"DONE !\n\r");
while(1)
{
}
}
//=======================timer 2 ISR============================//
#INT_TIMER3 // This function is called every time
void timer3_isr() { // timer 2 overflows (250->0), which is
int8 x;
if(--int_count_tmr3==0){// approximately 61 times per second for this program.
fprintf(DEBUG,".");
int_count_tmr3 = 20;
}
}
//===================== PrgmPIC ===================code size=0x02A0=672
//#org 0x7D20, 0x7FC0 default
//#org 0x0700, 0x0A00 default
//#org 0x0030, 0x0400 default
#org 0x0070, 0x0330 default
#use I2C(MASTER,SDA=PIN_C4,SCL=PIN_C3,FORCE_HW,FAST,RESTART_WDT)
void PrgmPIC(void){//FRAM addr 0-0x7FFF stores the program
#use I2C(MASTER,SDA=PIN_C4,SCL=PIN_C3,FORCE_HW,FAST,RESTART_WDT)
int32 address;
int8 data,size;
#define block 64
char *ptr_char;
disable_interrupts(INT_RDA);
output_low(PIN_C5);//tx enable
output_high(PIN_C6);
//Read the FRAM in 64 byte block and self program the PIC
for(address=(int32)0;address<0x7D00;address+=block){ //read 8 bytes prgm from fram
ptr_char=&RX_BUF[0];//&RX_BUF[0] is defined as global. char RX_BUF[256];
for(size=block;size;ptr_char++,size--){
if(size==block){
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
i2c_write(hi(address));
i2c_write(lo(address));
i2c_start();
i2c_write((0xA0|(int8)(address>>14))|1);//|1 forces to read
}
if(size==1)
{
*ptr_char=i2c_read(0);//No ack on last read of block
i2c_stop();
}
else
{
*ptr_char=i2c_read(1);//The ack will put next data on bus
}
}
write_program_memory(address,&RX_BUF[0],64);//write=8,erase=64
restart_wdt();
}
reset_cpu();//last step is reset the CPU and see if programming worked
}
#org default
#int_global
void isr(void) {
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
//#build(reset=0x0350, interrupt=0x0250)
//PrgmPIC();
|
Last edited by treitmey on Tue Apr 18, 2006 10:45 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Tue Apr 18, 2006 9:48 am |
|
|
There are several problems.
First, you cannot have a int_timer3 declaration, when you have an int_global declaration. As soon as you have the latter, _you_ become responsible for vectoring to all the interrupt handlers.
The second problem, is that you memory range is already used by the main routine. Declare this after your relocated routine, and add a #org default line after your routine, to allow normal memory management to 'restart' at this point.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Tue Apr 18, 2006 9:56 am |
|
|
I thought I wanted the ISR to be re-programable. Thus they needed to be outside of the "protected" area. That is why is tried the int_global to redirect to the new ISR. Is this the correct way to handle this?
Is this how you suggested it? main inside protected area, which simply jumps outside to the main_app() ? ((this won't compile))
Code: | #include <18F452.H>
#case
#use delay(clock=40000000)
#fuses h4,nowdt,noprotect,nolvp
#use rs232(baud=19200,xmit=PIN_C0,invert,stream=DEBUG,disable_ints) // stderr(same as debug)
#zero_ram
//------------------------------------------------------------------//
#ifndef hi
#define hi(x) (*(&x+1)) //data held at addr of x + 1
#define lo(x) (*(&x)) //data held at addr of x
#endif
void main_app(void);
#separate
void PrgmPIC(void);
int8 int_count_tmr3,RX_BUF[64];
#org 0x0040, 0x06F default
void main(void){
main_app();
}
#org default
//===================== PrgmPIC ===================code size=0x02A0=672
//#org 0x7D20, 0x7FC0 default
//#org 0x0700, 0x0A00 default
//#org 0x0030, 0x0400 default
#org 0x0070, 0x0330 default
#use I2C(MASTER,SDA=PIN_C4,SCL=PIN_C3,FORCE_HW,FAST,RESTART_WDT)
void PrgmPIC(void){//FRAM addr 0-0x7FFF stores the program
#use I2C(MASTER,SDA=PIN_C4,SCL=PIN_C3,FORCE_HW,FAST,RESTART_WDT)
int32 address;
int8 data,size;
#define block 64
char *ptr_char;
disable_interrupts(INT_RDA);
output_low(PIN_C5);//tx enable
output_high(PIN_C6);
//Read the FRAM in 64 byte block and self program the PIC
for(address=(int32)0;address<0x7D00;address+=block){ //read 8 bytes prgm from fram
ptr_char=&RX_BUF[0];//&RX_BUF[0] is defined as global. char RX_BUF[256];
for(size=block;size;ptr_char++,size--){
if(size==block){
i2c_start();
i2c_write((0xA0|(int8)(address>>14))&0xFE);//&0xFE forces to write
i2c_write(hi(address));
i2c_write(lo(address));
i2c_start();
i2c_write((0xA0|(int8)(address>>14))|1);//|1 forces to read
}
if(size==1)
{
*ptr_char=i2c_read(0);//No ack on last read of block
i2c_stop();
}
else
{
*ptr_char=i2c_read(1);//The ack will put next data on bus
}
}
write_program_memory(address,&RX_BUF[0],64);//write=8,erase=64
restart_wdt();
}
reset_cpu();//last step is reset the CPU and see if programming worked
}
#org default
void main_app(void){
set_tris_c(0xFF);set_tris_a(0);set_tris_b(0);set_tris_d(0);set_tris_e(0);
setup_adc_ports(NO_ANALOGS);
setup_timer_3(T3_INTERNAL|T3_DIV_BY_8);
set_timer3(0);
int_count_tmr3 = 20;
enable_interrupts(INT_TIMER3);
enable_interrupts(GLOBAL);
fprintf(DEBUG,"Rx packet\n\r");
fprintf(DEBUG,"Process packet\n\r");
fprintf(DEBUG,"If program data save in FRAM\n\r");//FRAM addr 0-0x7FFF
fprintf(DEBUG,"Now ProgPIC\n\r");//ProgPIC is in protected Boot area
PrgmPIC();
fprintf(DEBUG,"Reset_CPU\n\r");
fprintf(DEBUG,"DONE !\n\r");
while(1)
{
}
}
//=======================timer 2 ISR============================//
#INT_TIMER3 // This function is called every time
void timer3_isr() { // timer 2 overflows (250->0), which is
int8 x;
if(--int_count_tmr3==0){// approximately 61 times per second for this program.
fprintf(DEBUG,".");
int_count_tmr3 = 20;
}
}
#int_global
void isr(void) {
jump_to_isr(0x0340);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Apr 18, 2006 10:51 am |
|
|
You use the timer interrupt in the bootloader for progress information. Nice but not very accurate, you are only showing the time passed since program start, it doesn't say anything about actual progress. Assume that the programming algorithm fails then you will still be outputing new '. ' characters. Why not change your program as to output a '.' character after programming every 512 bytes? That will give you:
- more accurate progress information
- you don't need the interrupt anymore
- and without the interrupt overhead the bootloader will be smaller.
Without using interrupts in your bootloader you can use the #build command to relocate the interrupt vectors. |
|
![](templates/subSilver/images/spacer.gif) |
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Tue Apr 18, 2006 11:24 am |
|
|
Didn't mean to mislead you. The #INT_TIMER3 is just so I have an INT. I want the ISR's in the unprotected(re-programmable) area. I didn't mean it to do anything. In the real code I use RDA and others,.. timer3 was just a short and handy representation.
The problem is I can't get the code PrgmPIC in low mem. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|