madias wrote:Ok, I was reading the RTOS reference and looked at some examples.
In the library folder there are two RTOS libs: FreeRTOS and FreeRTOS821. I think the 821 is the newer one that I should use? (Sadly I didn't found a hint in the forum)
Howto DMA and RTOS-tasks (my consideration):
In the DMA IRQ, which triggers when buffer is empty (I deleted the half empty option) I should set a handler/trigger to an RTOS-task (call it: RTOS_audioengine)
So the RTOS_audinoengine fires up fill up and fill up the buffer?
Should I do that within the DMA IRQ with:
So the RTOS_audioengine is first priority.
The rest of the tasks should be: TFT (low priority), MIDI (middle-high), human-interface (middle-low), modulations ADSR, LFO's (middle)....
As you use a single buffer, Semaphore should work fine.
The Queues are more useful if you have several items to give, like imagine you set up 2 buffers, you can place them in a Queue with size for 2 objects, such as the pointer to the buffer start address.
Then when DMA finish sending a buffer the DMA ISR could picks one from the queue, and place the one it just used in the queue.
But for 1 single buffer, I would probably just use a semaphore.
Then in the function that needs to fill the buffer it just waits until the semaphore has been set as free and fills the buffer and take it. And the DMA ISR only takes care of giving the Semaphore back.
If you decide to use the half transfer and transfer complete interrupts, then you can split the buffer in two halves as I said before, and then you could use a Queue for 2 objects.
The ESP8266 MP3 player that someone linked a while back, uses a queue for the sending buffers from the task that decodes the MP3 to the task that plays them. That one is written for FreeRTOS if I remember right, but you can have a look.
I haven't personally used Queues yet, so can't give you much more advise.
EDIT: to add more details.
Both with queues and semaphores, you can set the timeout value waiting for it to be free. If you set it to infinite, then that task will seat not taking any CPU time until the semaphore is free or the Queue has an object to be taken. I used semaphores extensively I use mutexes to write to the screen, so only one tasks can write to the screen at any given time. Kind of like semaphores, just slightly different.
So I would do something like this.
2.-The task that writes the buffers, RTOS_audioengine, takes the semaphore, fills the buffer, and loops back to try to take the semaphore again, to just seat there because it wasn't released yet.
3.-The DMA ISR will eventually trip, and will release the semaphore, and return.
Next, RTOS_audioengine will be called because the semaphore was released, and will repeat step 1.
In the time between that task filling the buffer and the DMA emptying it, all the other tasks will take time to run depending on their priorities.
If a higher priority task is in a loop checking some something like reading a value from a pin or something that is not a CoOS thing, like queue, semaphores, mutex, etc it will block any code with a lower priority, because CoOS doesn't know it is waiting, so it will let it run.
So any time you need to wait for something, either insert a vDelay, or use mutex, semaphore, etc. You can see a bit of that in how I read the button, that has a bunch of delays before re-reading the button again. That gives time to any other task to run.
Your priorities look good to me, but the human-interface, unless you inssert a some delays like I did, should have a lower priority than MIDI, otherwise someone pressing a button may cause some Midi packets to be lost.