|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Sun Nov 22, 2015 3:24 pm |
|
|
But, if you are loading this data via a system like a cell phone, then this is the main CRC you should check to verify that the whole communication has worked.
Problem is that the 'per line' CRC, does not guarantee that you have received the whole file. You could lose an entire line, and these would still be OK, but now the program would have a 'hole' in it..... |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Sun Nov 22, 2015 6:28 pm |
|
|
PCM programmer wrote: | It's a hex file comment. It should be ignored by the bootloader in the PIC.
The file 'loader.c' says this:
Quote: | // Only process data blocks that start with ':'
if (rBuffer[0].buffer[0] == ':')
{
|
Since that line starts with ';', the code will ignore it. |
You're right!
I thought that was what was missing, but it is not.
I put some PRINTS to see where the error was.
I tested the bootloader transferring the program from the PC and then reading external EEPROM memory.
this was the result!
Code: |
while (!done) // Loop until the entire program is downloaded
{
buffidx = 0; // Read into the buffer until 0x0D ('\r') is received or the buffer is full
flag_primeiro=1;
for (J = 0; J < 64; J++) {
buffer[J] = NULL;
}
/*
do {
//buffer[buffidx] = getc();
aux_eeprom = read_ext_eeprom(contador);
if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
if(aux_eeprom == 'O'){
if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
}
buffer[buffidx] = aux_eeprom;
contador = contador + 1;
flag_primeiro=0;
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
*/
do {
buffer[buffidx] = getc();
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
putchar (XOFF); // Suspend sender
do_ACKLOD = TRUE;
// Only process data blocks that start with ':'
if (buffer[0] == ':')
{
printf("\r\n%s",buffer);
count = atoi_b16 (&buffer[1]); // Get the number of bytes from the buffer
printf("\r\n2- %d",buffer[1]);
printf("\r\n3- %d",count);
// Get the lower 16 bits of address
l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));
printf("\r\n4- %ld",l_addr);
line_type = atoi_b16 (&buffer[7]);
printf("\r\n5- %d",line_type);
addr = make32(h_addr,l_addr);
printf("\r\n6- %ld",addr);
#if defined(__PCM__) // PIC16 uses word addresses
addr /= 2;
#endif
checksum = 0; // Sum the bytes to find the check sum value
for (i=1; i<(buffidx-3); i+=2)
checksum += atoi_b16 (&buffer[i]);
checksum = 0xFF - checksum + 1;
printf("\r\nCS:%d",checksum);
if (checksum != atoi_b16 (&buffer[buffidx-3]))
do_ACKLOD = FALSE;
else
{
|
result from PC:
:0406400037EF03F09D
2- 48
3- 4
4- 1600
5- 0
6- 1600
CS:-99
:08064800EA6A050EE96EEF50AD
2- 48
3- 8
4- 1608
5- 0
6- 1608
CS:-83
:100650000DE0060E016E006A002EFED7012EFBD7BC
2- 49
3- 16
4- 1616
5- 0
6- 1616
CS:-68
:100660007B0E006E002EFED7EF2EF3D71200F86A35
2- 49
3- 16
4- 1632
5- 0
6- 1632
CS:53
:10067000D09EB8862A0EAF6E000EB06EA60EAC6E7F
2- 49
3- 16
4- 1648
5- 0
6- 1648
CS:127
:10068000900EAB6EC150C00B0F09C16E840ED56EBB
2- 49
3- 16
4- 1664
5- 0
6- 1664
CS:-69
:10069000F29AF298F096F0989D9AF29CF29EF2BE31
2- 49
3- 16
4- 1680
5- 0
6- 1680
CS:49
:1006A000FDD794928B92939A8A8A640E056ECCDF62
2- 49
3- 16
4- 1696
5- 0
6- 1696
CS:98
:0E06B000939A8A9A640E056EC7DFF5D7030091
2- 48
3- 14
4- 1712
5- 0
6- 1712
CS:-111
:020000040030CA
2- 48
3- 2
4- 0
5- 4
6- 0
CS:-54
:0E00000000C2180E0084810000C03FE03F40A7
2- 48
3- 14
4- 0
5- 0
6- 3145728
CS:-89
:00000001FF
2- 48
3- 0
4- 0
5- 1
6- 3145728
CS:-1
-----------------------------------------
result from EEPROM:
:0406400037EF03F09D
2- 48
3- 4
4- 1600
5- 0
6- 1600
CS:-99
:08064800EA6A050EE96EEF50AD
2- 48
3- 8
4- 1608
5- 0
6- 1608
CS:-83
:100650000DE0060E016E006A002EFED7012EFBD7BC
2- 49
3- 16
4- 1616
5- 0
6- 1616
CS:-68
:100660007B0E006E002EFED7EF2EF3D71200F86A35
2- 49
3- 16
4- 1632
5- 0
6- 1632
CS:53
:10067000D09EB8862A0EAF6E000EB06EA60EAC6E7F
2- 49
3- 16
4- 1648
5- 0
6- 1648
CS:127
:10068000900EAB6EC150C00B0F09C16E840ED56EBB
2- 49
3- 16
4- 1664
5- 0
6- 1664
CS:-69
:10069000F29AF298F096F0989D9AF29CF29EF2BE31
2- 49
3- 16
4- 1680
5- 0
6- 1680
CS:49
:1006A000FDD794928B92939A8A8A640E056ECCDF62
2- 49
3- 16
4- 1696
5- 0
6- 1696
CS:98
:0E06B000939A8A9A640E056EC7DFF5D7030091
2- 48
3- 14
4- 1712
5- 0
6- 1712
CS:-111
:020000040030CA
2- 48
3- 2
4- 0
5- 4
6- 0
CS:-54
:0E00000000C2180E0084810000C03FE03F40A7
2- 48
3- 14
4- 0
5- 0
6- 0
CS:-89
:00000001FF
2- 48
3- 0
4- 0
5- 1
6- 0
CS:-1
I not understand why this happened! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Mon Nov 23, 2015 1:40 am |
|
|
That is correct.......
However not with the code you show.
Look at the line before. Line type = 04. This says load the payload into the h_addr field (extended linear address). So 0x0030 gets put into h_addr. The code you show does not do this.
The next line it to be programmed at address 0x300000. Fuses probably.
Now, this raises a point.
Your bootloader _should not program the fuses_. If it does, you risk stopping it from running. Code that is to be loaded with the bootloader, _must_ run with the same fuses as the bootloader itself. Otherwise, once programmed, the bootloader will stop working.....
Ideally two things are done:
1) Write the bootloader to automatically reject writes to addresses outside the program memory.
2) Program code to be bootloaded, with "#FUSES NONE". This tells the compiler to not add fuses to the output file.
Preferably use _both_ approaches. This way if you (or another programmer), later 'forgets' to turn off the fuses, disaster is avoided, but also the extra space needed to send the fuses is also saved.
You need to handle the extended addressing, otherwise you can't program chips with >65K memory.
The CCS bootloader uses approach '1'. If you look, it only _writes_ to the memory if the decoded address < getenv("PROGRAM_MEMORY"). |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Mon Nov 23, 2015 5:10 am |
|
|
Ttelmah wrote: | That is correct.......
However not with the code you show.
Look at the line before. Line type = 04. This says load the payload into the h_addr field (extended linear address). So 0x0030 gets put into h_addr. The code you show does not do this.
The next line it to be programmed at address 0x300000. Fuses probably.
|
I do not quite understand what you're saying.
but I do not I put the rest of the code, because it is the same as the original file.
I do not understand how the same "buffer" can have two different results ...
I still do not understand!
Ttelmah wrote: |
Now, this raises a point.
Your bootloader _should not program the fuses_. If it does, you risk stopping it from running. Code that is to be loaded with the bootloader, _must_ run with the same fuses as the bootloader itself. Otherwise, once programmed, the bootloader will stop working.....
Ideally two things are done:
1) Write the bootloader to automatically reject writes to addresses outside the program memory.
2) Program code to be bootloaded, with "#FUSES NONE". This tells the compiler to not add fuses to the output file.
Preferably use _both_ approaches. This way if you (or another programmer), later 'forgets' to turn off the fuses, disaster is avoided, but also the extra space needed to send the fuses is also saved.
You need to handle the extended addressing, otherwise you can't program chips with >65K memory.
The CCS bootloader uses approach '1'. If you look, it only _writes_ to the memory if the decoded address < getenv("PROGRAM_MEMORY").
|
I did not understand anything he said here!
It was very confusing.
could be clearer?
I'm using the same fuses for the program and for the bootloader. I can not do that?
and the rest I do not understand anything! The standard bootloader does not do everything right? because you have to change something?
look at the code changes that I am making (loader.c):
Code: |
///////////////////////////////////////////////////////////////////////////
//// loader.c ////
//// ////
//// This driver will take an Intel 8-bit Hex file over RS232 channels ////
//// and modify the flash program memory with the new code. A proxy ////
//// function is required to sit between the real loading function ////
//// and the main code because the #org preprocessor command could ////
//// possibly change the order of functions within a defined block. ////
//// ////
//// After each good line, the loader sends an ACKLOD character. The ////
//// driver uses XON/XOFF flow control. Also, any buffer on the PC ////
//// UART must be turned off, or to its lowest setting, otherwise it ////
//// will miss data. ////
//// ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2013 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////
#ifndef LOADER_END
#define LOADER_END getenv("PROGRAM_MEMORY")-1
#if defined(__PCM__)
#define LOADER_SIZE 0x27F
#elif defined(__PCH__)
#if (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")) == 0
#define LOADER_SIZE 0x3FF
#else
#define LOADER_SIZE (getenv("PROGRAM_MEMORY") % (getenv("FLASH_ERASE_SIZE")) - 1)
#endif
#endif
#endif
#define LOADER_ADDR LOADER_END-LOADER_SIZE
#ifndef BOOTLOADER_AT_START
#ORG LOADER_ADDR+4, LOADER_END auto=0 default
#endif
#define BUFFER_LEN_LOD 64
int buffidx;
char buffer[BUFFER_LEN_LOD];
#define ACKLOD 0x06
#define XON 0x11
#define XOFF 0x13
unsigned int atoi_b16(char *s);
void real_load_program (void)
{
int1 do_ACKLOD, done=FALSE;
int8 checksum, line_type;
int16 l_addr,h_addr=0;
int32 addr;
#if getenv("FLASH_ERASE_SIZE") != getenv("FLASH_WRITE_SIZE")
int32 next_addr;
#endif
int8 dataidx, i, count;
int8 data[32];
char aux_eeprom;
int1 flag_primeiro;
int J;
while (!done) // Loop until the entire program is downloaded
{
buffidx = 0; // Read into the buffer until 0x0D ('\r') is received or the buffer is full
flag_primeiro=1;
for (J = 0; J < 64; J++) {
buffer[J] = NULL;
}
/*
do {
//buffer[buffidx] = getc();
aux_eeprom = read_ext_eeprom(contador);
if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
if(aux_eeprom == 'O'){
if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
}
buffer[buffidx] = aux_eeprom;
contador = contador + 1;
flag_primeiro=0;
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
*/
do {
buffer[buffidx] = getc();
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
putchar (XOFF); // Suspend sender
do_ACKLOD = TRUE;
// Only process data blocks that start with ':'
if (buffer[0] == ':')
{
printf("\r\n%s",buffer);
count = atoi_b16 (&buffer[1]); // Get the number of bytes from the buffer
printf("\r\n2- %d",buffer[1]);
printf("\r\n3- %d",count);
// Get the lower 16 bits of address
l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));
printf("\r\n4- %ld",l_addr);
line_type = atoi_b16 (&buffer[7]);
printf("\r\n5- %d",line_type);
addr = make32(h_addr,l_addr);
printf("\r\n6- %ld",addr);
#if defined(__PCM__) // PIC16 uses word addresses
addr /= 2;
#endif
checksum = 0; // Sum the bytes to find the check sum value
for (i=1; i<(buffidx-3); i+=2)
checksum += atoi_b16 (&buffer[i]);
checksum = 0xFF - checksum + 1;
printf("\r\nCS:%d",checksum);
if (checksum != atoi_b16 (&buffer[buffidx-3]))
do_ACKLOD = FALSE;
else
{
// 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(&buffer[9]), atoi_b16(&buffer[11]));
else if (line_type == 0)
{
if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < getenv("PROGRAM_MEMORY"))
{
// Loops through all of the data and stores it in data
// The last 2 bytes are the check sum, hence buffidx-3
for (i = 9,dataidx=0; i < buffidx-3; i += 2)
data[dataidx++]=atoi_b16(&buffer[i]);
#if getenv("FLASH_ERASE_SIZE") > getenv("FLASH_WRITE_SIZE")
if ((addr!=next_addr) && (addr > (next_addr + (getenv("FLASH_ERASE_SIZE") - (next_addr % getenv("FLASH_ERASE_SIZE"))))) && ((addr & (getenv("FLASH_ERASE_SIZE")-1)) != 0))
{
#if defined(__PCH__) && defined(BOOTLOADER_AT_START)
#if ((getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")) != 0)
if (addr > (getenv("PROGRAM_MEMORY") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE"))))
{
read_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
erase_program_eeprom(addr);
write_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
}
else
#endif
#endif
erase_program_eeprom(addr);
}
#if defined(__PCM__)
next_addr = addr + count/2;
#else
next_addr = addr + count;
#endif
#endif
#if defined(__PCH__) && defined(BOOTLOADER_AT_START)
#if ((getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")) != 0)
if (addr == (getenv("PROGRAM_MEMORY") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE"))))
{
read_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
write_program_memory(addr, data, count);
write_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
}
else
#endif
#endif
write_program_memory(addr, data, count);
}
}
}
}
if (do_ACKLOD)
putchar (ACKLOD);
putchar(XON);
}
putchar (ACKLOD);
putchar(XON);
reset_cpu();
}
unsigned int atoi_b16(char *s) { // Convert two hex characters to a int8
unsigned int result = 0;
int 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);
}
#ifndef BOOTLOADER_AT_START
#ORG default
#ORG LOADER_ADDR, LOADER_ADDR+3
#endif
void load_program(void)
{
real_load_program();
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Mon Nov 23, 2015 8:06 am |
|
|
This:
Code: |
else if (line_type == 4)
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
|
Is what was missing from your earlier code, that loads the h_addr value.
Hence the difference between the two addresses.
The existing bootloader does everything to be a bootloader, _but_ is not what you want to be using if you are loading the value into an EEPROM, from a cell phone.
The bootloader assumes you are talking directly to the device, and will be able to reprogram, if something goes wrong. If you are 'pre-building' the data into an EEPROM from packets sent by a cell phone, _you_ need to add extra checking to ensure that what is built is 'right' before the loader can be used. This is _essential_.
This means the cellphone code is going to have to verify _all_ the data. Either by interpreting the checksum and testing this matches the received data, or by you adding another checksum outside the data. This though implies that the loader code is going to have to interpret the data. As such it is pointless to have this duplicated in the bootloader.
You could simplify the bootloader massively by just having it work directly with already interpreted data. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Mon Nov 23, 2015 1:25 pm |
|
|
Ttelmah wrote: | This:
Code: |
else if (line_type == 4)
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
|
Is what was missing from your earlier code, that loads the h_addr value.
Hence the difference between the two addresses.
The existing bootloader does everything to be a bootloader, _but_ is not what you want to be using if you are loading the value into an EEPROM, from a cell phone.
The bootloader assumes you are talking directly to the device, and will be able to reprogram, if something goes wrong. If you are 'pre-building' the data into an EEPROM from packets sent by a cell phone, _you_ need to add extra checking to ensure that what is built is 'right' before the loader can be used. This is _essential_.
This means the cellphone code is going to have to verify _all_ the data. Either by interpreting the checksum and testing this matches the received data, or by you adding another checksum outside the data. This though implies that the loader code is going to have to interpret the data. As such it is pointless to have this duplicated in the bootloader.
You could simplify the bootloader massively by just having it work directly with already interpreted data. |
I'll still ride the safe transfer protocol for mobile data packet.
Now my difficulty is to read the EEPROM data and record them!
I assume that the EEPROM data is correct, because before recording them I already checked!
as I simplify the bootloader to work directly with the interpreted data?
I need help in this part!
.hex file of the data already have CRC?
how work?
:0406400037EF03F09D
:08064800EA6A050EE96EEF50AD
:100650000DE0060E016E006A002EFED7012EFBD7BC
:100660007B0E006E002EFED7EF2EF3D71200F86A35
:10067000D09EB8862A0EAF6E000EB06EA60EAC6E7F
:10068000900EAB6EC150C00B0F09C16E840ED56EBB
:10069000F29AF298F096F0989D9AF29CF29EF2BE31
:1006A000FDD794928B92939A8A8A640E056ECCDF62
:0E06B000939A8A9A640E056EC7DFF5D7030091
:020000040030CA
:0E00000000C2180E0084810000C03FE03F40A7
:00000001FF
;PIC18LF2685
;CRC=2444 CREATED="21-nov-15 13:04" |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Mon Nov 23, 2015 3:56 pm |
|
|
The supplied bootloader, 'dis-interprets' the incoming hex, to generate the bytes to feed to memory.
What you want to do is:
1) Have an EEPROM whose size matches or exceeds the ROM or your PIC.
2) Have a program running in your main code, which reads and dis-interprets the hex (bootloader shows how), and writes the values to the EEPROM.
3) Once the EEPROM is complete _check the CRC matches the one in the arriving hex.
4) Only if it does then set a flag in the EEPROM - remember if the EEPROM memory matches the PIC, there will be an unused block at the bottom of memory, where the bootloader resides in the PIC. You can use this to put a nice little table saying 'lowest location to program', 'highest location to program', and with a 'good' flag to say the data is valid.
5) If it doesn't, indicate the transfer has failed. Either tell the main system to send again, or whatever else you require.
6) On boot; the loader need only read the 'good' flag to know there is a new program there. You can either use a switch, or could completely get rid of this and just have the loader automatically trigger if the flag is set.
7) All the loader then has to do, is copy the data from the EEPROM to the program memory, from the 'lowest location', to 'highest location'. Once this is done, clear the 'good' flag.
Voila. The booloader code will actually be smaller than the standard bootloader (the extra space is the program in the main code which reads and verifies the data).
The approach you currently have, is like a person insisting on reading a document 'letter by letter', instead of the (amazing) way we scan word/section by section. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Wed Nov 25, 2015 8:53 am |
|
|
Ttelmah wrote: | The supplied bootloader, 'dis-interprets' the incoming hex, to generate the bytes to feed to memory.
What you want to do is:
1) Have an EEPROM whose size matches or exceeds the ROM or your PIC.
2) Have a program running in your main code, which reads and dis-interprets the hex (bootloader shows how), and writes the values to the EEPROM.
3) Once the EEPROM is complete _check the CRC matches the one in the arriving hex.
4) Only if it does then set a flag in the EEPROM - remember if the EEPROM memory matches the PIC, there will be an unused block at the bottom of memory, where the bootloader resides in the PIC. You can use this to put a nice little table saying 'lowest location to program', 'highest location to program', and with a 'good' flag to say the data is valid.
5) If it doesn't, indicate the transfer has failed. Either tell the main system to send again, or whatever else you require.
6) On boot; the loader need only read the 'good' flag to know there is a new program there. You can either use a switch, or could completely get rid of this and just have the loader automatically trigger if the flag is set.
7) All the loader then has to do, is copy the data from the EEPROM to the program memory, from the 'lowest location', to 'highest location'. Once this is done, clear the 'good' flag.
Voila. The booloader code will actually be smaller than the standard bootloader (the extra space is the program in the main code which reads and verifies the data).
The approach you currently have, is like a person insisting on reading a document 'letter by letter', instead of the (amazing) way we scan word/section by section. |
I understand what you want me to do!
I'm unable to do that!
I could understand that I can withdraw checksum lines of the .hex file and save memory on my EEPROM.
and take also checking the checksum in the bootloader.
the number 2 when you talk I will read the code "dis-interprets" I tried to understand the bootloader for how to do this, I understood how to get the checksum, removing the last 2 bytes.
in short, I will have to do this here?
Code: |
for (i = 9, dataidx = 0; i <buffidx-3; i + = 2)
date [dataidx ++] = atoi_b16 (& buffer [i]);
|
This code above is part of the bootloader showing the useful part of the package that will be engraved in memory, am I right?
I do not understand what you meant in number 4. the same thing at number 7.
the rest I get it and I will do as you are asking!
I do not have much experience with this, I have trouble understanding. and do something.
I tried to understand why this error happens, but not understood:
: 0E00000000C2180E0084810000C03FE03F40A7
2- 48
3- 14
4- 0
5- 0
6- 0
CS: -89
: 00000001FF
2- 48
3- 0
4- 0
5- 1
6- 0
CS: -1
if I can not resolve the error, I can make it work.
because I could not do as you asked, I have no knowledge to that and not found anyone explain to me in more detail.
Can you help me?
you talking, it seems easy, but do not know how to do this:
Voila. The bootloader code will be smaller than Actually the standard bootloader (the extra space is the program in the main code Which reads and Verifies the date).
The approach you currently have, is like a person insisting on reading the document 'letter by letter, "instead of the (amazing) way we scan word / section by section. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Wed Nov 25, 2015 10:36 am |
|
|
The fact that the value is 3145728 (or 0x00300000) before and 0 after, would tend to move me towards a casting or conversion error somewhere. After all, if you cast or convert 3145728 to a 16bit number, it becomes 0. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Wed Nov 25, 2015 11:19 am |
|
|
jeremiah wrote: | The fact that the value is 3145728 (or 0x00300000) before and 0 after, would tend to move me towards a casting or conversion error somewhere. After all, if you cast or convert 3145728 to a 16bit number, it becomes 0. |
except!
I do not understand why the recording through the pc is that!
Interestingly, the recording through the PC goes to the end and restart the PIC!
The recording through the EEPROM, not ends and does not restart the pic.
I do not understand!!
I need help! |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Wed Nov 25, 2015 1:28 pm |
|
|
So it could be a combination of things. I don't know exactly what the data looks like in the EEPROM. Based on your code, there are some "OK"s in it.
You do have some potential bugs that could cause your behavior:
1. Possible buffer overrun (doubtful the issue but still a bug):
Your buffer is 64 bytes long but certain parts of your code allow you access buffer[64] which is outside the range of the array:
Code: |
do {
buffer[buffidx] = getc();
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
|
Notice here that you allow the loop to go if buffidx is less than or equal to BUFFER_LEN_LOD. This is not good. It should be just less than so the highest element you access is buffer[63]. I doubt this is the cause to your issue due to the size of the lines, but it is a potential bug later on. You will be overwriting other variables in memory with this bug. It also applies to your EEPROM reading loop which has the same condition.
2. Inconsistent final buffidx values (likely the issue):
In your EEPROM reading loop you have the following code
Code: |
do {
//buffer[buffidx] = getc();
aux_eeprom = read_ext_eeprom(contador);
if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
if(aux_eeprom == 'O'){
if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
}
buffer[buffidx] = aux_eeprom;
contador = contador + 1;
flag_primeiro=0;
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
|
notice in particular:
Code: |
if(aux_eeprom == 'O'){
if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
}
|
here, if you get an "OK", it abruptly ends leaving the variable buffidx pointing to the 0x0D location. So if you line was ":020000040030CAOK", buffidx would be 15, pointing to the newly added '\r' just after the A
Your later check
Code: |
if (checksum != atoi_b16 (&buffer[buffidx-3]))
do_ACKLOD = FALSE;
else
{
// 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(&buffer[9]), atoi_b16(&buffer[11]));
|
compares the computed checksum to the two characters starting at buffidx - 3 (in the initial if statement). Since buffidx is 15, it will start at 15-3 or index 12. The character at index 12 in this example is '0', not 'C' as you would expect. This would cause the checksum validation to fail in most cases (some number combinations would still work, but not many). If that check fails you never do the part:
Code: |
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
|
which means, h_addr remains 0. Furthermore, you would never write the data to program memory, because you would never get into the else following the checksum validation. |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Wed Nov 25, 2015 3:10 pm |
|
|
jeremiah wrote: | So it could be a combination of things. I don't know exactly what the data looks like in the EEPROM. Based on your code, there are some "OK"s in it.
You do have some potential bugs that could cause your behavior:
1. Possible buffer overrun (doubtful the issue but still a bug):
Your buffer is 64 bytes long but certain parts of your code allow you access buffer[64] which is outside the range of the array:
Code: |
do {
buffer[buffidx] = getc();
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
|
Notice here that you allow the loop to go if buffidx is less than or equal to BUFFER_LEN_LOD. This is not good. It should be just less than so the highest element you access is buffer[63]. I doubt this is the cause to your issue due to the size of the lines, but it is a potential bug later on. You will be overwriting other variables in memory with this bug. It also applies to your EEPROM reading loop which has the same condition.
2. Inconsistent final buffidx values (likely the issue):
In your EEPROM reading loop you have the following code
Code: |
do {
//buffer[buffidx] = getc();
aux_eeprom = read_ext_eeprom(contador);
if(((aux_eeprom == ':') || (aux_eeprom == ';') ) && (flag_primeiro == 0)){buffer[buffidx] = 13;BREAK;}//0x0D
if(aux_eeprom == 'O'){
if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
}
buffer[buffidx] = aux_eeprom;
contador = contador + 1;
flag_primeiro=0;
} while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );
|
notice in particular:
Code: |
if(aux_eeprom == 'O'){
if(read_ext_eeprom(contador+1) == 'K'){buffer[buffidx] = 13;BREAK;}//0x0D
}
|
here, if you get an "OK", it abruptly ends leaving the variable buffidx pointing to the 0x0D location. So if you line was ":020000040030CAOK", buffidx would be 15, pointing to the newly added '\r' just after the A
Your later check
Code: |
if (checksum != atoi_b16 (&buffer[buffidx-3]))
do_ACKLOD = FALSE;
else
{
// 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(&buffer[9]), atoi_b16(&buffer[11]));
|
compares the computed checksum to the two characters starting at buffidx - 3 (in the initial if statement). Since buffidx is 15, it will start at 15-3 or index 12. The character at index 12 in this example is '0', not 'C' as you would expect. This would cause the checksum validation to fail in most cases (some number combinations would still work, but not many). If that check fails you never do the part:
Code: |
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
|
which means, h_addr remains 0. Furthermore, you would never write the data to program memory, because you would never get into the else following the checksum validation. |
Hello, thanks for your help!
I'm modifying the existing code already developed by CCS !!
Look LOADER.C file that comes with the ccs!
I'm modifying this file for him to read the data starting from the external EEPROM!
I already managed to get it completed the buffer with data from the EEPROM, but it did not work! I explained it above.
As for your questions,
much of what you said, not I who did. I was ready and it works. It is the standard ccs!
you said you would be my buffer (: 020000040030CAOK)
but that never happens! OK simply serves to detect the end of the program! It is a marker. He does not come in the package!
Note that I stop before putting it in the package!
His other doubts about the checksum, buffer size, etc ... Everything was done by the CCS team. I tested and work.
Look in my previous posts.
I posted the LOG of a debug what I did to see the value of the variables comparing a recording using PC with a recording reading the EEPROM program.
Buffer works well, I never burst! I do not lose data!
The checksum, always works!
The problem is what I told you before.
When I record a given from the PC by serial, everything is good and pic restarts to run the new program!
But when I record the program read by the EEPROM, everything happens in a similar way, except what I put in red in the debug I posted. Then the pic not complete recording and does not restart. But I do not understand why this happens.
Look 2 debugs I did and posted above! one with serial debug via recording and one with recording via EEPROM.
You will understand better, you will see the buffer and the checksum working.
The Ttelmah tried talking to help me step by step what to do, but I did not understand some of what he said. = ( |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Mon Nov 30, 2015 5:31 pm |
|
|
Hello Friend,
can you help me?
I read your text.
I had some doubts, posted above. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 30, 2015 6:40 pm |
|
|
Your complaint is that field 6 (the address) is displayed as 0. Jeremiah
told you that the problem is probably due to 'buffidx' being wrong.
That's what I found. I compiled your posted code, and the problem is
that buffidx is wrong. Because buffidx is wrong, the following code
doesn't read the checksum bytes from the HEX file line.
Code: | if (checksum != atoi_b16 (&buffer[buffidx-3]))
do_ACKLOD = FALSE; |
As a result, the if() statement is False, and the "Type 4" code is not
executed, and the extended linear address is not extracted from the
hex file line, and field 6 is wrong.
The calculated checksum is correct. You are always loudly telling us that.
But the problem is that the "CA" checksum bytes in the following line
are not being read correctly, because buffidx is the wrong value.
You need to fix this. Do not ask us to fix it. It's your code.
Put in some debugging lines (printf), and look at the value of buffidx
just before it reads the checksum ("CA"), and make sure that buffidx
is correct. If not, then look at the code and fix it. Do not re-post
your request every couple of days, hoping that we will solve it for you.
Here are some tips:
buffidx should be pointing at the last character in the string.
In the tests that I ran, I used the following string:
Code: | :020000040030CA 0x0d 0x0a |
The hex file line ends with 0d, 0a, which is a carriage return and linefeed.
buffidx should be pointing at the 0x0a. Then when it gets to this line,
Code: | if (checksum != atoi_b16 (&buffer[buffidx-3]))
do_ACKLOD = FALSE; |
buffidx will have 3 subtracted from it, and it will then point to "CA".
"CA" is the checksum for the hex line. atoi_b16() will convert it from
ascii to an integer. It will be compared to 'checksum', and will be equal.
The if() statement will be True, and the next code here will be executed:
Quote: | // 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(&buffer[9]), atoi_b16(&buffer[11]));
printf("Processed line type 4 \n\r"); // *** ADDED ***
}
|
Then h_addr will be set to 0x3000, which is the desired result.
Here are the results of your tests when buffidx is correct:
Code: |
:020000040030CA
buffidx = 16
2- 0
3- byte count = 02
4- l_addr = 0000
5- line_type = 04
6- addr = 00000000
CS in hex: ca
Processed line type 4
:0E00000000C2180E0084810000C03FE03F40A7
buffidx = 40
2- 0
3- byte count = 0e
4- l_addr = 0000
5- line_type = 00
6- addr = 00300000
CS in hex: a7
Done |
|
|
|
|
|
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
|