I am porting an existing FreeRTOS projects that runs on a single core MCU to the RP2040 dual ARM Cortex M0+ MCU. The second core will be dedicated to an IO task, so FreeRTOS only needs to run on the first core. The existing application uses an ISR to execute vTaskNotify when certain I/O events occur. In the RP2040 port those I/O events will be detected by a state machine running on the second core. My question is: what mechanism can I use to have the second core execute a vTaskNotify on the first core? I imagine that the second core will need to store details of the required vTaskNotify call in a mailbox in shared memory, then generate some kind of interrupt to the first core to tell it to look at the mailbox.
That would be one way. “Inter-system” communication (as an AMP-Multi-core application often ends up needing) often get very application specific, especially if it needs to be efficient, and not just over some “Standard Communication Channel” (virtual or real).
Are you using FreeRTOS SMP? If so, you can pin IO task to one core and rest all the tasks to the other core. You should then be able to use vTaskNotify.
@aggarg thanks for replying. However, we are planning to run standard FreeRTOS on one core only. We can afford to dedicate the second core to the IO task, which is to implement a limited implementation of CAN-FD without BRS running at 1mbit/sec. If we ran FreeRTOS on the second core, the task switching overhead would probably jeopardise the ability of the core to meet the required deadlines, in particular to generate the ACK bit when a message has been received, accepted, and the CRC checked.
I have found that the RP2040 has two FIFOs for passing 32-bit words between the cores. It appears that if we avoid using certain SDK functions that would claim exclusive use of these FIFOs (which IMO is one of several poor design decisions in the RP2040 SDK), we can use one of these FIFOs to pass a mailbox address from the second core to the first.
PS your comment " Are you using FreeRTOS SMP? If so, you can pin IO task to one core and rest all the tasks to the other core" is interesting. Perhaps I should look into it further.
My knowledge of the system is limited to your above description - but so far I think running the single core version on one core is the right choice. You need that core to be able to generate interrupts on the second core so a task on the second core can block to wait for the interrupt to know there is data to read. How you generate the interrupt, or how you pass the data, depends on the hardware capability - maybe via the mailboxes - or otherwise a simple circular buffer (lockless maybe, for efficiency, which is basically what the FreeRTOS stream buffers are), other other suitable mechanism.
I ended up using the inter-core fifo from core 1 to core 0 to allow core 1 to interrupt core 0. All other communication was done using shared memory, with each variable being 32 bits or less, only one of the cores writing each variable.
Thank you for taking time to report your solution.