What is and when to use IRAM_ATTR ?

ogensyts
Posts: 9
Joined: Fri Jan 05, 2018 2:41 pm
Location: Quebec, Canada

What is and when to use IRAM_ATTR ?

Postby ogensyts » Mon Mar 12, 2018 3:15 pm

Hi,

i do not fully comprehend IRAM_ATTR. From my understanding it tells to a function to use or to be in the Internal RAM of the ESP32.

One time I used it to fix an error concerning a interrupt function running on the second core ; error which made the ESP32 crash saying there was an error with the cache. After using IRAM_ATTR on this function, everything worked fine. But to this day i do not fully comprehend why it fixed the error.

example :
before:

Code: Select all

void test_interrupt()
after:

Code: Select all

void IRAM_ATTR test_interrupt()
So my question is :
What is and when to use IRAM_ATTR ?

Thanks a lot,
ogensyts

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: What is and when to use IRAM_ATTR ?

Postby kolban » Mon Mar 12, 2018 4:46 pm

You pose a great question. Here is my understanding which could contain errors or not be complete and is an opportunity for correction of my own thinking.

The ESP32 is based on a harvard architecture which means that there are two buses ... one for instructions and one for data. Loosely, address space south of 0x4000 0000 is taken from the data bus while address space (if I remember correctly) from 0x4000 0000 to 0x4FFF FFFF is from the instruction bus.

Now imagine a 64K page of RAM. Unlike in other environments where that page of RAM "just exists" at a fixed address space location, on the ESP32 we have MMU (Memory Mapping Unit) which can make that 64K page of real RAM be mapped to distinct address locations. This means that we can have RAM that can be read from the data bus or have RAM read from the instruction bus.

That then begs the question, what would you put in RAM that can be read from the instruction bus? The answer is (if I understand correctly) ... instructions (executable code).

When we compile a C source file we end up with an object file that is then linked to produce an executable. During compilation, the different "sections" of the compiled C are placed in different "sections" of the object file. For example, code goes into the ".text" section and initialized data goes into the ".data" section. By flagging a piece of code with the "IRAM_ATTR" we are declaring that the compiled code will be placed in a section called ".dram.text" (I'm making that up as I don't have a reference to hand). What this means is that instead of an executable having just ".text" and ".data" sections, there are additional sections. The ESP32 bootloader, upon startup, will copy those ".dram.text" sections into real RAM at startup before giving control to your application. The RAM is then mapped into the instruction area address space (> 0x4000 0000). This means that control can be passed to this code (as normal) from within your running app and it will "work" because the code lives in the instruction bus address space.

What now remains is "why" you would want to do this? The answer is to consider the alternative. If the code you want to run is NOT in RAM, then where else could it be? The answer is "flash" ... if it is in flash, then when a request to execute that code is received, the code has to be executed from there. Flash on the ESP32 is much slower than RAM access ... so there is a memory cache which can be used to resolve some of that ... however we can't be assured that when we branch to a piece of code that it will be present in cache and hence may need a slow load from flash.

And now we come to the kicker ... if the code we want to run is an interrupt service routine (ISR), we invariably want to get in and out of it as quickly as possible. If we had to "wait" within an ISR for a load from flash, things would go horribly wrong. By flagging a function as existing in RAM we are effectively sacrificing valuable RAM for the knowledge that its access will be optimal and of constant time.
Last edited by kolban on Tue Mar 13, 2018 2:52 am, edited 1 time in total.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

ESP_Sprite
Posts: 8926
Joined: Thu Nov 26, 2015 4:08 am

Re: What is and when to use IRAM_ATTR ?

Postby ESP_Sprite » Tue Mar 13, 2018 2:39 am

As an addendum to Kolbans great post:
- The 'cache error' actually is from the flash cache. This is a bit of memory that is used while accessing the flash: if that bit of memory doesn't have the info you are trying to read, it'll try to update itself from flash so it can give the processor the data it needs. However, if flash is disabled it cannot do that, hence the error.
- If you use esp_intr_alloc to set up your interrupt, you normally don't need this: interrupts allocated using esp_intr_alloc will normally be disabled when flash is not available unless you pass it the ESP_INTR_FLAG_IRAM flag. If you got this error with an interrupt allocated with esp_intr_alloc without that flag, I'd be interested in seeing what you did; that's a bug.

ogensyts
Posts: 9
Joined: Fri Jan 05, 2018 2:41 pm
Location: Quebec, Canada

Re: What is and when to use IRAM_ATTR ?

Postby ogensyts » Tue Mar 13, 2018 3:29 am

@kolban :
Thank you, I now understand the usage of IRAM_ATTR, especially for the interrupts i am using. I hope this post will be useful to other people searching for this information.

