I'm struggling with my first real freeRTOS project. I am basically using an ATmega328P microcontroller and an nRF24L01+ radio as a "node". I have two of these nodes and I am using them to talk to each other. I have successfully ported freeRTOS to my microcontroller so that I can use tasks to blink LEDs and to do very basic send/receive of data using my radio driver which I also wrote. The part that I'm struggling with is how to best structure my code and tasks to create something like a network layer on top of my radio driver.
Here were my initial thoughts:
- When the radio's data ready interrupt fired, I would set a global boolean variable to signal to my "radio_task()" function to read data from the radios FIFO.
I would have a function called "radio_task()", which would NOT actually be a freeRTOS task, which would check the outgoing queue and use my radio driver (in combination with freeRTOS receiveFromQueue()) to send the front packet on the queue if there is one. This function would also check the global boolean and read a packet from the radio's FIFO if there was one. It would then sendToQueue() this read packet onto the incoming queue.
I would then have an actual freeRTOS called nwk_task() which would have a state machine to do various network maintenance and upkeep etc. Inside the state machine there would be some calls to a nwk_send() function which would sendToQueue() for the outgoing queue. Likewise there would have to be some receiveFromQueue() calls on the incoming queue which would process whatever packets I receive. Then lastly this freeRTOS task would call my function radio_task()
I would potentially have other tasks running which would monitor sensor data and perhaps also call nwk_send() when certain events occur based on sensor data etc.
I feel like that is not a terrible approach, but I'm running into a few difficulties that I thought I would ask about. Questions:
- I've created a typedef for my nwk_packet_t which is a struct consisting of an address, a statically defined array which is the maximum size for a radio packet, and a data_length which says how much of the array is actually used for this packet. How do I make a freeRTOS queue which holds my nwk_packet_t 's?? Also is there a better way to make my nwk_packet_t than using the statically sized array? I thought about using a pointer but then I have to make sure the array that I'm sending isn't overwritten until it's actually pulled off the queue right?
I'm confused about where blocking would/needs to occur. By using the global boolean flag in my data ready ISR I allow interrupts to occur more frequently, but does that mean I need to use portENTER_CRITICAL() when I actually push/pull data from the queues?
How would a more experienced embedded programmer structure the tasks and queues to allow for a network layer on top of my basic radio driver?
Sorry for my severe lack of understanding on some of these topics, this is my first venture into OS level programming. Everything else I've done has been very low level and basic C. Thanks for your help!
EDIT: One thing I forgot to mention is that my radio has some hardware provisions for acking. You can set a message to be auto acknowledged with a certain number of retries and the hardware will handle all of that. However, a message can still fail which you can read from the radio or have the radio trigger an interrupt when this happens. So I would like to have some notion of a message success and a message failure that does some type of callback but I have no idea how to work that into my structure. Any ideas on that would fit in with removing stuff from the queues etc.?