CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Self programming code relocation

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

Self programming code relocation
PostPosted: Tue Apr 18, 2006 9:29 am     Reply with quote

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
Ttelmah
Guest







PostPosted: Tue Apr 18, 2006 9:48 am     Reply with quote

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
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Apr 18, 2006 9:56 am     Reply with quote

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);
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Apr 18, 2006 10:51 am     Reply with quote

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.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Apr 18, 2006 11:24 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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