|
|
View previous topic :: View next topic |
Author |
Message |
fordcf2000
Joined: 11 Oct 2014 Posts: 2
|
PIC24EP512GU814 write_program_memory issue |
Posted: Wed Sep 16, 2015 3:38 pm |
|
|
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: 19538
|
|
Posted: Thu Sep 17, 2015 7:36 am |
|
|
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
|
|
Posted: Thu Sep 17, 2015 8:00 am |
|
|
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: 19538
|
|
Posted: Thu Sep 17, 2015 9:10 am |
|
|
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.... |
|
|
|
|
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
|