Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
6 years, 9 months ago.
Tickers and Queues on F411RE
Hi guys,
I'm trying to use an Mbed Ticker object to push 'events' into a Queue object. It seems like this should be fairly simple, however it appears the callback attached to the Ticker never gets called.
Here is an abstract of my code:
DigitalOut userLed(LED1); Queue<int, 8> eventQueue; Ticker drawTimeInt; Ticker checkAlarmInt; void mainLoop(){ time_t seconds = time(NULL); struct tm* curTime = localtime(&seconds); osEvent event; int* eventCode; drawTimeInt.attach(&scheduleDrawTime, 1.0f); checkAlarmInt.attach(&scheduleCheckAlarms, ((60.0) - (curTime->tm_sec))); while(1){ seconds = time(NULL); curTime = localtime(&seconds); event = eventQueue.get(50); if(event.status == osEventMessage){ eventCode = (int*) event.value.p; switch(*eventCode){ case EVENT_DRAW_TIME: drawTime(seconds); break; case EVENT_CHECK_ALARMS: checkAlarms(curTime); checkAlarmInt.attach(&scheduleCheckAlarms, 60.0); break; default: debugWrite(DEBUG_ER, "Invalid event code: %d", *eventCode); break; } } else{ debugWrite(DEBUG_IN, "Nothing..."); } } void scheduleDrawTime(){ int event = EVENT_DRAW_TIME; userLed = !userLed; eventQueue.put(&event, 1000); } void scheduleCheckAlarms(){ int event = EVENT_CHECK_ALARMS; eventQueue.put(&event, 1000); }
I have tried only using 1 Ticker and removing any of the queue interaction and I still see no activity from the LED. This leads me to believe the timer interrupt is simply never triggering.
Anyone have any ideas for what could be causing this?
Also is it even possible to use the Queue object from interrupt context? How many Ticker objects can be in use at once?
Thanks, Russell Bateman
1 Answer
6 years, 9 months ago.
I tried to make a more generic example that is runnable. This works for me. However, I am still worried about access to the shared variable event_number.
#include "mbed.h" #define EVENT_NULL 0 #define EVENT1 1 #define EVENT2 2 DigitalOut led(LED1); Queue<int, 8> queue; Ticker ticker1; Ticker ticker2; int event_number = EVENT_NULL; void event1Isr(); void event2Isr(); int main() { osEvent os_event; int *event_received; ticker1.attach(&event1Isr, 1.0f); ticker2.attach(&event2Isr, 1.1f); printf("\n\nStart\n"); while (1) { os_event = queue.get(100); // printf("OS event status %d\n",os_event.status); if (os_event.status == osEventMessage) { event_received = (int *)os_event.value.p; switch (*event_received) { case EVENT_NULL: printf("null event\n"); break; case EVENT1: printf("event1\n"); break; case EVENT2: printf("event2\n"); break; default: printf("Invalid event code: %d\n", *event_received); break; } } else { printf(".\n"); } } } void event1Isr() { event_number = EVENT1; led = !led; queue.put(&event_number); } void event2Isr() { event_number = EVENT2; queue.put(&event_number); }
Hi Graham, thanks for looking at this for me. I can confirm your code does indeed work! However I can't see any massive differences between this code and what I'm doing. I was wondering why you made the event number a shared global instead of having a local variable to the ISR. Is this normally best practise?
If the ISR's trigger at fairly different paces then I cant imagine it creates much of an issue. I was just wondering if there was any rationale behind this choice or if it was just your preference.
Anyway thanks for the code and I'll try and get my program working from it!
posted by 18 Mar 2018You can't pass a pointer to a local variable into the queue because the variable goes out of scope when the ISR exits and no longer exits by the time main gets to it. Another way to do it is to use a mailbox, which is like a queue but with storage. In this simple case, a global boolean flag would work almost as well as the queue but would introduce a little bit of delay since main() would wait out the 50ms delay every time whereas with the queue it runs immediately. But the global volatile bool flag would be simpler.
I also removed the timeout in the call to queue.put because it was causing me trouble and didn't seem necessary anyway.
posted by 18 Mar 2018