Home > Software engineering >  APM32 C Copy & Execute function in RAM
APM32 C Copy & Execute function in RAM

Time:05-03

hi i am using an APM32F003 with Keil uVision compiler.
is a little known microcontroller but compatible with STM32.

I would like to write functions in RAM for different purposes.

I don't want to use the linker attribute to assign the function in ram,
but I want to copy a written one in flash and transfer it in RAM in run-time.

below the code I am trying to write but for now it is not working.
I think it's not possible in this way right?

static volatile uint8_t m_buffer_ram[100];

void flash_function()
{
    /* Example */
    LED2_ON();
}

void flash_function_end()
{
}

void call_function_in_ram()
{
    uint32_t size = (uint32_t) flash_function_end - (uint32_t) flash_function;

    /* clone function in RAM */
    for (uint32_t i = 0; i < size; i  )
        m_buffer_ram[i] = (((uint8_t*)&flash_function)[i]);

    __disable_irq();

    /* cast buffer to function pointer */
    void(*func_ptr)(void) = (void(*)(void)) (&m_buffer_ram);
    /* call function in ram */
    func_ptr();

    __enable_irq();
}

CodePudding user response:

Eugene asked if your function is relocatable. This is very important. I have had issues in the past wherein I copied a function from flash to RAM, and the compiler used an absolute address in the "flash" based function. Therefore the code which was running in RAM jumped back into the flash. This is just one example of what might go wrong with moving code which is not relocatable.

If you have a debugger that can disassemble and also step through the compiled code for you, that would be ideal.

Note also "the busybee" pointed out that code which is adjacent in source code does is not guaranteed to be adjacent in the compiled binary, so your method of finding the size of the code is not reliable.

You can look in the map file to determine the size of the function. I agree with the comment that you would be better off learning to have the linker do the work for you.

None of what I am saying here is new; I am just reinforcing the comments made above.

CodePudding user response:

  • CODE

      static volatile uint8_t m_buffer_ram[200];
      static uint32_t m_function_size;
    
      void flash_function(void)
      {
          LED2_ON();
      }
    
      void flash_function_end(void)
      {
      }
    
      void test(void)
      {
          m_function_size = (uint32_t) flash_function_end - (uint32_t) flash_function;
    
          /* clone function in RAM */
          for (uint16_t i = 0; i < m_function_size; i  )
              m_buffer_ram[i] = (((uint8_t*)&flash_function)[i]);
    
          __disable_irq();
    
          /* cast buffer to function pointer,  1 Thumb Code */
          void(*func_ptr)(void) = (void(*)(void)) (&m_buffer_ram[1]);
          /* call function in ram */
          func_ptr();
    
          __enable_irq();
      }
    
  • MAP

    Image Symbol Table

      Symbol Name                            Value         Ov Type        Size  Object(Section)
    
      Local Symbols
      .....
      m_function_size                        0x20000024       Data           4  test.o(.data)
      m_buffer_ram                           0x200001f0       Data         200  test.o(.bss)
    
      Global Symbols
      .....
      flash_function                         0x00000399   Thumb Code    12  test.o(i.flash_function)
      flash_function_end                     0x000003a9   Thumb Code     2  test.o(i.flash_function_end)
    

    Memory Map of the image

      Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
      .....
      0x00000398   0x00000398   0x00000010   Code   RO        355    i.flash_function      test.o
      0x000003a8   0x000003a8   0x00000002   Code   RO        356    i.flash_function_end  test.o
    
  • DISASSEMBLE

      .....
          30:         m_function_size = (uint32_t) flash_function_end - (uint32_t) flash_function; 
          31:  
      0x00000462 480D      LDR      r0,[pc,#52]  ; @0x00000498
      0x00000464 4A0D      LDR      r2,[pc,#52]  ; @0x0000049C
      0x00000466 4C0E      LDR      r4,[pc,#56]  ; @0x000004A0
      0x00000468 1A81      SUBS     r1,r0,r2
      0x0000046A 6021      STR      r1,[r4,#0x00]
          32:         for (uint16_t i = 0; i < m_function_size; i  ) 
      0x0000046C 2000      MOVS     r0,#0x00
          33:                 m_buffer_ram[i] = (((uint8_t*)&flash_function)[i]); 
          34:  
      0x0000046E 4B0D      LDR      r3,[pc,#52]  ; @0x000004A4
      0x00000470 2900      CMP      r1,#0x00
      0x00000472 D905      BLS      0x00000480
          33:                 m_buffer_ram[i] = (((uint8_t*)&flash_function)[i]); 
      0x00000474 5C15      LDRB     r5,[r2,r0]
      0x00000476 541D      STRB     r5,[r3,r0]
          32:         for (uint16_t i = 0; i < m_function_size; i  ) 
      0x00000478 1C40      ADDS     r0,r0,#1
      0x0000047A B280      UXTH     r0,r0
          32:         for (uint16_t i = 0; i < m_function_size; i  ) 
      0x0000047C 4288      CMP      r0,r1
      0x0000047E D3F9      BCC      0x00000474
          35:         __disable_irq(); 
          36:  
      0x00000480 B672      CPSID    I
          37:         void(*func_ptr)(void) = (void(*)(void)) (&m_buffer_ram[1]); 
      0x00000482 1C5B      ADDS     r3,r3,#1
          38:         func_ptr(); 
          39:  
      0x00000484 4798      BLX      r3
          40:         __enable_irq();  
          41:  
      0x00000486 B662      CPSIE    I
    

I report all the information that I was able to recover. I added a shift for the Thumb Code; the calculation of the function size coincides with the MAP file
my doubt is that in debug the pointer cannot jump to a point of the RAM .. for this reason I activate a led to see if (flashing code and run) this turns on without debugging.

as reported below, the read values coincide
    (0x000003a8)flash_function_end - (0x00000398)flash_function = 0x10
    (0x20000024)m_function_size = 0x10
    func_ptr = 0x200001f1;
  • Related