0

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;
}
VC.One
  • 14,790
  • 4
  • 25
  • 57
Dino Alves
  • 113
  • 10
  • What is the purpose of explaining all thing about special constant value? It seems a problem related to the "loading of a new main program", whatever that means.. – LPs Mar 14 '16 at 13:32
  • Try to post the bootloader jump code, and the bootloader copy program function. At least, try to explain how your bootloader perform the copy. – LPs Mar 14 '16 at 13:34
  • The bootloader works as expected. It is capable of loading a new main program into the Program Flash Memory, a feature which I use to give the user the ability to upgrade firmware on the hardware we designed. The constant (0x3BDFED92) is a unique key that we want to exist on not all, but most of the hardware that gets deployed. Whenever the main program executes inside the PFM, we want the code to check the address 1FC02FEC (Virtual: 9FC02FEC) to see if that unique key/constant is stored in that location. If so, the code then behaves in a certain way and if not then it behaves differently. – Dino Alves Mar 14 '16 at 13:36
  • Ok, but how could we help you without your code and with a vague idea of what is going on? Are you sure that the bootloader jumps to the new firmware? Or is the bootloader that got stuck? BTW how about define a specific section at a specific address in linker script and store your signature in that section? – LPs Mar 14 '16 at 13:44
  • I am 110% sure the bootloader works (Without the --fill command). It is only now when I try to add this new feature, that the code seems to crash. But I cannot tell if it is the bootloader and it's --fill command that is the problem. Or if it is the main program and the if statement I am using to check that memory location. How would I do that in the linker script? I am using the default one provided by Microchip called: app_32MX795F512L.ld inside the main program project and I use btl_32MX795F512L.ld inside the bootloader program project. – Dino Alves Mar 14 '16 at 13:48
  • I thought that by adding the --fill command in the xc32-ld section under the project settings for the bootloader was doing that already? Or am I wrong? – Dino Alves Mar 14 '16 at 13:50
  • Could you post the fill command you use? – LPs Mar 14 '16 at 13:50
  • --fill=0x3bdfed92@0x9FC02FEC as mentioned in my original question :) – Dino Alves Mar 14 '16 at 13:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/106245/discussion-between-dino-alves-and-lps). – Dino Alves Mar 14 '16 at 13:57
  • Using floating point for a simple delay in a bare-metal embedded system looks like a bad idea. Even more for a bootloader. – too honest for this site Mar 14 '16 at 14:16
  • Hi Olaf, thought the same thing when I saw it. But this is the microchip code directly. So I trust they know what they are doing. – Dino Alves Mar 15 '16 at 08:02

2 Answers2

1

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; 
LPs
  • 16,045
  • 8
  • 30
  • 61
  • And this would go into the linker of the bootloader am I correct? – Dino Alves Mar 14 '16 at 14:01
  • Yes, you are. This will define a section where your signature is stored. The in your code you can siply define a volatile pointer to that address. – LPs Mar 14 '16 at 14:03
  • Let me try this quickly and will get back to you ASAP. Thank you for your assistance. – Dino Alves Mar 14 '16 at 14:03
  • I edited with a different solution that does not involves linker script, I hope. – LPs Mar 14 '16 at 14:12
  • I have tried both your suggestions here. The first suggestion didn't compile as it says there is a syntax error in the linker script file. And the second suggestion I tried too, but after reading back the memory the 0x9fc02fec location shows 0xffffffff instead of the expected 0x3bdfed92. I wonder why this is happening? – Dino Alves Mar 14 '16 at 14:23
  • Sorry I do not follow, what do you mean by that? – Dino Alves Mar 14 '16 at 14:26
  • @DinoAlves Try using `0x1FC02FEC` – LPs Mar 14 '16 at 14:28
  • Oh i tried that but the compiler fails and tells me I must use the virtual address and not the physical address. So I must use 9fc02fec. But this const int __attribute__((space(prog), address(0x9fc02fec))) signature = 0x3bdfed92; doesn't seem to work – Dino Alves Mar 14 '16 at 14:29
  • @DinoAlves Last think before give up: add `static` keyword to the definition. – LPs Mar 14 '16 at 14:32
  • Unfortunately still not :( – Dino Alves Mar 14 '16 at 14:34
  • @DinoAlves Are you able to produce a .map file? Is signature var listed? – LPs Mar 14 '16 at 14:52
  • Just had a look now and the signature var is not listed inside the .map file I generate for this code. What could I try next? – Dino Alves Mar 15 '16 at 08:09
  • @DinoAlves I really don't know. Googling around many people had this problem due to compiler bugs, it seems. If your compiler does not give you back warnings or errors, why that var is not present in your map file? – LPs Mar 15 '16 at 08:14
  • That is a very good point. What I did now is I added signature under memory in my linker script. Then I created a SECTIONS for the signature. I then defined const int __attribute__((space(prog), section(".signature"))) signature = 0x3bdfed92; inside the bootloader and now the 1FC02FEC address holds the correct value of 3BDFED92 but when I try read that section in my main program, I think I am not reading it correctly. – Dino Alves Mar 15 '16 at 08:57
  • In my main program I create an attribute as follows: const int __attribute__((space(prog), section(".signature"))) signature; And then I compare it like so if(signature == 0x3bdfed92) Am I maybe doing the comparison wrong? Please note, I added the memory and section to the linker script of the main program as well – Dino Alves Mar 15 '16 at 08:59
  • @DinoAlves Did you try to simply use a pointer to that specific address? – LPs Mar 15 '16 at 09:20
  • Hi @LPs yes I did. Still doesn work. I have posted something on the Microchip Forum about this with more information on what I have done and hopefully someone will get back to me: http://www.microchip.com/forums/m919173.aspx?tree=true – Dino Alves Mar 15 '16 at 11:40
  • @DinoAlves Take notes that a pointer to a specific location must be defined as xc32 sdk define mcu registers. Use that sintax to define your pointer. – LPs Mar 15 '16 at 13:09
0

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

blsmit5728
  • 434
  • 3
  • 11
  • I have put const char __attribute__((space(prog), address(0x9fc02fec))) signature = 0x3bdfed92; inside my bootloader and downloaded it to the pic32 and then read back the memory and 9fc02fec does not have the value 0x3bdfed92 but instead has 0xFFFFFFFF why is this happening? – Dino Alves Mar 14 '16 at 14:21
  • on a dsPIC33FJ64MC706A it points to: 0x157F2 which is close to the end of the Flash addresses. It looks like in the PIC32, 0x3BDFED92 is in the RESV section of Virtual memory. See Figure 4-6 in the Datasheet. I would suggest using something in the 0x9D000000->0x9D07FFFF Range Sorry for the late response. – blsmit5728 Mar 23 '16 at 12:31