I am trying to create a device that controls an array of 8 LED’s. I can communicate to the CYBLE-416045-02 module with Bluetooth connection and call different functions that turn the LED’s on and off per specific patterns. A particular pattern is blinking the LED’s forever with an infinite loop implemented with for (;;).
If I once start this function to run forever, I cannot stop it with another Bluetooth message. I couldn’t find how to implement an interrupt mechanism that would break the forever loop and start another patter of LED’s blinking.
Do I need to consider to use tasks rather than functions with forever loops? I just want the blinking pattern to run until I send another mode command via Bluetooth or turn the device off.
Basically you‘re better off using separate task(s) for concurrent functions. Maybe including FreeRTOS timers (implemented as task, as well).
But you could also set a global (volatile) variable or flag in an ISR you can check in the infinite loop and break to invoke another function or simply select an other pattern within this loop.
Hello Geodreieck, in order to get more insight into your project, maybe you can attach some code that you have already written?
What if I need to run a function forever?
In fact, a task is a function that runs for ever. One thing to remember is that a task must always yield or block, in order to give CPU time to other tasks.
If your code has a loop forever with nothing in it to stop to accept new data, that is what the code will do. It sounds like that blinking loop should have in it some test to see if a new pattern is available. This likely means that the display operation is a task, and gathering new patterns may well be a separate task that when it gets the new information sends that to the display task.
One way to do this is use something like a queue to post the new pattern, and the display loop does a read from queue with no wait, and IF you get a new pattern, you switch to it, and if you don’t you keep the same pattern.
void genericEventHandler(uint32_t event, void *eventParam)
{
/* Take an action based on the current event */
printf("genericEventHandler\r\n");
switch (event)
{
/* This event is received when the BLE stack is Started */
...
case CY_BLE_EVT_GATTS_WRITE_REQ:
printf("Command received\r\n");
running = false;
handleBluetoothMessage(eventParam);
break;
default:
printf("Unhandled Bluetooth event\r\n");
break;
}
}
handleBluetoothMessage is the function that decodes received Bluetooth message and starts the blinking pattern. I also have added some debug code and I checked them with UART. The problem is, once the blinking pattern starts, the Bluetooth stack stops receiving any messages. If the pattern ends then it starts accepting messages again. If the pattern is a forever loop, then it never handles any other Bluetooth message.
I guess I am doing a very basic design error somewhere in the code, but I couldn’t figure it out by myself. I hope the snippets explain it better.
Googling your function, I found this example. It calls Cy_BLE_GATTS_WriteRsp(handle) after handling the request. Did you also do so?
If the pattern ends then it starts accepting messages again
Wait, which code is producing the blinking? The function handleBluetoothMessage()?
I would expect that function to return immediately so you can receive more messages.
The easiest solution is to add a separate task that does the blinking, like e.g.
@htibosch Thank you very much for your help. After your message, I found that I had to study the task concept a little bit more and I have spent a good three hours on studying the “Mastering the FreeRTOS™ Real Time Kernel” document.
Now I have two seperate task. One is for the Bluetooth, one is for the blinking. They communicate over a queue mechanism. It works like a charm.
Thank you again for your guidance. I feel much more comfortable with tasks now.