General strategy question

Hi, This is my first post. I am making a musical sequencer on an ESP32. It is using two TFT displays. My plan was to have two tasks running - one that deals with the timing with a high priority and another that deals with the (slower) updating the display. This way the timing will remain solid.

I currently have it up and running with 2 tasks. Of course if I make the timing task a higher priority, the display task will never run. I am currently just doing a vTaskDelay() in the timing task to give the display task time to work. I have been experimenting with how long to delay for in order to have a smooth display, but not interfere with the timing.

My question: Is this a good strategy? Is there a better way to handle this situation? I have watched a bunch of tutorials, but have not really seen an example like this.

Any suggestions would be greatly appreciated!

Why is this “of course?” Will the computations in your hi pri task be so CPU bound that they will never yield the processor? Normally a closer analysis of the timing reveals that there will be times in which the high priority tasks can be allowed to yield the CPU. If that should not be the case, there is nothing you can do about it aside from running more than changing your hardware platform (eg use a MCU with multiple cores or a significantly faster processor) or try to delegate some computations, for example via DMA or a DSP coprocessor.

Thanks for your reply. My wording was clumsy - I should have written “if I just make the timing task a higher priority - without yielding the CPU…”

When I do that, then the lower task never gets run. The display updates can take 3 - 5ms, so it is possible to miss a clock in or a midi sync message which runs at 24 per quarter note.

I have tried to use the second core on the ESP32 (core 0), but my project that runs fine on one core starts rebooting after a while when I put one of the tasks on core 0. I will have to learn more to try and see what is causing the issue.

The problem is your “without yielding the CPU”. Why is the task not yielding the CPU when it has nothing to do? The whole concept of shared CPU processing is tasks need to give up the CPU when they don’t have something to do, and not just twiddle their virtual thumbs using the CPU waiting for something to happen.

The timing task needs to schedule what it needs to happen, then delay till the next event it has to process. The delay call will let the other task(s) run.