cancel
Showing results for 
Search instead for 
Did you mean: 

Help with load & Executing Code into Stm32 mcu Ram

KeiKei
Associate II

I have both STM32F1038T6 and STM32F401CC. I have been trying to get a code to run from ram for days now. 

Im using arduino ide with stm32duino. 

 

i first create a buffer in ram with malloc then  copy the code to the buffer using memcpy. The code is in  byte array inside a  include file.

 

Like for example

memcpy_P(RamAddr, mCode, 2904);
 
void (*functionPtr)(void);
functionPtr = (void(*)(void))RamAddr;
functionPtr();

 

RamAddr is a byte pointer. Also the above code is in a method function that is called in Arduinos' loop()

 

The code is copied properly. When functionPtr() is called the Program counter loads the Address of the function (Which is the start of the code) and I can see it when debugging it. However the pc increments normally but nothing happens and if left to run it ends up in WWDG_IRQHandler as pointer by Program counter. The mCode code  just blinks PC13 on and off and was built from Stm32CubeIde. I tried the blink program by flashing it directly to mcu and it works. 

So am i doing something wrong or missing something? If so how can it be done with examples. Because i want to be able to load code from spi flash or memory card

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

https://community.st.com/t5/stm32-mcus-products/bootloader-and-jumping-to-flash-location/td-p/462009

typedef int (*pFunction)(void);
void RamCode(void)
{
  static const uint16_t Code[] = { 0xF04F, 0x007B, 0x4770 }; // payload
  uint8_t Buffer[16]; // as big as required
  pFunction RunCode;
  memcpy(Buffer, Code, sizeof(Code)); // Copy code
  RunCode = (pFunction)&Buffer[1]; // +1 for Thumb code
  printf("%d\n",RunCode());
}
  MOV R0, #123
  BX LR
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

View solution in original post

6 REPLIES 6

Have a Hard Fault Handler to catch failures.

The function pointer needs to be an ODD address. Suggest you print if out to confirm.

ie 0x20002001 for code you copy to 0x20002000

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

In the data sheet it says bit 0 is not set in PC and it must be half word aligned. And i tried odd address before it does the same thing. so im using Even addresses.

Try something simple than loads R0 with a value and returns.

You'd need to show the code, and a disassembly to be able to trouble shoot from here.

It needs to be THUMB code, you need to copy on an even address, and call at the odd address. That's how the Cortex-M3 expects things.

Create a pointer for a function you can uses successfully, and print out the value. Say for a qsort() implementation, which takes a pointer for a compare function.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

So if i manual set PC to address of code in ram the code runs  but if not it just jumps to HardFault handler. I tried both odd and even address. Worst is the St-link step doesnt let me step through it maybe because its not part of the function but external code. Only lets me step through it if i manually enter the address into the Program counter.

this is the code i use to execute in ram.  Also i removed the Push,pop and bx instructions and it does the same thing. However it worked once when push and pop werent included but bx lr was but it immediately caused a fault  when it got to digitalwrite after functionptr(). Then it never worked again lol.

 

void ExecuteCodeInBuffer()
{  
  //0x10,0xB5 Push All general purpose ( M bit Set)
  //0x10,0xBD Push all registers with Bit 8 set ( Bit P)
  //0x10,0xBC Push all registers with Bit 8 not set ( bit P)

  //nCode does this
  //push all regs
  //MOV R1,0xFE
  //MOV R2,0xED
  //MOV R3,0xBE
  //MOV R4,0xBF
  //POP all regs
  //BX LR

  byte nCode[14] = { 0x10,0xB5,0xFE,0x21,0xED,0x22,0xBE,0x23,0xBF,0x24,0x10,0xBC,0x70,0x47};

  uint32_t xAddr = (uint)NewAddr;
  if((xAddr & 0x1) == 0x1) { Serial.print("NewAddr is not half word Aligned.");}

   Serial.print("NewAddr: 0x");
   Serial.println(xAddr,HEX);

  byte* pAddr = (byte*)&nCode[0];
  uint32_t* pAddr32 =(uint32_t*) &nCode[0];
  memcpy_P((byte*)NewAddr,pAddr, 14);

   Serial.print("Ram Address of All Code: 0x");
   uint32_t mAddr = (uint)(uint*)NewAddr;
   Serial.println(mAddr,HEX);
   Serial.print("New Address Ins: 0x");
   Serial.print( NewAddr[0],HEX);
   Serial.print(" Old Address Ins: 0x");
   Serial.println(pAddr32[0],HEX);
 

    byte* FunctionAddr = (byte*)((uint32_t)NewAddr + 1);

    Serial.print("Address Of main() Code In Ram  : 0x");
    Serial.println(((uint)FunctionAddr),HEX);


   int value = memcmp((byte*)NewAddr, (byte*)pAddr32,14);

   if(value != 0){ Serial.println("Data is Corrupted."); }
   else { Serial.println("Data is Copied Successfully."); }
 
    Serial.println("Setting Up Function Pointer.");

     void (*functionPtr)(void);
     functionPtr = (void(*)(void))FunctionAddr;
   
     

      Serial.println("Performing Long Call to Function Pointer.");
      int cc=10;
        Serial.print("Executing Call in...");
       for(int i=0;i < 10;i++)
       {
         Serial.print("-");
         Serial.print(cc);
         digitalWrite(PC13, HIGH); /
         delay(500);
         digitalWrite(PC13, LOW); 
         delay(500);
         cc--;

       }
      Serial.println(" ");
       
      functionPtr();

      digitalWrite(PC13, LOW); 
      Serial.println("After Function Call.");

}
   

https://community.st.com/t5/stm32-mcus-products/bootloader-and-jumping-to-flash-location/td-p/462009

typedef int (*pFunction)(void);
void RamCode(void)
{
  static const uint16_t Code[] = { 0xF04F, 0x007B, 0x4770 }; // payload
  uint8_t Buffer[16]; // as big as required
  pFunction RunCode;
  memcpy(Buffer, Code, sizeof(Code)); // Copy code
  RunCode = (pFunction)&Buffer[1]; // +1 for Thumb code
  printf("%d\n",RunCode());
}
  MOV R0, #123
  BX LR
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

I got it to work. I was getting the error because i was  modifying 4 registers, r1,r2,r3,r4 which were used by rtos so what i did was push these registers then run my code. After code runs, i pop the registers then use BX LR.

 also another error i was getting was because of  using wrong push and pop instructions. There is two versions of both push and pop. For push there is 0xB4 and 0xB5 and for pop there is 0xBC and 0xBD. I had to use 0xB4(push) with 0xBC(pop) and if i used 0xB5(push) then use 0xBD for pop. Any other combination causes a fault.

for the new code it looks like this

 

byte nCode[14] = { 0x10,0xB5,0xFE,0x21,0xED,0x22,0xBE,0x23,0xBF,0x24,0x10,0xBD,0x70,0x47 };

Thanks for the help. Really appreciate it.