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

PIC24EP512GU814 write_program_memory issue

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



Joined: 11 Oct 2014
Posts: 2

View user's profile Send private message

PIC24EP512GU814 write_program_memory issue
PostPosted: Wed Sep 16, 2015 3:38 pm     Reply with quote

I am currently trying to get a bootloader to work with the 24EP514GU814. The bootloader is working other than at certain addresses the write_program_memory function will not write the data.

I put the bootloader at address 0x40000 (#org 0x40000 default).
The main code will start at address 0x200 (#org default)
When bootloading, starting at address 0x220, some of the values are not being written to program memory.

Any suggestions would be appreciated.
Communication via e-mail would be the quickest way for me to respond.
fordcf2000@gmail.com



main.h for both bootloader and main program
Code:

#include <24EP512GU814.h>
#device ADC=10
#org default

//these must be set to NO in order to write to the program memory for the bootloader
   #FUSES NOWRT                    //Program memory not write protected
   #FUSES NOPROTECT                //Code not protected from reading       
   #FUSES NOGSSK                   //General Segment Key bits, use if using either WRT or PROTECT fuses
//

#FUSES WDT                    //No Watch Dog Timer
#FUSES NOIESO                     //Internal External Switch Over mode enabled
#FUSES OSCIO                    //OSC2 is clock output
#FUSES NOIOL1WAY                  //Allows only one reconfiguration of peripheral pins
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES PLLWAIT                  //Clock switch to PLL will wait until the PLL lock signal is valid
#FUSES WINDIS                   //Watch Dog Timer in non-Window mode
#FUSES PUT128                   //Power On Reset Timer value 128ms
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOALTI2C1                //I2C1 mapped to SDA1/SCL1 pins
#FUSES NOALTI2C2                //I2C2 mapped to SDA2/SCL2 pins
#FUSES RESET_PRIMARY            //Device will reset to Primary Flash Reset location
#FUSES NOJTAG                   //JTAG disabled
#FUSES NOAWRT                   //Auxiliary program memory is not write-protected
#FUSES NOAPROTECT               //Auxiliary program memory is not code-protected
#FUSES NOAPLK                     //Auxiliary Segment Key bits, use if using either AWRT or APROTECT fuses
#FUSES NODEBUG   

#use delay(internal=7.37MHz)

#pin_select SDI1 = PIN_g7
#pin_select SDO1 = PIN_G8
#pin_select SCK1OUT = PIN_G6



//RS232-1           
#define Radio_baud 9600
#pin_select U1TX=PIN_F2                     
#pin_select U1RX=PIN_F8                                     
#use rs232(UART1,baud=radio_baud,errors, stream=radio)
       
   
//RS232-2   
#pin_select U2TX=PIN_D1
#pin_select U2RX=PIN_D12     
#use rs232(UART2,BAUD=9600,ERRORS,stream=EXT_COM)

//computer
#define computer_baud 2400
#pin_select U3TX=PIN_D2
#pin_select U3RX=PIN_D13                           
#use rs232(UART3, baud=computer_baud,errors, stream=computer)
                   
//XBEE
#pin_select U4TX=PIN_G15
#pin_select U4RX=PIN_E9
#use rs232(UART4, baud=9600,  errors, stream=XBEE)

#use rs232(baud=4800,xmit=pin_D3,RCV=pin_D11,errors,stream=GPS_Module)
#use rs232(baud=9600,xmit=pin_k11,RCV=pin_D8,errors,stream=RS485)

#pin_select INT1=PIN_G13//rain gauge
#pin_select INT2=PIN_G12//flow1
#pin_select INT3=PIN_G14//flow2

#define Alive_led              PIN_J9
#define regulator_enable       PIN_B2
#define com_chip               PIN_J0
#define rs232_forceoff         PIN_J1
#define SD_Detect              PIN_J8

[b]Main.c of bootloader[/b]

#include <main.h>

void application(void){
    while(TRUE){//start main loop
      output_toggle(alive_led);
      delay_ms(1000);
      restart_wdt();
   }
}


//all code beyond this point will be in program memory above 0x40000
#org 0x40000 default
//#include <my_pcd_bootloader.h>
#include <my_loader_pcd.c>



void main(void){
   output_low(com_chip);//Turn on RS-232 chip
   output_high(rs232_forceoff);//Enable the RS-232 chip
   output_high(regulator_enable);//turn on the voltage regulator to run the RS-232 chip
   delay_ms(100);//all the regulator to power up
   
   fprintf(ext_com,"hello: %u\r",restart_cause());
    if(!input_state(SD_Detect)){//see if the sd card is pushed in
      fprintf(ext_com,"\r\nBootloader Version 1.0\r\n");
      // Let the user know it is ready to accept a download
      fprintf(ext_com,"\r\nWaiting for download...\r");

      // Load the program
      load_program();
   }
   else{
      fprintf(ext_com,"no card\r");//SD card is not inserted
   }
   application();
}

my_loader_pcd.c (actual bootloader)

#define BUFFER_LEN_LOD 64
#define BUFFER_COUNT   1
#WORD NVMKEY = 0x072E
#word NVMCON = 0x0728
#word NVMADRU= 0x072A
#word NVMADR = 0x072C
#word tblpage = 0x0054
struct{
   unsigned int16 idx;
   char buffer[BUFFER_LEN_LOD];
} rBuffer[BUFFER_COUNT];

#define ACKLOD 0x06
#define XON    0x11
#define XOFF   0x13
#define LOADER_END 0x4FFFE
#define LOADER_ADDR 0x40000


unsigned int8 atoi_b16(char *s);


void load_program (void){
   unsigned int1  do_ACKLOD, done=FALSE;
   unsigned int8  checksum, line_type;
   unsigned int16 l_addr,h_addr=0;
   unsigned int32 addr;
   unsigned int8  dataidx;
   unsigned int16 i,z;
   unsigned int16 count=0;
   unsigned int8  data[32],d[32];
   unsigned int8  buffidx;
 
 
   buffidx = 0;
   
   
   while (!done){  // Loop until the entire program is downloaded
         restart_wdt();
         rBuffer[buffidx].idx = 0;  // Read into the buffer until 0x0D ('\r') is received or the buffer is full
         rBuffer[0].buffer[0]=0;
         buffidx=0;
      do{
         rBuffer[buffidx].buffer[rBuffer[buffidx].idx] = fgetc(computer);
         fputc(rBuffer[buffidx].buffer[rBuffer[buffidx].idx],ext_com);
      }
      while ((rbuffer[buffidx].buffer[rBuffer[buffidx].idx++] != 0x0A) && (rbuffer[buffidx].idx <= BUFFER_LEN_LOD));
         fPutc(XOFF,computer);  // Suspend sender
         do_ACKLOD = false;
               // Only process data blocks that start with ':'
               if (rBuffer[0].buffer[0] == ':'){
                  count = atoi_b16 (&rBuffer[0].buffer[1]);  // Get the number of bytes from the buffer
         
                  // Get the lower 16 bits of address
                  l_addr = make16(atoi_b16(&rBuffer[0].buffer[3]),atoi_b16(&rBuffer[0].buffer[5]));
         
                  line_type = atoi_b16 (&rBuffer[0].buffer[7]);
                  addr = ((make32(h_addr,l_addr))/2);
         
                  checksum = 0;  // Sum the bytes to find the check sum value
                  for (i=1; i<(rBuffer[0].idx-5); i+=2){
                     checksum += atoi_b16 (&rBuffer[0].buffer[i]);
                  }   
                  checksum = 0xFF - checksum + 1;
                 
                  fprintf(ext_com,"calc checksum = %X\r",checksum);
                  if (checksum != atoi_b16 (&rBuffer[0].buffer[rBuffer[0].idx-4])){
                     do_ACKLOD = FALSE;
                     fprintf(ext_com,"  Checksum failed. %X\r",atoi_b16 (&rBuffer[0].buffer[rBuffer[0].idx-4]));
                  }
                  else{
                     do_ACKLOD = true;
                     fprintf(ext_com,"  Checksum PASSED\r");
                     // If the line type is 1, then data is done being sent
                     if (line_type == 1){
                        done = TRUE;
                     }
                     else if (line_type == 4){
                        h_addr = make16(atoi_b16(&rBuffer[0].buffer[9]), atoi_b16(&rBuffer[0].buffer[11]));
                     }   
                     else if (line_type == 0){
                          if ((addr < LOADER_ADDR) && (addr>=0x200) && addr < getenv("PROGRAM_MEMORY")){        // Loops through all of the data and stores it in data
                             fprintf(ext_com,"writing firmware\r");
                             for (i = 9,dataidx=0; i < rBuffer[0].idx-3; i += 2){
                                 data[dataidx++]=atoi_b16(&rBuffer[0].buffer[i]);
                             }   
                             fprintf(ext_com,"Addr = 0x%lX\rCount = 0x%X\r",addr,count);
                             
                             write_program_memory(addr,data,count);//only write 8 values at first(2 addresses of data);
                             delay_ms(1);
                             read_program_memory(addr,d,count);
                             for (z=0;z<count;z++){
                                 fprintf(ext_com,"%u = %X  %X\r",z,data[z],d[z]);
                                  if (data[z] != d[z]){
                                     delay_ms(1000);
                                  }
                             }
                         }
                     }
                  }
               }
             
       
         fprintf(ext_com,"next line\r");
         if (do_ACKLOD){
            fPutc(ACKLOD,computer);
         }   
         fPutc(XON,computer);
   }
   fPutc(ACKLOD,computer);
   fPutc(XON,computer);
   fprintf(ext_com,"\r\rrebooting\r");
   delay_ms(5);
   reset_cpu();
}

unsigned int8 atoi_b16(char *s) {  // Convert two hex characters to a int8
   unsigned int8 result = 0;
   unsigned int8 i;

   for (i=0; i<2; i++,s++){
      if (*s >= 'A')
         result = 16*result + (*s) - 'A' + 10;
      else
         result = 16*result + (*s) - '0';
   }

   return(result);
}

Main.c (test program I'm trying to load)
Code:


#include "C:\Users\Chad\Desktop\New folder\main.h"
#ZERO_RAM

void application(void){
   output_low(alive_led);
   output_high(Regulator_enable);
   while(true){
      restart_wdt();
      output_toggle(alive_led);
      delay_ms(50);
  }
}

#org 0x40000 default
#include "C:\Users\Chad\Desktop\New folder\my_loader_pcd.c"

void main(void){
   output_low(com_chip);
   output_high(rs232_forceoff);
   output_high(regulator_enable);
   delay_ms(100);
   fprintf(ext_com,"hello: %u\r",restart_cause());
    if(!input_state(SD_Detect)){
      fprintf(ext_com,"\r\nBootloader Version 1.0\r\n");
      // Let the user know it is ready to accept a download
      fprintf(ext_com,"\r\nWaiting for download...\r");

      // Load the program
      load_program();
   }
   else{
      fprintf(ext_com,"no press\r");
   }
   application();
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19358

View user's profile Send private message

PostPosted: Thu Sep 17, 2015 7:36 am     Reply with quote

You do realise how the flash pages work on these chip?.

You can't write to an address like 0x200 and put new data there replacing the old.
The erase page on this chip is 3072 bytes (1K instructions). To write something to the middle of a page, you have to read the entire page, change the bytes you want, then write the whole page back. The write_program_memory function, will erase the page, if you write to the first address in the page, _but not otherwise_.
It'll do a write of a small part like you are using, _if you erase the page first_.

You have to get your head into the page based layout of the flash memory. Load lines from your file, till you have a complete page, or have finished the file, and then write the whole page.
fordcf2000



Joined: 11 Oct 2014
Posts: 2

View user's profile Send private message

PostPosted: Thu Sep 17, 2015 8:00 am     Reply with quote

I will give that a try. I'm used to working with the 18F6722 where I can write one address at a time.
Ttelmah



Joined: 11 Mar 2010
Posts: 19358

View user's profile Send private message

PostPosted: Thu Sep 17, 2015 9:10 am     Reply with quote

You can still write just one instruction at a time (instruction, not byte), but only to a page that has already been erased (or to a location whose value happens to be such that all bits that you need erased in the 'result', are already erased).
There is also a block write that writes 128 instructions (384 bytes), taking the same time as a single write.

Remember also that the memory is organised as:
Code:

B B B x
B B B x
B B B x

So the '128 instructions', above, corresponds to 512 bytes sent to the write_program_memory function, with every fourth byte 'missing'. The erase page is also on each 4096byte boundary in the address range. So 0x00000, 0x01000, 0x02000 etc...

The 6722, also erases in pages, but only of 64 bytes at a time, and doesn't have the gaps....
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