@ESP_Sprite :
Interesting.

In short ; I am not using esp_intr_alloc(). That may be why I had to use IRAM_ATTR in my case.

In my case flash was not disabled ; i am storing real-time data into the NVS. So flash is available.

To add, this error only appeared after i started using the two cores simultaneously.
Core 0 = WIFI / Socket -- Core 1 = Interrupts / data storage

After some thoughts ( i may be wrong ) I think my error might be from the fact that WIFI from core 0 and data storage from core 1 both use flash (WIFI uses flash right? You have to call nvs_flash_init() before using it!).
So both cores using flash brings up some latency on the R/W operations in the flash and bugs my ESP32 because the interrupt on core 1 took too long to finish (because of flash R/W latency). Which makes using IRAM_ATTR a valuable solution for my problem.

Regards,
ogensyts

jmcornil
Posts: 21
Joined: Mon Feb 10, 2020 1:42 pm

Re: What is and when to use IRAM_ATTR ?

Postby jmcornil » Sat Feb 15, 2020 4:57 pm

Hello and Thank you for these great explanations !

But I have a question about the variables used in a such ISR tagged as IRAM_ATTR. I have read in the doc that they must be tagged as DRAM_ATTR.

Can someone explain why, and the risk if we do not so ?

I tried with a counter increment by an ISR, with and without the tag DRAM_ATTR and I get no compile error.

Best regards

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: What is and when to use IRAM_ATTR ?

Postby PeterR » Sat Feb 15, 2020 9:38 pm

This is an old post!
AFAIK. You need (EDIT: internal DRAM) in ISR code because the IDF will not fetch from external FLASH/RAM when you are in an ISR. Not sure of the exact limitations.
You cannot run FLASH code from an ISR & so a block on External RAM also seems reasonable, both of which are reached via the same SPI bus. So it follows that ISR variables must be located in internal RAM.
The compiler will know very little about these constraints. The compiler will quite hapily compile your code. Linkers allocate. You may then get a run time memory exception when trying to use memory which cannot be reached. This is simply a division of concern, the ESP specific stuff is not the compiler's concern. PS Did you tell the compiler/linker that you function was an ISR or that your variables were used from an ISR? Don't expect any compiler/linker to cover these rules.
I suspect that you do not need to use the DRAM attribute. It would help of course. AFAIK .bss and .data will not be placed in external RAM. auto will only be placed on DRAM (as the stack must be DRAM). EDIT: AFAIK external RAM is for heap allocation only.
So ISR stuff must be IRAM and DRAM. External SPI resources will be out. Makes sense as SPI access is slow. I suspect that file/static variables will by default be DRAM and auto must always be DRAM. Use the attributes to be sure.
& I also believe that IDF CAN should be fixed.

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: What is and when to use IRAM_ATTR ?

Postby ESP_Angus » Tue Feb 18, 2020 4:53 am

PeterR wrote:
Sat Feb 15, 2020 9:38 pm
I suspect that you do not need to use the DRAM attribute. It would help of course. AFAIK .bss and .data will not be placed in external RAM. auto will only be placed on DRAM (as the stack must be DRAM). EDIT: AFAIK external RAM is for heap allocation only.
So ISR stuff must be IRAM and DRAM. External SPI resources will be out. Makes sense as SPI access is slow. I suspect that file/static variables will by default be DRAM and auto must always be DRAM. Use the attributes to be sure.
That's broadly correct. The reason DRAM_ATTR exists is for constant variables, which are compiled to .rodata by default. The default location of .rodata is flash, so it's a risk. The compiler can also be clever, and notice that a variable is read-only at compile time even though it's not marked "const". Placing the DRAM_ATTR attribute prevents any of this from happening.

Some more about DRAM_ATTR & IRAM_ATTR can be found here:
https://docs.espressif.com/projects/esp ... t-handlers

If putting functions in IRAM for performance (rather than SPI flash operation safety) then it's less important to use DRAM_ATTR, unless some constant is on the "critical path" for performance (for example, an error log string that is only accessed in failure can safely be in flash as it won't be read while the function is performing, but it's a crash risk if the code is in an ISR which may be accessed while flash is being written.

BTW, it is also possible to mark some .bss sections for placement in external memory. But this is 100% optional:
https://docs.espressif.com/projects/esp ... nal-memory

jmcornil
Posts: 21
Joined: Mon Feb 10, 2020 1:42 pm

Re: What is and when to use IRAM_ATTR ?

Postby jmcornil » Tue Feb 18, 2020 9:42 am

Thank you very much for all your replies !

I see a little bit clear about this problem.

Who is online

Users browsing this forum: No registered users and 126 guests