Ramfunc attribute not working with RP2040

I am trying to use a Raspberry Pi Pico board to drive an ILI9341 based display. I program it using the Arduino IDE and Earle Philhower's RP2040 core. I want the driver to be fast, so I'd like to place the critical functions in RAM memory.
I am using the section(".ramfunc") attribute, but it does not work. The function still lands in flash memory. However, if I specify the .data section, then it works. See this program fragment:

__attribute__((section(".ramfunc"), noinline)) uint32_t Ramfunc() {
  register uint32_t result asm("r0");
  asm (
    "mov r0, pc"
    : "=r" (result) : :
  );
  return result;
}

__attribute__((section(".data"), noinline)) uint32_t Data() {
  register uint32_t result asm("r0");
  asm (
    "mov r0, pc                     "
    : "=r" (result) : :
  );
  return result;
}

void setup() {
  Serial.begin(9600);
  Serial.println(Ramfunc(), HEX);
  Serial.println(Data(), HEX);
}

void loop() { }

The functions return their own locations in the memory map. The output is:

1000F154
20000F3C

The former is in flash XIP. The latter is in RAM.
I also looked at the elf file with objdump:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .boot2        00000100  10000000  10000000  00010000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .ota          000024e4  10000100  10000100  00010100  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .partition    00000a1c  100025e4  100025e4  000125e4  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  3 .text         0000c150  10003000  10003000  00013000  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  4 .ramfunc      00000004  1000f150  1000f150  0001f150  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  5 .rodata       0000091c  1000f158  1000f158  0001f158  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .ram_vector_table 000000c0  20000000  20000000  0002170c  2**2
                  CONTENTS
  7 .data         0000164c  200000c0  1000fa74  000200c0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  8 .scratch_x    00000000  20040000  20040000  000217cc  2**0
                  CONTENTS

That says the same thing: .ramfunc section is in flash memory.

Although the .data trick seems to work, is probably a dangerous solution. Also, it does not compile with Arduino IDE v1.8.19 (the latest that's willing to run on my laptop's Windows 7).
My question: is there a way to make .ramfunc work correctly? Or some other method to get that function in RAM? It is true, that frequently used routines tend to get copied in the cache, but just in case...

There is no .ramfunc section in the Pico's linker script: arduino-pico/lib/memmap_default.ld at master · earlephilhower/arduino-pico · GitHub

If you want to place a function in RAM, use __not_in_flash_func or __time_critical_func:

@PieterP Thank you very much for your help. It solved my problem.
I have previously experimented with __not_in_flash_func, but it didn't work. Why? Because I made a mistake: I used it alone, without provisions to keep the compiler from inlining the function. My test function was small, was invoked from only one place, so it got inlined into setup(), which was residing in flash memory.
Your answer hinted at __no_inline_not_in_flash_func, which was a full success. Using section("time_critical") worked too. And both solutions work with Arduino IDE v1.8.19 (for those who still hang on to Windows 7 like me).
Here is a summary of all experiments:

uint32_t __no_inline_not_in_flash_func(MyFunc)(arguments);  // just works
__attribute__ ((long_call, section (".time_critical"))) uint32_t MyFunc(arguments);  // just works
uint32_t __not_in_flash_func(MyFunc)(arguments);  // lands in flash if gets inlined
__attribute__ ((long_call, section (".data"))) uint32_t MyFunc(arguments);  // works in Arduino v2.1.1, doesn't compile in v1.8.19
__attribute__ ((long_call, section (".ramfunc"))) uint32_t MyFunc(arguments);  // lands in flash

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.