|
|
View previous topic :: View next topic |
Author |
Message |
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
write_program_memory function and bootloader questions |
Posted: Sun Sep 09, 2012 8:09 pm |
|
|
Hi, guys.
Because last week, with some people help, I know currently ccs doesn't support auxiliary flash memory quite well.
So this week, I just put my bootloader code in main flash memory, and did another main program(LED blinking) demo code. In the demo code I used #org 0x10000 which means I want to compiler generate the code which can only put them after address 0x10000, and once I downloaded my bootloader code which will occupy 0x200 to 0xFFFF, I send the demo code by RS232.
I am using dsPIC33EP256MU814 with CCS v4.133
my question is, once I got lines of hex code such as
Code: |
:080000000000040001000000F3
:020000040002F8
:10000000C1E8A8000E2EEF001E2EEF002E2EEF00EE
|
What I need to do is analyze the code, such as the first byte is 08, that means 8 data byte, and followed with two bytes address, then I just combine those two bytes as one word and put it into write_program_memory function, is that right? I can not understand the address bytes meaning, for my demo code address should be from 0x10000, but you can see it is not, first several line is 0x0000, and then 0x0040? Is that two bytes means offset or something else? and how to use write_program_memory ? Thanks a lot. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Sun Sep 09, 2012 8:27 pm |
|
|
Type
Intel hex file format
into Google and do the search and a wikipedia page should pop up that completely describes how the file is formatted.
The big things to watch for are:
1. I think the file gives you addresses formatted at the byte level and PIC24/dsPIC33 are at word level, so you need to make the translation of the address correctly. It's easy to figure out by doing a #org on a line of code, then look at it in the hex file and see the address the hex file produces. I want to say, you need to divide by 2, but I haven't looked in ages.
2. There are a few hex file format lines that change the upper 16 bits part of the address and don't actually have code.
3. Don't assume that the hex file will always give you code in address order. I have had a couple of files where addresses are out of order.
EDIT:
For example, take the excerpt from your hex file:
Code: |
:020000040002F8
:10000000C1E8A8000E2EEF001E2EEF002E2EEF00EE
|
I think the upper line sets the upper address word to 2, and the second line then places all that code at low address word 0 or combined: 0x20000. If I am right and it divides by two due to byte vs word addresses, then that would be at 0x10000 as you expect. Again, I am pretty sure the wikipedia page on this goes into good detail and provides links to some external sites too. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Sun Sep 09, 2012 8:52 pm |
|
|
Thanks jeremiah, actually I opened wiki page and check my hex file to see if I can understand. I didn't notice data type 04 too much, I just see type 00, and thought the two byte address is the absolute address that will put in, that's why I got confused. After you explain, I think I can understand, and I will interpret the hex file again and check if my code can also interpret it right when it read that info. Thanks. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Sun Sep 09, 2012 9:51 pm |
|
|
Do we have any software which can read out the hex code in micro and display it with alignment of address?
I used the MPLAB bootloader code, it can fit the data type 04 automatically and looks fine. However, after I program in the hex file and read it out, I can not get the same result (only once I got).
Code: |
void WriteHexRecord2Flash(/*unsigned int8 * HexRecord, */unsigned int8 totalHexRecLen)
{
static T_HEX_RECORD HexRecordSt;
unsigned int8 Checksum = 0;
unsigned int8 i;
unsigned int32 WrData;
unsigned int32 ProgAddress;
unsigned int8 Result;
unsigned int32 nextRecStartPt = 0;
while(totalHexRecLen>=5) // A hex record must be atleast 5 bytes. (1 Data Len byte + 1 rec type byte+ 2 address bytes + 1 crc)
{
// HexRecord = &HexRecord[nextRecStartPt];
HexRecordSt.RecDataLen = uartRecvInfo[1];//HexRecord[0 + 1];
HexRecordSt.RecType = uartRecvInfo[4];//HexRecord[3 + 1];
HexRecordSt.Hex_Data = &uartRecvInfo[5];//&HexRecord[4 + 1];
//Determine next record starting point.
nextRecStartPt = HexRecordSt.RecDataLen + 5;
// Decrement total hex record length by length of current record.
totalHexRecLen = totalHexRecLen - nextRecStartPt;
// Hex Record checksum check.
Checksum = 0;
// for(i = 1/*0*/; i < HexRecordSt.RecDataLen + 5; i++)
// {
// Checksum += uartRecvInfo[i];//HexRecord[i];
// }
//
// if(Checksum != 0)
// {
// //Error. Hex record Checksum mismatch.
// }
// else
{
// Hex record checksum OK.
switch(HexRecordSt.RecType)
{
case DATA_RECORD: //Record Type 00, data record.
HexRecordSt.Address.byte_dw.MB = 0;
HexRecordSt.Address.byte_dw.UB = 0;
HexRecordSt.Address.byte_dw.HB = uartRecvInfo[2];//HexRecord[1];
HexRecordSt.Address.byte_dw.LB = uartRecvInfo[3];//HexRecord[2];
// Derive the address.
HexRecordSt.Address.Val = HexRecordSt.Address.Val + HexRecordSt.ExtLinAddress.Val + HexRecordSt.ExtSegAddress.Val;
while(HexRecordSt.RecDataLen) // Loop till all bytes are done.
{
// Convert the Physical address to Virtual address.
ProgAddress = (HexRecordSt.Address.Val/2);
// ProgAddress = (HexRecordSt.Address.Val);
// Make sure we are not writing boot area and device configuration bits.
if(((ProgAddress < AUX_FLASH_BASE_ADRS) || (ProgAddress > AUX_FLASH_END_ADRS))
&& ((ProgAddress < DEV_CONFIG_REG_BASE_ADDRESS) || (ProgAddress > DEV_CONFIG_REG_END_ADDRESS)))
{
if(HexRecordSt.RecDataLen < 4)
{
// Sometimes record data length will not be in multiples of 4. Appending 0xFF will make sure that..
// we don't write junk data in such cases.
WrData = 0xFFFFFFFF;
memcpy(&WrData, HexRecordSt.Hex_Data, HexRecordSt.RecDataLen);
}
else
{
memcpy(&WrData, HexRecordSt.Hex_Data, 4);
}
// Write the data into flash.
// Result = NVMemWriteWord(ProgAddress, WrData);
write_program_memory(ProgAddress,WrData,4);
// Assert on error. This must be caught during debug phase.
// ASSERT(Result==0);
}
// Increment the address.
HexRecordSt.Address.Val += 4;
// Increment the data pointer.
HexRecordSt.Hex_Data += 4;
// Decrement data len.
if(HexRecordSt.RecDataLen > 3)
{
HexRecordSt.RecDataLen -= 4;
}
else
{
HexRecordSt.RecDataLen = 0;
}
}
break;
case EXT_SEG_ADRS_RECORD: // Record Type 02, defines 4th to 19th bits of the data address.
HexRecordSt.ExtSegAddress.byte_dw.MB = 0;
HexRecordSt.ExtSegAddress.byte_dw.UB = HexRecordSt.Hex_Data[0];
HexRecordSt.ExtSegAddress.byte_dw.HB = HexRecordSt.Hex_Data[1];
HexRecordSt.ExtSegAddress.byte_dw.LB = 0;
// Reset linear address.
HexRecordSt.ExtLinAddress.Val = 0;
break;
case EXT_LIN_ADRS_RECORD: // Record Type 04, defines 16th to 31st bits of the data address.
HexRecordSt.ExtLinAddress.byte_dw.MB = HexRecordSt.Hex_Data[0];
HexRecordSt.ExtLinAddress.byte_dw.UB = HexRecordSt.Hex_Data[1];
HexRecordSt.ExtLinAddress.byte_dw.HB = 0;
HexRecordSt.ExtLinAddress.byte_dw.LB = 0;
// Reset segment address.
HexRecordSt.ExtSegAddress.Val = 0;
break;
case END_OF_FILE_RECORD: //Record Type 01, defines the end of file record.
default:
HexRecordSt.ExtSegAddress.Val = 0;
HexRecordSt.ExtLinAddress.Val = 0;
break;
}
}
}//while(1)
}
|
The code is above, actually it is almost the same as MPLAB example, I didn't use their format on UART message level. But this level is the same, just using CCS built in function "write_program_memory". |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Sun Sep 09, 2012 10:02 pm |
|
|
If you mean just read the hex file aligned, then the CCS IDE does that. If you mean read the data off of the micro itself after being programmed, then CCSLoad does, but it is for the programmers from CCS. If you are using a different programmer, you might see if they have an option to read code from a PIC. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Sun Sep 09, 2012 10:49 pm |
|
|
jeremiah wrote: | If you mean just read the hex file aligned, then the CCS IDE does that. If you mean read the data off of the micro itself after being programmed, then CCSLoad does, but it is for the programmers from CCS. If you are using a different programmer, you might see if they have an option to read code from a PIC. |
Thanks, Jeremiah.
I just tried a simply code below
Code: |
s = "1234";
iniBootloader();
while(!F_flashMemProgDone);
write_program_memory(0x10000,s,4);
Clear_Picture();
homeLCD();
sprintf(s, "Flash Memory Program Done Successfully");
printCusString(s);
|
Thanks, mate.
I just want to try if "write_program_memory" can work properly. the F_flashMemProgDone will change to TRUE when RS232 gets a ";", I tried the code, after "Flash Memory Program Done Successfully" showed on LCD, I read out the micro, and on the relative address, the data is 00. Any idea? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Mon Sep 10, 2012 6:30 am |
|
|
A call to read_program_memory() and then print it out could help show if the data got written.
EDIT: also, your use of the "s" variable looks suspect, though I cannot see other code relating to it. It looks like it is only big enough to hold 5 values, but you do an sprintf() with a much longer string into it. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Mon Sep 10, 2012 4:02 pm |
|
|
jeremiah wrote: | A call to read_program_memory() and then print it out could help show if the data got written.
EDIT: also, your use of the "s" variable looks suspect, though I cannot see other code relating to it. It looks like it is only big enough to hold 5 values, but you do an sprintf() with a much longer string into it.
|
Thanks Jeremiah, I tried the way you suggest, by popping out the data in the memory via LCD or RS232, both of them are failed, I can not get correctly result. (if the string just contains four bytes, then it looks ok, but if more, looks not good. ) I even tried to use MPLAB example which is using its built_in function "tblwtl" (I write with asm for those operation, not sure if they are correct), and it doesn't work...feel really bad...
The code below is using ccs built in function ,write it and read back, I just tried write one byte, it failed. The content displayed on screen via RS232 is "the result" even the word "is" is not showed!
Code: |
unsigned int32 WrData;
s= "abcd";
memcpy(&WrData, s, 4);
// while(!F_flashMemProgDone);
write_program_memory(0x10000,WrData,4);
#asm
NOP;
NOP;
#endasm
read_program_memory(0x10000,s1,4);
#asm
NOP;
NOP;
#endasm
for(i=0; i < 26;i++)
{
fprintf(GSM, "The result is %c", s1[i]);
}
|
The result is FF |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Mon Sep 10, 2012 4:47 pm |
|
|
Code: |
unsigned int32 WrData,RdData;
s="abcdefg";
s1 = "zyxwvu";
//memcpy(&WrData, s, 4);
// while(!F_flashMemProgDone);
write_program_memory(0x00010000,s,7);
#asm
NOP;
NOP;
#endasm
read_program_memory(0x00010000,s1,7);
#asm
NOP;
NOP;
#endasm
for(i=0; i < 7;i++)
{
fprintf(GSM, "The result IS %u\n", s1[i]);
}
|
The result printed out are all 65535(0xFF), I think that can prove that write_program_memory built in function doesn't work, am I right? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Mon Sep 10, 2012 4:55 pm |
|
|
you still have string size issues. You are writing / reading 7 characters but not adding a null terminator to what you read back. Though I would expect plain garbage instead of all FFs
Try putting:
Code: |
erase_program_memory(0x00010000);
|
before your write_program_memory() call. Maybe it isn't calling the erase for some reason.
I know write_program_memory() works fine on PIC24 and at least some of the dsPIC33Fs that I have at work. I just tested it today. For your particular pic I am unsure. I don't have one to test against with my normal test program.
You can always contact CCS support and give them an example file that isn't working and see if they can confirm a bug or not. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 10, 2012 4:59 pm |
|
|
You never answered Jeremiah's question about 's' and 's1'.
I don't see that you have legal code in your program.
Do it like this. Then it's legal:
Code: |
void main(void)
{
int8 s[8] = "abcdefg";
int8 s1[8] = "zyxwvu";
while(1);
} |
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Mon Sep 10, 2012 5:03 pm |
|
|
Also, you aren't writing/reading in multiples of 4, and you aren't making every 4th byte 0x00. So the write_program_memory() might not be executing at all.
EDIT:
Try this test program. Don't use a bootloader, just load this directly to the PIC. I tried using the settings you provided from your previous thread, but change the fuses, pin_select, use delay(), and use rs232() to fit your current configuration.
Code: |
#case
#include <33EP256MU814.h>
#fuses HS,PR,NOWDT,ICSP2
#use delay(clock=20000000) // Actual crystal is 20M
#pin_select U1TX = PIN_D0
#pin_select U1RX = PIN_D1
#use RS232(UART1, STREAM=GSM, BAUD=9600, BITS=8, STOP=1, PARITY=N, ERRORS)
void main(){
unsigned int8 data_to_write[] = {0x01,0x02,0x03,0x00};
unsigned int8 data_read[sizeof(data_to_write)];
delay_ms(1000);
fprintf(GSM,"\r\nProgram Start\r\n");
//erase_program_memory(0x00010000); //shouldn't need this line
write_program_memory(0x00010000,data_to_write,4);
delay_ms(1000);
read_program_memory(0x00010000,data_read,4);
fprintf(GSM,"Write: %x %x %x %x\r\n",
data_to_write[0],
data_to_write[1],
data_to_write[2],
data_to_write[3],
);
fprintf(GSM,"Read: %x %x %x %x\r\n",
data_read[0],
data_read[1],
data_read[2],
data_read[3],
);
while(TRUE);
}
|
|
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Mon Sep 10, 2012 5:34 pm |
|
|
PCM programmer wrote: | You never answered Jeremiah's question about 's' and 's1'.
I don't see that you have legal code in your program.
Do it like this. Then it's legal:
Code: |
void main(void)
{
int8 s[8] = "abcdefg";
int8 s1[8] = "zyxwvu";
while(1);
} |
|
s and s1 are defined like
char s[50], s1[100]; |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Mon Sep 10, 2012 5:40 pm |
|
|
While
will compile (at least it does in 4.135), it is bad code and will probably corrupt memory. You are essentially telling it to reassign your memory array pointer to the location of the constant string "abcdefg" and to no longer point to your buffer of 50 characters. I don't believe it is legal C to reassign an array name like a pointer to a new string (as PCM Programmer was pointing out), so that may be part of the issue.
Were you able to try the code I posted? |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Mon Sep 10, 2012 5:41 pm |
|
|
jeremiah wrote: | Also, you aren't writing/reading in multiples of 4, and you aren't making every 4th byte 0x00. So the write_program_memory() might not be executing at all.
EDIT:
Try this test program. Don't use a bootloader, just load this directly to the PIC. I tried using the settings you provided from your previous thread, but change the fuses, pin_select, use delay(), and use rs232() to fit your current configuration.
Code: |
#case
#include <33EP256MU814.h>
#fuses HS,PR,NOWDT,ICSP2
#use delay(clock=20000000) // Actual crystal is 20M
#pin_select U1TX = PIN_D0
#pin_select U1RX = PIN_D1
#use RS232(UART1, STREAM=GSM, BAUD=9600, BITS=8, STOP=1, PARITY=N, ERRORS)
}
|
|
Thanks for your great help, jeremiah. I put your test code in the main function, and comment out my code. The result is same:
Program Start
Write: 1 2 3 0
Read: ff ff ff 0
I know that the most significant byte should be 00, but I just want to test this built_in function, if I write in {0x55,0x55,0xAA,0xAA}, then the first three bytes should be ok, the fourth will be 0x00 or 0xFF, however, my code or you code gives the same result that even the first three bytes are not written correctly~
By the way, is there any written protection in software config or hardware config?(except NVMKEY sequence).
I just add erase program before the write in your test code, same result
And because auxiliary flash memory can not be compiled by ccs, so my "bootloader" code actually is the normal code, put into the main flash memory. Just my demo main program(blink LED) code will be compiled from 0x10000 address. So my "bootloader" code actually is normal
Last edited by naughty_mark on Mon Sep 10, 2012 5:55 pm; edited 1 time in total |
|
|
|
|
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
|