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 CCS Technical Support

write_program_memory function and bootloader questions
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

write_program_memory function and bootloader questions
PostPosted: Sun Sep 09, 2012 8:09 pm     Reply with quote

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: 1343

View user's profile Send private message

PostPosted: Sun Sep 09, 2012 8:27 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Sep 09, 2012 8:52 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Sep 09, 2012 9:51 pm     Reply with quote

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: 1343

View user's profile Send private message

PostPosted: Sun Sep 09, 2012 10:02 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Sep 09, 2012 10:49 pm     Reply with quote

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: 1343

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 6:30 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 4:02 pm     Reply with quote

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... Crying or Very sad
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 Rolling Eyes
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 4:47 pm     Reply with quote

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: 1343

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 4:55 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 4:59 pm     Reply with quote

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: 1343

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 5:03 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 5:34 pm     Reply with quote

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: 1343

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 5:40 pm     Reply with quote

While
Code:

s="abcdefg";


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

View user's profile Send private message

PostPosted: Mon Sep 10, 2012 5:41 pm     Reply with quote

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

 
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