Вопрос

I have an mplabx project with a custom bootloader and application for the PIC32MX795F512L. All throughout its development, I have been jumping from the bootloader to the application with no problem using the line:

((void (*)(void))(APPLICATION_RESET_ADDRESS))();

where APPLICATION_RESET_ADDRESS is a macro with the address of the reset handler for my application. After some recent modifications to the bootloader, I suddenly started getting into the general exception handler sometime after executing that line and before getting into the main function of the application. the odd thing is, if I set a breakpoint on that line and then continue after breaking it works fine. further more, if I change the way I jump to the application to:

asm volatile
(
    "JALR %0"
    :
    :"r"(APPLICATION_RESET_ADDRESS)
    :
);

it jumps to the application with no problem which is really confusing because the assembly generated by: ((void (*)(void))(APPLICATION_RESET_ADDRESS))(); is

LUI v0,-25341
ADDIU V0, V0, -28672
JALR V0
NOP

and the assembly generated by:

asm volatile
(
    "JALR %0"
    :
    :"r"(APPLICATION_RESET_ADDRESS)
    :
);

is

LUI V0, -25342
ORI V0, V0, -28672
JALR V0
NOP

so both methods use the same number of instructions, and both jump using JALR the only difference between the 2 is how they load the pointer into the register. does anyone have any ideas?

Это было полезно?

Решение

I don't know if you have already covered this case. But, one possible issue that you may be experiencing is the fact that you could be running interrupts while jumping to your application. While Microchip does not expressly cover this situation in their Application Note on the PIC 32 Bootloader - AN1388, there is a possibility that you could vector to an incorrect address if an interrupt occurs and you are in the middle of setting up your startup code in the application - a lot of this would depend on how your startup code is setup.

It is always a good idea to disable interrupts prior to jumping to your application.

If you look at the AN1388 Source Code for microchip, you can see that they disable interrupts prior to jumping to the application. Below is their code with my own comments:

//Enter firmware upgrade mode if there is a trigger or if the
//application is not valid.
if(CheckTrigger() || !ValidAppPresent())
{
    TRANS_LAYER_Init(pbClk);  //  Init the transport layer...
                              //Interrupts are enabled during
                              //this function.
    while(!FRAMEWORK_ExitFirmwareUpgradeMode())
    {
        /* Keep receiving commands from the PC */
        ...
    }

    TRANS_LAYER_Close();  //   This is just a wrapper that
                          //makes a call to a function which
                          //disables all interrupts.
}

JumpToApp();  //Similar to your function.

Hopefully, this will give you someplace to look. I do not see any issues with how you are calling the jump.

Другие советы

I know this isn't an answer to why but, I used the same method as the AN1388 from microchip to jump to my bootloader:

void jump_to_app(void)
{
    void (*fptr)(void);
    fptr = (void (*)(void))USER_APP_RESET_ADDRESS;
    fptr();
}

It works and we have a pretty complicated bootloader/application combination in our product.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top