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;