1
votes

I'm looking for hints in using dynamic memory handler safe in multi-threaded system. Details of the issue:

  1. written in C will run on cortex-M3 processor, with RTOS (CooCox OS),
  2. TLSF memory allocator will be used (other allocators might be used if I will find them better suited and they will be free and open-source),
  3. Solution I'm looking for is using memory allocator safe from OS tasks and interrupts.

So far thought of 2 possible approaches, both have few yet unknown for me details:

  1. disable and enable interrupts when calling allocator functions. Problem - if I'm not mistaking I can't play with interrupts disable and enable in normal mode, only in privileged mode (so if I'm not mistaken, that is only in interrupts), I need to do that from runtime also - to prevent interupts and task switching during memory handler operations.
  2. call allocator from SWI. This one is still very unclear for me. 1st - is SWI same as FIQ (if so is it true that FIQ code needs to be written in asm - since allocator is written in C). Then still have few doubts about calling FIQ from IRQ (that scenarion would happen - tho not often), but most likely this part will not cause issues.

So any ideas on possible solutions for this situation?

1
The oly way I've been able to handle this is by not using the allocation directly in interrupts at all. Instead, I use two sets of three queues, one set for IRQ, one for FIQ. In each set, one queue supplies buffer indices/pointers to the tx interrupts, one supplies 'empty' buffers to the rx interrupts and the third is a return queue for filled rx buffers and 'used' tx buffers. One thread manages each set of queues and runs when the interrupt signals a semaphore to say that the queues 'need attention'. The FIQ signals its semaphore by triggering an 'SWI' IRQ that runs when the FIQ exits. - Martin James
@MartinJames: That does not sound like Cortex-M, but the older ARM7/9/10/11 or Cortex-R (not sure about -A). COretx-M has a completely different interrupt system with a full grown interrupt controller (NVIC) which includes true vectors, priorization (internal/external), etc. This mechanism would defy the whole architecture. - too honest for this site
As far as I get from a short peek at the code, the interrupts will be blocked quite a while (allthough this might have a max. boundary). You should make sure your system can tolerate this under all circumstances. The SWI is not the thing for such (actually there is no SWI instruction, it has at least been renamed to SVC). The Cortex-M has a very clever exception system; you might have a look at SVPend instead of SVC. And (as I already stated) the Cortex-M has a different interupt system and not just two vectors. - too honest for this site
You should first get very familar with the Cortex-M exception system. Most things you state in your question do not even exist or seem to make no sense to me (no offense). You might start with the Cortex-M3 TRM and Architecture Guide which cen be downloaded free from ARM (beware: there are two different Arch-Guides). Also, your MCU-vendor should provide a reference manual (also called user('s) guide or similar; this is not the datasheet, but that might also be required). - too honest for this site

1 Answers

0
votes

Regarding your suggestions 1 and 2:

  1. On Cortex-M3 you can enable and disable interrupts at any time in privileged level code through the CMSIS intrinsics __disable_irq/_enable_irq functions. privileged level is not restricted to handler mode; thread mode code can run at privileged level too (and in many small RTOS that is the default).
  2. SWI and FIQ are concepts from legacy ARM architectures. They do not exist in Cortex-M3.

You would not ideally want to perform memory allocation in an interrupt handler - even if the allocator is deterministic, it may still take significant amount of time; I can think of few reasons you would want to do that.

The best approach is to modify the tlsf code to use an RTOS mutex for each of the calls with external linkage. Other libraries I have used have stubs already in the library that normally do nothing, but which you can override with your own implementation to map it to any RTOS.

Now you cannot of course use a mutex in an ISR, but as I said you should probably not allocate memory there either. If you really must perform allocation in an interrupt handler, then enable/disable interrupts is your only option, but you are then confounding all the real-time deterministic behaviour that an RTOS provides. A better solution to that is to have your ISR do not more than issue an event-flag or semaphore to a thread context handler. This allows you to use all RTOS services and scheduling, and the context switch time from ISR to a high priority thread will be insignificant compared to the memory allocation time.

Another possibility would be to not use this allocator at all, but instead use a fixed-block allocator using RTOS queues. You pre-allocate blocks of memory (statically or dynamically), post pointers to the start of each block onto a queue, then to allocate you simply receive a pointer from the queue, and to free you post back to the queue. If memory is exhausted (queue is empty), you can baulk or block on the queue (do not block in an ISR though). You can create multiple queues for different sized blocks, and use the one appropriate to your needs (ensuring you post back to the same queue of course!)