0
\$\begingroup\$

So I'm working on a bootloader for a dsPIC33EP32MC504 with a CAN-Bus and the Bootloader flashes the firmware correctly. I verified that by reading out the program memory at the location I flashed it to and compared it with how the firmware looks like when its flashed via a programming tool.

The problem now is that the microcontoller wont let me jump to the address of the firmware. When the command is executed, the microcontroller simply resets itself and starts at 0x000000 again, which jumps to 0x000200 where the bootloader is.

I tried two different types of goto-jumps:

1.: Inline asm code

asm("goto 0x1C00");

2.: function pointer

//first defining the pointer
firmware_ptr = (void (*)(void))0x1C00;
//...
//later using the function
firmware_ptr();

Unfortunately both ways lead to the same result as described above

Another thing I tried is giving the code base of the firmware an offset by manipulating the linker-script and only program the firmware to the microcontroller via the PICkit3 and without the bootloader. I manipulated the two lines mentioning the start of the program in the linker script:

/*
** Memory Regions
*/
MEMORY
{
  data  (a!xr)   : ORIGIN = 0x1000,        LENGTH = 0x1000
  reset          : ORIGIN = 0x0,           LENGTH = 0x4
  ivt            : ORIGIN = 0x4,           LENGTH = 0x1FC
  program (xr)   : ORIGIN = 0x1C00,         LENGTH = 0x55EC  /*here*/
  FICD           : ORIGIN = 0x57F0,        LENGTH = 0x2
  FPOR           : ORIGIN = 0x57F2,        LENGTH = 0x2
  FWDT           : ORIGIN = 0x57F4,        LENGTH = 0x2
  FOSC           : ORIGIN = 0x57F6,        LENGTH = 0x2
  FOSCSEL        : ORIGIN = 0x57F8,        LENGTH = 0x2
  FGS            : ORIGIN = 0x57FA,        LENGTH = 0x2
  FUID0          : ORIGIN = 0x800FF8,      LENGTH = 0x2
  FUID1          : ORIGIN = 0x800FFA,      LENGTH = 0x2
  FUID2          : ORIGIN = 0x800FFC,      LENGTH = 0x2
  FUID3          : ORIGIN = 0x800FFE,      LENGTH = 0x2
}

__FICD = 0x57F0;
__FPOR = 0x57F2;
__FWDT = 0x57F4;
__FOSC = 0x57F6;
__FOSCSEL = 0x57F8;
__FGS = 0x57FA;
__FUID0 = 0x800FF8;
__FUID1 = 0x800FFA;
__FUID2 = 0x800FFC;
__FUID3 = 0x800FFE;
__NO_HANDLES = 1;          
__CODE_BASE = 0x1C00;      /*And here*/
__CODE_LENGTH = 0x55EC;
__IVT_BASE  = 0x4;

__DATA_BASE = 0x1000;
__DATA_LENGTH = 0x1000;
__YDATA_BASE = 0x1800;

Unfortunately the same thing occurs: it always resets and never runs

Some more information on the bootloader and the firmware: Neither bootloader nor firmware uses interrupts, therefore the IVT is empty. The bootloader is programmed via a PICkit3 at the beginning of the programm memory (at 0x0200) and the firmware should start at 0x1C00. The firmware is only a small testing firmware consisting of 203 words, and is working fine when programmed normally via the PICkit3 at 0x0200. In the python script which I use to calculate the addresses and words from the .hex file, I only transmit the firmware related words and addresses to the bootloader, not the IVT or the reset vector. The configuration bits of firmware and bootloader are the same. I use the XC16 version 1.35 compiler for firmware and bootloader

Since I am running out of ideas what could be the problem, I think I missed something regarding the organisation of the programm memory in the dsPIC33E series or regarding the inner connection between program pointer, program memory and IVT

\$\endgroup\$
1
\$\begingroup\$

This is what works for me:

void PIC_LongJump( uint32_t Addr )
{
    __asm__ ("push.d %0" : : "r"(Addr));
    __asm__ ("return" : : );
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.