Dino Alves
Dino Alves

Reputation: 113

--fill command on PIC32MX boot flash memory

I have been trying for the last few weeks to find out why this isn't working. I have tried reading all the documentation I could find on my PIC32 MCU (PIC32MX795F512L) and the XC32 compiler I am using (v1.34) but with no success as of yet.

I need a special constant value written to the physical boot flash address 0x1FC02FEC (Virtual address: 0x9FC02FEC). This constant is 0x3BDFED92.

I have managed to successfully do this on my main program (If I program my pic32 directly using Real ICE) by means of the following command line (Which I put in xc32-ld under "Additional options" under the Project Properties):

--fill=0x3bdfed92@0x9FC02FEC

I am then able to check (Inside my main program) if this address indeed does have the correct value stored inside it, and this works too. I use the following code for that:

if(*(int *)(0x9fc02fec) == 0x3bdfed92)

My problem is the following. I do not want my main program hex file to write the constant into that location. I want my bootloader hex file to do this and my main program must just be able to read that location and see if that constant is there. If I use the --fill command inside the xc32-ld of my bootloader program, it successfully writes the constant just like the main program did (I have tested this by running my bootloader program with the same --fill command in debug mode and checking the 0x1FC02FEC address for the constant). Problem is, when my bootloader reads in a new main program via the MicroSD, and then jumps to the new main program, everything doesn't work. Seems like, before it jumps to the new main program, something bad happens and everything crashes. Almost like writing a value to the 1FC02FEC location is a problem when the program jumps from boot loader to main program.

Is there a reason for this? I hope my explanation is ok, if not then please let me know and I will try reword it in a more understandable way.

I am using the example code provided by Microchip to do the bootloader using the MicroSD card. The following is the code:

int main(void)
{
    volatile UINT i;
    volatile BYTE led = 0;

    // Setup configuration
    (void)SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

    InitLED();
    TRISBbits.TRISB14 = 0;
    LATBbits.LATB14 = 0;

    ClrWdt();

    // Create a startup delay to resolve trigger switch bouncing issues
    unsigned char x;
    WORD ms = 500;
    DWORD dwCount = 25;

    while(ms--)
    {
        ClrWdt();
        x=4;
        while(x--)
        {
            volatile DWORD _dcnt;

            _dcnt = dwCount*((DWORD)(0.00001/(1.0/GetInstructionClock())/10));
            while(_dcnt--)
            {
                    #if defined(__C32__)
                            Nop();
                            Nop();
                            Nop();
                    #endif
            }
        }
    }


    if(!CheckTrigger() && ValidAppPresent())
    {
        // This means the switch is not pressed. Jump
        // directly to the application

        JumpToApp();        
    }
    else if(CheckTrigger() && ValidAppPresent()){

        if(MDD_MediaDetect()){
            if(FSInit()){
                myFile = FSfopen("image.hex","r");

                if(myFile == NULL){
                    JumpToApp();
                }
            }
            else{
                JumpToApp();
            }
        }
        else{
            JumpToApp();
        }

    }

    //Initialize the media
    while (!MDD_MediaDetect())
    {
        // Waiting for media to be inserted.
        BlinkLED();
    }

    // Initialize the File System
    if(!FSInit())
    {
         //Indicate error and stay in while loop.
         Error();
         while(1);
    }


    myFile = FSfopen("image.hex","r");

    if(myFile == NULL)// Make sure the file is present.
    {
        //Indicate error and stay in while loop.
         Error();
         while(1);
    }     

    // Erase Flash (Block Erase the program Flash)
    EraseFlash();
    // Initialize the state-machine to read the records.
    record.status = REC_NOT_FOUND;

     while(1)
     {
         ClrWdt();

         // For a faster read, read 512 bytes at a time and buffer it.
         readBytes = FSfread((void *)&asciiBuffer[pointer],1,512,myFile);

         if(readBytes == 0)
         {
             // Nothing to read. Come out of this loop
             // break;
             FSfclose(myFile);
             // Something fishy. The hex file has ended abruptly, looks like there was no "end of hex record".
             //Indicate error and stay in while loop.
             Error();
             while(1);             
         }

         for(i = 0; i < (readBytes + pointer); i ++)
         {

          // This state machine seperates-out the valid hex records from the read 512 bytes.
             switch(record.status)
             {
                 case REC_FLASHED:
                 case REC_NOT_FOUND:
                     if(asciiBuffer[i] == ':')
                     {
                      // We have a record found in the 512 bytes of data in the buffer.
                         record.start = &asciiBuffer[i];
                         record.len = 0;
                         record.status = REC_FOUND_BUT_NOT_FLASHED;
                     }
                     break;
                 case REC_FOUND_BUT_NOT_FLASHED:
                     if((asciiBuffer[i] == 0x0A) || (asciiBuffer[i] == 0xFF))
                     {
                      // We have got a complete record. (0x0A is new line feed and 0xFF is End of file)
                         // Start the hex conversion from element
                         // 1. This will discard the ':' which is
                         // the start of the hex record.
                         ConvertAsciiToHex(&record.start[1],hexRec);
                         WriteHexRecord2Flash(hexRec);
                         record.status = REC_FLASHED;
                     }
                     break;
             }
             // Move to next byte in the buffer.
             record.len ++;
         }

         if(record.status == REC_FOUND_BUT_NOT_FLASHED)
         {
          // We still have a half read record in the buffer. The next half part of the record is read 
          // when we read 512 bytes of data from the next file read. 
             memcpy(asciiBuffer, record.start, record.len);
             pointer = record.len;
             record.status = REC_NOT_FOUND;
         }
         else
         {
             pointer = 0;
         }
         // Blink LED at Faster rate to indicate programming is in progress.
         led += 3;
         mLED = ((led & 0x80) == 0);

     }//while(1)


    return 0;
}

Upvotes: 0

Views: 1179

Answers (2)

LPs
LPs

Reputation: 16243

If I remember well (very long time ago I used PIC32) you can add into your linker script:

MEMORY
{
   //... other stuff
   signature (RX) : ORIGIN = 0x9FC02FEC, length 0x4
} 

then

SECTIONS
{
   .signature_section:
   {
      BYTE(0x3b);
      BYTE(0xdf);
      BYTE(0xed);
      BYTE(0x92);
   }>signature
}

Googling around I also found out, that you could do that in your source code, I hope...

const int __attribute__((space(prog), address(0x9FC02FEC))) signature = 0x3bdfed92; 

Upvotes: 1

blsmit5728
blsmit5728

Reputation: 444

In my program I use an attribute to place a certain value at a certain location in memory space. My bootloader and App can read this location. This may be a simpler way for you to do this. This is using xc16 and a smaller part but I've done it on a PIC32 as well.

#define CHECK_SUM 0x45FB
#define CH_HIGH ((CHECK_SUM & 0xFF00) >> 8)
#define CH_LOW  ((CHECK_SUM & 0x00FF) >> 0)
const char __attribute__((space(prog), address(APP_CS_LOC))) CHKSUM[2] = {CH_LOW,CH_HIGH};

Just a note, when you read it, it will be in the right format: HIGH->LOW

Upvotes: 0

Related Questions