How to best convert legacy polling embedded firmware architecture into an event driven one?












-1














I've got a family of embedded products running a typical main-loop based firmware with 150+k lines of code. A load of complex timing critical features is realized by a combination of hardware interrupt handlers, timer polling and protothreads (think co-routines). Actually protothreads are polling well and "only" are syntactic sugar to mimic pseudo-parallel scheduling of multiple threads (endless loops). I add bugfixes and extensions to the firmware all the time. There are about 30k devices of about 7 slightly different hardware types and versions out in the field.



For a new product-family member I need to integrate an external FreeRTOS-based project on the new product only while all older products need to get further features and improvements.



In order to not have to port the whole complex legacy firmware to FreeRTOS with all the risk of breaking perfectly fine products I plan to let the old firmware run inside a FreeRTOS task. On the older products the firmware shall still not run without FreeRTOS. Inside the FreeRTOS task the legacy firmware would consume all available processor time because its underlying implementation scheme is polling based. Due to the fact that its using prothreads (timer and hardware polling based behind the scenes) and polls on a free-running processor counter register I hope that I can convert the polling into a event driven behavior.



Here are two examples:





// first example: do something every 100 ms
if (GET_TICK_COUNT() - start > MS(100))
{
start = GET_TICK_COUNT();
// do something every 100 ms
}




// second example: wait for hardware event
setup_hardware();
PT_WAIT_UNTIL(hardware_ready(), pt);

// hardware is ready, do something else




So I got the impression that I can convert these 2 programming patterns (e.g. through macro magic and FreeRTOS functionality) into an underlying event based scheme.



So now my question: has anybody done such a thing already? Are there patterns and or best practices to follow?



[Update]



Thanks for the detailed responses. Let me comment some details: My need is to combine a "multithreading-simulation based legacy firmware (using coo-routines implementation protothreads)" and a FreeRTOS based project being composed of a couple of interacting FreeRTOS tasks. The idea is to let the complete old firmware run in its own RTOS task besides the other new tasks. I'm aware of RTOS principles and patterns (pre-emption, ressource sharing, blocking operations, signals, semaphores, mutexes, mailboxes, task priorities and so forth). I've planed to base the interaction of old and new parts exactly on these mechanisms. What I'm asking for is 1) Ideas how to convert the legacy firmware (150k+ LOC) in a semi-automated way so that the busy-waiting / polling schemes I presented above are using either the new mechanisms when run inside the RTOS tasks or just work the old way when build and run as the current main-loop-kind of firmware. A complete rewrite / full port of the legacy code is no option. 2) More ideas how to teach the old firmware implementation that is used to have full CPU resources on its hands to behave nicely inside its new prison of a RTOS task and not just consume all CPU cycles available (when given the highest priority) or producing new large Real Time Latencies when run not at the highest RTOS priority.



I guess here is nobody who already has done such a very special tas. So I just have to do the hard work and solve all the described issues one after another.










share|improve this question
























  • Things like interrupts vs polling are low-level concepts, whereas processes and threads are higher level, and event-driven even higher level. There's no obvious benefit of using event-driven patterns in real-time code. Event-driven design is more suitable for GUI and high-level programming. Mostly it is just another buzzword, which by itself does not give any obvious benefits nor disadvantages, it is just a design pattern which may or may not be useful.
    – Lundin
    Nov 20 at 11:45












  • Just have look at the two examples take out of the current firmware: the first is based on the polling pattern. The second is actually based on the polling pattern as well behind the scenes - but I want to replace polling with blocking primitives from FreeRTOS when possible. So I get an event driven scheme and are not wasting CPU power any more.
    – Marcel
    Nov 20 at 16:03






  • 1




    @Lundin : Mostly you make complete sense, but "no obvious benefit of using event-driven patterns in real-time code." makes no sense to me. Most hard real-time systems react to external real-time events - that is rather the definition. While you can create a deterministic system using simple time-triggered methods, many tasks require near instantaneous response to some real-time event. Perhaps you have a different concept of "event driven"; while the term is often applied to UI frameworks, it has other contexts.
    – Clifford
    Nov 20 at 21:24










  • @Clifford My definition of event-driven is that you have an API where you can register events by passing on numerous function pointers, and will then have callback functions executed when an event occurs. Such as create_menu(on_enter, on_exit, on_selected), where the parameters are function pointers of a given format. What you describe rather sounds like interrupt handlers. Though of course, you can execute callbacks from inside an ISR, but that requires that the person who wrote the callback knows what they are doing, and keep it minimal.
    – Lundin
    Nov 21 at 7:59












  • @Lundin I see. The term is rather more general than that, and pre-dates GUI frameworks by many years. I am not talking about interrupt handlers, but more specifically real-time events, such as event: limit switch opened, reaction: motor stops within 1ms. That may involve interrupts, but that is an implementation detail.
    – Clifford
    Nov 21 at 8:08


















-1














I've got a family of embedded products running a typical main-loop based firmware with 150+k lines of code. A load of complex timing critical features is realized by a combination of hardware interrupt handlers, timer polling and protothreads (think co-routines). Actually protothreads are polling well and "only" are syntactic sugar to mimic pseudo-parallel scheduling of multiple threads (endless loops). I add bugfixes and extensions to the firmware all the time. There are about 30k devices of about 7 slightly different hardware types and versions out in the field.



For a new product-family member I need to integrate an external FreeRTOS-based project on the new product only while all older products need to get further features and improvements.



In order to not have to port the whole complex legacy firmware to FreeRTOS with all the risk of breaking perfectly fine products I plan to let the old firmware run inside a FreeRTOS task. On the older products the firmware shall still not run without FreeRTOS. Inside the FreeRTOS task the legacy firmware would consume all available processor time because its underlying implementation scheme is polling based. Due to the fact that its using prothreads (timer and hardware polling based behind the scenes) and polls on a free-running processor counter register I hope that I can convert the polling into a event driven behavior.



Here are two examples:





// first example: do something every 100 ms
if (GET_TICK_COUNT() - start > MS(100))
{
start = GET_TICK_COUNT();
// do something every 100 ms
}




// second example: wait for hardware event
setup_hardware();
PT_WAIT_UNTIL(hardware_ready(), pt);

// hardware is ready, do something else




So I got the impression that I can convert these 2 programming patterns (e.g. through macro magic and FreeRTOS functionality) into an underlying event based scheme.



So now my question: has anybody done such a thing already? Are there patterns and or best practices to follow?



[Update]



Thanks for the detailed responses. Let me comment some details: My need is to combine a "multithreading-simulation based legacy firmware (using coo-routines implementation protothreads)" and a FreeRTOS based project being composed of a couple of interacting FreeRTOS tasks. The idea is to let the complete old firmware run in its own RTOS task besides the other new tasks. I'm aware of RTOS principles and patterns (pre-emption, ressource sharing, blocking operations, signals, semaphores, mutexes, mailboxes, task priorities and so forth). I've planed to base the interaction of old and new parts exactly on these mechanisms. What I'm asking for is 1) Ideas how to convert the legacy firmware (150k+ LOC) in a semi-automated way so that the busy-waiting / polling schemes I presented above are using either the new mechanisms when run inside the RTOS tasks or just work the old way when build and run as the current main-loop-kind of firmware. A complete rewrite / full port of the legacy code is no option. 2) More ideas how to teach the old firmware implementation that is used to have full CPU resources on its hands to behave nicely inside its new prison of a RTOS task and not just consume all CPU cycles available (when given the highest priority) or producing new large Real Time Latencies when run not at the highest RTOS priority.



I guess here is nobody who already has done such a very special tas. So I just have to do the hard work and solve all the described issues one after another.










share|improve this question
























  • Things like interrupts vs polling are low-level concepts, whereas processes and threads are higher level, and event-driven even higher level. There's no obvious benefit of using event-driven patterns in real-time code. Event-driven design is more suitable for GUI and high-level programming. Mostly it is just another buzzword, which by itself does not give any obvious benefits nor disadvantages, it is just a design pattern which may or may not be useful.
    – Lundin
    Nov 20 at 11:45












  • Just have look at the two examples take out of the current firmware: the first is based on the polling pattern. The second is actually based on the polling pattern as well behind the scenes - but I want to replace polling with blocking primitives from FreeRTOS when possible. So I get an event driven scheme and are not wasting CPU power any more.
    – Marcel
    Nov 20 at 16:03






  • 1




    @Lundin : Mostly you make complete sense, but "no obvious benefit of using event-driven patterns in real-time code." makes no sense to me. Most hard real-time systems react to external real-time events - that is rather the definition. While you can create a deterministic system using simple time-triggered methods, many tasks require near instantaneous response to some real-time event. Perhaps you have a different concept of "event driven"; while the term is often applied to UI frameworks, it has other contexts.
    – Clifford
    Nov 20 at 21:24










  • @Clifford My definition of event-driven is that you have an API where you can register events by passing on numerous function pointers, and will then have callback functions executed when an event occurs. Such as create_menu(on_enter, on_exit, on_selected), where the parameters are function pointers of a given format. What you describe rather sounds like interrupt handlers. Though of course, you can execute callbacks from inside an ISR, but that requires that the person who wrote the callback knows what they are doing, and keep it minimal.
    – Lundin
    Nov 21 at 7:59












  • @Lundin I see. The term is rather more general than that, and pre-dates GUI frameworks by many years. I am not talking about interrupt handlers, but more specifically real-time events, such as event: limit switch opened, reaction: motor stops within 1ms. That may involve interrupts, but that is an implementation detail.
    – Clifford
    Nov 21 at 8:08
















-1












-1








-1







I've got a family of embedded products running a typical main-loop based firmware with 150+k lines of code. A load of complex timing critical features is realized by a combination of hardware interrupt handlers, timer polling and protothreads (think co-routines). Actually protothreads are polling well and "only" are syntactic sugar to mimic pseudo-parallel scheduling of multiple threads (endless loops). I add bugfixes and extensions to the firmware all the time. There are about 30k devices of about 7 slightly different hardware types and versions out in the field.



For a new product-family member I need to integrate an external FreeRTOS-based project on the new product only while all older products need to get further features and improvements.



In order to not have to port the whole complex legacy firmware to FreeRTOS with all the risk of breaking perfectly fine products I plan to let the old firmware run inside a FreeRTOS task. On the older products the firmware shall still not run without FreeRTOS. Inside the FreeRTOS task the legacy firmware would consume all available processor time because its underlying implementation scheme is polling based. Due to the fact that its using prothreads (timer and hardware polling based behind the scenes) and polls on a free-running processor counter register I hope that I can convert the polling into a event driven behavior.



Here are two examples:





// first example: do something every 100 ms
if (GET_TICK_COUNT() - start > MS(100))
{
start = GET_TICK_COUNT();
// do something every 100 ms
}




// second example: wait for hardware event
setup_hardware();
PT_WAIT_UNTIL(hardware_ready(), pt);

// hardware is ready, do something else




So I got the impression that I can convert these 2 programming patterns (e.g. through macro magic and FreeRTOS functionality) into an underlying event based scheme.



So now my question: has anybody done such a thing already? Are there patterns and or best practices to follow?



[Update]



Thanks for the detailed responses. Let me comment some details: My need is to combine a "multithreading-simulation based legacy firmware (using coo-routines implementation protothreads)" and a FreeRTOS based project being composed of a couple of interacting FreeRTOS tasks. The idea is to let the complete old firmware run in its own RTOS task besides the other new tasks. I'm aware of RTOS principles and patterns (pre-emption, ressource sharing, blocking operations, signals, semaphores, mutexes, mailboxes, task priorities and so forth). I've planed to base the interaction of old and new parts exactly on these mechanisms. What I'm asking for is 1) Ideas how to convert the legacy firmware (150k+ LOC) in a semi-automated way so that the busy-waiting / polling schemes I presented above are using either the new mechanisms when run inside the RTOS tasks or just work the old way when build and run as the current main-loop-kind of firmware. A complete rewrite / full port of the legacy code is no option. 2) More ideas how to teach the old firmware implementation that is used to have full CPU resources on its hands to behave nicely inside its new prison of a RTOS task and not just consume all CPU cycles available (when given the highest priority) or producing new large Real Time Latencies when run not at the highest RTOS priority.



I guess here is nobody who already has done such a very special tas. So I just have to do the hard work and solve all the described issues one after another.










share|improve this question















I've got a family of embedded products running a typical main-loop based firmware with 150+k lines of code. A load of complex timing critical features is realized by a combination of hardware interrupt handlers, timer polling and protothreads (think co-routines). Actually protothreads are polling well and "only" are syntactic sugar to mimic pseudo-parallel scheduling of multiple threads (endless loops). I add bugfixes and extensions to the firmware all the time. There are about 30k devices of about 7 slightly different hardware types and versions out in the field.



For a new product-family member I need to integrate an external FreeRTOS-based project on the new product only while all older products need to get further features and improvements.



In order to not have to port the whole complex legacy firmware to FreeRTOS with all the risk of breaking perfectly fine products I plan to let the old firmware run inside a FreeRTOS task. On the older products the firmware shall still not run without FreeRTOS. Inside the FreeRTOS task the legacy firmware would consume all available processor time because its underlying implementation scheme is polling based. Due to the fact that its using prothreads (timer and hardware polling based behind the scenes) and polls on a free-running processor counter register I hope that I can convert the polling into a event driven behavior.



Here are two examples:





// first example: do something every 100 ms
if (GET_TICK_COUNT() - start > MS(100))
{
start = GET_TICK_COUNT();
// do something every 100 ms
}




// second example: wait for hardware event
setup_hardware();
PT_WAIT_UNTIL(hardware_ready(), pt);

// hardware is ready, do something else




So I got the impression that I can convert these 2 programming patterns (e.g. through macro magic and FreeRTOS functionality) into an underlying event based scheme.



So now my question: has anybody done such a thing already? Are there patterns and or best practices to follow?



[Update]



Thanks for the detailed responses. Let me comment some details: My need is to combine a "multithreading-simulation based legacy firmware (using coo-routines implementation protothreads)" and a FreeRTOS based project being composed of a couple of interacting FreeRTOS tasks. The idea is to let the complete old firmware run in its own RTOS task besides the other new tasks. I'm aware of RTOS principles and patterns (pre-emption, ressource sharing, blocking operations, signals, semaphores, mutexes, mailboxes, task priorities and so forth). I've planed to base the interaction of old and new parts exactly on these mechanisms. What I'm asking for is 1) Ideas how to convert the legacy firmware (150k+ LOC) in a semi-automated way so that the busy-waiting / polling schemes I presented above are using either the new mechanisms when run inside the RTOS tasks or just work the old way when build and run as the current main-loop-kind of firmware. A complete rewrite / full port of the legacy code is no option. 2) More ideas how to teach the old firmware implementation that is used to have full CPU resources on its hands to behave nicely inside its new prison of a RTOS task and not just consume all CPU cycles available (when given the highest priority) or producing new large Real Time Latencies when run not at the highest RTOS priority.



I guess here is nobody who already has done such a very special tas. So I just have to do the hard work and solve all the described issues one after another.







embedded polling freertos firmware event-driven






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 at 10:47

























asked Nov 20 at 10:19









Marcel

245




245












  • Things like interrupts vs polling are low-level concepts, whereas processes and threads are higher level, and event-driven even higher level. There's no obvious benefit of using event-driven patterns in real-time code. Event-driven design is more suitable for GUI and high-level programming. Mostly it is just another buzzword, which by itself does not give any obvious benefits nor disadvantages, it is just a design pattern which may or may not be useful.
    – Lundin
    Nov 20 at 11:45












  • Just have look at the two examples take out of the current firmware: the first is based on the polling pattern. The second is actually based on the polling pattern as well behind the scenes - but I want to replace polling with blocking primitives from FreeRTOS when possible. So I get an event driven scheme and are not wasting CPU power any more.
    – Marcel
    Nov 20 at 16:03






  • 1




    @Lundin : Mostly you make complete sense, but "no obvious benefit of using event-driven patterns in real-time code." makes no sense to me. Most hard real-time systems react to external real-time events - that is rather the definition. While you can create a deterministic system using simple time-triggered methods, many tasks require near instantaneous response to some real-time event. Perhaps you have a different concept of "event driven"; while the term is often applied to UI frameworks, it has other contexts.
    – Clifford
    Nov 20 at 21:24










  • @Clifford My definition of event-driven is that you have an API where you can register events by passing on numerous function pointers, and will then have callback functions executed when an event occurs. Such as create_menu(on_enter, on_exit, on_selected), where the parameters are function pointers of a given format. What you describe rather sounds like interrupt handlers. Though of course, you can execute callbacks from inside an ISR, but that requires that the person who wrote the callback knows what they are doing, and keep it minimal.
    – Lundin
    Nov 21 at 7:59












  • @Lundin I see. The term is rather more general than that, and pre-dates GUI frameworks by many years. I am not talking about interrupt handlers, but more specifically real-time events, such as event: limit switch opened, reaction: motor stops within 1ms. That may involve interrupts, but that is an implementation detail.
    – Clifford
    Nov 21 at 8:08




















  • Things like interrupts vs polling are low-level concepts, whereas processes and threads are higher level, and event-driven even higher level. There's no obvious benefit of using event-driven patterns in real-time code. Event-driven design is more suitable for GUI and high-level programming. Mostly it is just another buzzword, which by itself does not give any obvious benefits nor disadvantages, it is just a design pattern which may or may not be useful.
    – Lundin
    Nov 20 at 11:45












  • Just have look at the two examples take out of the current firmware: the first is based on the polling pattern. The second is actually based on the polling pattern as well behind the scenes - but I want to replace polling with blocking primitives from FreeRTOS when possible. So I get an event driven scheme and are not wasting CPU power any more.
    – Marcel
    Nov 20 at 16:03






  • 1




    @Lundin : Mostly you make complete sense, but "no obvious benefit of using event-driven patterns in real-time code." makes no sense to me. Most hard real-time systems react to external real-time events - that is rather the definition. While you can create a deterministic system using simple time-triggered methods, many tasks require near instantaneous response to some real-time event. Perhaps you have a different concept of "event driven"; while the term is often applied to UI frameworks, it has other contexts.
    – Clifford
    Nov 20 at 21:24










  • @Clifford My definition of event-driven is that you have an API where you can register events by passing on numerous function pointers, and will then have callback functions executed when an event occurs. Such as create_menu(on_enter, on_exit, on_selected), where the parameters are function pointers of a given format. What you describe rather sounds like interrupt handlers. Though of course, you can execute callbacks from inside an ISR, but that requires that the person who wrote the callback knows what they are doing, and keep it minimal.
    – Lundin
    Nov 21 at 7:59












  • @Lundin I see. The term is rather more general than that, and pre-dates GUI frameworks by many years. I am not talking about interrupt handlers, but more specifically real-time events, such as event: limit switch opened, reaction: motor stops within 1ms. That may involve interrupts, but that is an implementation detail.
    – Clifford
    Nov 21 at 8:08


















Things like interrupts vs polling are low-level concepts, whereas processes and threads are higher level, and event-driven even higher level. There's no obvious benefit of using event-driven patterns in real-time code. Event-driven design is more suitable for GUI and high-level programming. Mostly it is just another buzzword, which by itself does not give any obvious benefits nor disadvantages, it is just a design pattern which may or may not be useful.
– Lundin
Nov 20 at 11:45






Things like interrupts vs polling are low-level concepts, whereas processes and threads are higher level, and event-driven even higher level. There's no obvious benefit of using event-driven patterns in real-time code. Event-driven design is more suitable for GUI and high-level programming. Mostly it is just another buzzword, which by itself does not give any obvious benefits nor disadvantages, it is just a design pattern which may or may not be useful.
– Lundin
Nov 20 at 11:45














Just have look at the two examples take out of the current firmware: the first is based on the polling pattern. The second is actually based on the polling pattern as well behind the scenes - but I want to replace polling with blocking primitives from FreeRTOS when possible. So I get an event driven scheme and are not wasting CPU power any more.
– Marcel
Nov 20 at 16:03




Just have look at the two examples take out of the current firmware: the first is based on the polling pattern. The second is actually based on the polling pattern as well behind the scenes - but I want to replace polling with blocking primitives from FreeRTOS when possible. So I get an event driven scheme and are not wasting CPU power any more.
– Marcel
Nov 20 at 16:03




1




1




@Lundin : Mostly you make complete sense, but "no obvious benefit of using event-driven patterns in real-time code." makes no sense to me. Most hard real-time systems react to external real-time events - that is rather the definition. While you can create a deterministic system using simple time-triggered methods, many tasks require near instantaneous response to some real-time event. Perhaps you have a different concept of "event driven"; while the term is often applied to UI frameworks, it has other contexts.
– Clifford
Nov 20 at 21:24




@Lundin : Mostly you make complete sense, but "no obvious benefit of using event-driven patterns in real-time code." makes no sense to me. Most hard real-time systems react to external real-time events - that is rather the definition. While you can create a deterministic system using simple time-triggered methods, many tasks require near instantaneous response to some real-time event. Perhaps you have a different concept of "event driven"; while the term is often applied to UI frameworks, it has other contexts.
– Clifford
Nov 20 at 21:24












@Clifford My definition of event-driven is that you have an API where you can register events by passing on numerous function pointers, and will then have callback functions executed when an event occurs. Such as create_menu(on_enter, on_exit, on_selected), where the parameters are function pointers of a given format. What you describe rather sounds like interrupt handlers. Though of course, you can execute callbacks from inside an ISR, but that requires that the person who wrote the callback knows what they are doing, and keep it minimal.
– Lundin
Nov 21 at 7:59






@Clifford My definition of event-driven is that you have an API where you can register events by passing on numerous function pointers, and will then have callback functions executed when an event occurs. Such as create_menu(on_enter, on_exit, on_selected), where the parameters are function pointers of a given format. What you describe rather sounds like interrupt handlers. Though of course, you can execute callbacks from inside an ISR, but that requires that the person who wrote the callback knows what they are doing, and keep it minimal.
– Lundin
Nov 21 at 7:59














@Lundin I see. The term is rather more general than that, and pre-dates GUI frameworks by many years. I am not talking about interrupt handlers, but more specifically real-time events, such as event: limit switch opened, reaction: motor stops within 1ms. That may involve interrupts, but that is an implementation detail.
– Clifford
Nov 21 at 8:08






@Lundin I see. The term is rather more general than that, and pre-dates GUI frameworks by many years. I am not talking about interrupt handlers, but more specifically real-time events, such as event: limit switch opened, reaction: motor stops within 1ms. That may involve interrupts, but that is an implementation detail.
– Clifford
Nov 21 at 8:08














2 Answers
2






active

oldest

votes


















2














In an RTOS you create and run tasks. If you are not running more than one task, then there is little advantage in using an RTOS.



I don't use FreeRTOS (but have done), but the following applies to any RTOS, and is pseudo-code rather then FreeRTOS API specific - many details such as task priorities and stack allocation are deliberately missing.



First in most simple RTOS, including FreeRTOS, main() is used for hardware initialisation, task creation, and scheduler start:



int main( void )
{
// Necessary h/w & kernel initialisation
initHardware() ;
initKernel() ;

// Create tasks
createTask( task1 ) ;
createTask( task2 ) ;

// Start scheduling
schedulerStart() ;

// schedulerStart should not normally return
return 0 ;
}


Now let us assume that your first example is implemented in task1. A typical RTOS will have both timer and delay functions. The simplest to use is a delay, and this is suitable when the periodic processing is guaranteed to take less than one OS tick period:



void task1()
{
// do something every 100 ms
for(;;)
{
delay( 100 ) ; // assuming 1ms tick period

// something
...
}
}


If the something takes more than 1ms in this case, it will not be executed every 100ms, but 100ms plus the something execution time, which may itself be variable or non-deterministic leading to undesirable timing jitter. In that case you should use a timer:



void task1()
{
// do something every 100 ms
TIMER timer = createTimer( 100 ) ; // assuming 1ms tick period
for(;;)
{
timerWait() ;

// something
...
}
}


That way something can take up to 100ms and will still be executed accurately and deterministically every 100ms.



Now to your second example; that is a little more complex. If nothing useful can happen until the hardware is initialised, then you may as well use your existing pattern in main() before starting the scheduler. However as a generalisation, waiting for something in a different context (task or interrupt) to occur is done using a synchronisation primitive such as a semaphore or task event flag (not all RTOS have task event flags). So in a simple case in main() you might create a semaphore:



createSemaphore( hardware_ready ) ;


Then in the context performing the process that must complete:



// Init hardware
...

// Tell waiting task hardware ready
semaphoreGive( hardware_ready ) ;


Then in some task that will wait for the hardware to be ready:



void task2()
{
// wait for hardware ready
semaphoreTake( hardware_ready ) ;

// do something else
for(;;)
{
// This loop must block is any lower-priority task
// will run. Equal priority tasks may run is round-robin
// scheduling is implemented.
...
}
}





share|improve this answer































    1














    You are facing two big gotchas...




    1. Since the old code is implemented using protothreads (coroutines), there is never any asynchronous resource contention between them. If you split these into FreeRTOS tasks, there there will be preemptive scheduling task switches; these switches may occur at places where the protothreads were not expecting, leaving data or other resources in an inconsistent state.

    2. If you convert any of your protothreads' PT_WAIT calls into real waits in FreeRTOS, the call will really block. But the protothreads assume that other protothreads continue while they're blocked.


    So, #1 implies you cannot just convert protothreads to tasks, and #2 implies you must convert protothreads to tasks (if you use FreeRTOS blocking primitives, like xEventGroupWaitBits().



    The most straightforward approach will be to put all your protothreads in one task, and continue polling within that task.






    share|improve this answer





















    • Thats exactly the kind of way I want to go. Please see my update in the question. You seam to have seen such stuff already. Any further hints for me?
      – Marcel
      Nov 21 at 10:49










    • your second point is a big issue on my list. My current idea is to convert most or all protothread code behind the scenes into a semi-blocking combination of waiting for the real event (e.g. data was sent on a serial channel) and asking a new internal timer module if any other protothread is un-blocking and we need to go there. I find it a very interesting puzzle to solve...
      – Marcel
      Nov 21 at 11:12












    • also @Marcel: I have never used FreeRTOS but glancing over the documentation it looks like they implemented exactly the ProtoThreads functionality - they termed it Coroutines there. Maybe the mapping is close to 1:1
      – Vroomfondel
      Nov 21 at 13:31










    • @Doug Currie Oh thats a missunderstanding. The legacy firmware use not based on FreeRTOS Coroutines / protothreads. I used directly Adam Dunkels protothread implementation. Its just under 50 lines of C headers. Nothing more. I won't port that to FreeRTOS.
      – Marcel
      Nov 22 at 9:35











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53390809%2fhow-to-best-convert-legacy-polling-embedded-firmware-architecture-into-an-event%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    In an RTOS you create and run tasks. If you are not running more than one task, then there is little advantage in using an RTOS.



    I don't use FreeRTOS (but have done), but the following applies to any RTOS, and is pseudo-code rather then FreeRTOS API specific - many details such as task priorities and stack allocation are deliberately missing.



    First in most simple RTOS, including FreeRTOS, main() is used for hardware initialisation, task creation, and scheduler start:



    int main( void )
    {
    // Necessary h/w & kernel initialisation
    initHardware() ;
    initKernel() ;

    // Create tasks
    createTask( task1 ) ;
    createTask( task2 ) ;

    // Start scheduling
    schedulerStart() ;

    // schedulerStart should not normally return
    return 0 ;
    }


    Now let us assume that your first example is implemented in task1. A typical RTOS will have both timer and delay functions. The simplest to use is a delay, and this is suitable when the periodic processing is guaranteed to take less than one OS tick period:



    void task1()
    {
    // do something every 100 ms
    for(;;)
    {
    delay( 100 ) ; // assuming 1ms tick period

    // something
    ...
    }
    }


    If the something takes more than 1ms in this case, it will not be executed every 100ms, but 100ms plus the something execution time, which may itself be variable or non-deterministic leading to undesirable timing jitter. In that case you should use a timer:



    void task1()
    {
    // do something every 100 ms
    TIMER timer = createTimer( 100 ) ; // assuming 1ms tick period
    for(;;)
    {
    timerWait() ;

    // something
    ...
    }
    }


    That way something can take up to 100ms and will still be executed accurately and deterministically every 100ms.



    Now to your second example; that is a little more complex. If nothing useful can happen until the hardware is initialised, then you may as well use your existing pattern in main() before starting the scheduler. However as a generalisation, waiting for something in a different context (task or interrupt) to occur is done using a synchronisation primitive such as a semaphore or task event flag (not all RTOS have task event flags). So in a simple case in main() you might create a semaphore:



    createSemaphore( hardware_ready ) ;


    Then in the context performing the process that must complete:



    // Init hardware
    ...

    // Tell waiting task hardware ready
    semaphoreGive( hardware_ready ) ;


    Then in some task that will wait for the hardware to be ready:



    void task2()
    {
    // wait for hardware ready
    semaphoreTake( hardware_ready ) ;

    // do something else
    for(;;)
    {
    // This loop must block is any lower-priority task
    // will run. Equal priority tasks may run is round-robin
    // scheduling is implemented.
    ...
    }
    }





    share|improve this answer




























      2














      In an RTOS you create and run tasks. If you are not running more than one task, then there is little advantage in using an RTOS.



      I don't use FreeRTOS (but have done), but the following applies to any RTOS, and is pseudo-code rather then FreeRTOS API specific - many details such as task priorities and stack allocation are deliberately missing.



      First in most simple RTOS, including FreeRTOS, main() is used for hardware initialisation, task creation, and scheduler start:



      int main( void )
      {
      // Necessary h/w & kernel initialisation
      initHardware() ;
      initKernel() ;

      // Create tasks
      createTask( task1 ) ;
      createTask( task2 ) ;

      // Start scheduling
      schedulerStart() ;

      // schedulerStart should not normally return
      return 0 ;
      }


      Now let us assume that your first example is implemented in task1. A typical RTOS will have both timer and delay functions. The simplest to use is a delay, and this is suitable when the periodic processing is guaranteed to take less than one OS tick period:



      void task1()
      {
      // do something every 100 ms
      for(;;)
      {
      delay( 100 ) ; // assuming 1ms tick period

      // something
      ...
      }
      }


      If the something takes more than 1ms in this case, it will not be executed every 100ms, but 100ms plus the something execution time, which may itself be variable or non-deterministic leading to undesirable timing jitter. In that case you should use a timer:



      void task1()
      {
      // do something every 100 ms
      TIMER timer = createTimer( 100 ) ; // assuming 1ms tick period
      for(;;)
      {
      timerWait() ;

      // something
      ...
      }
      }


      That way something can take up to 100ms and will still be executed accurately and deterministically every 100ms.



      Now to your second example; that is a little more complex. If nothing useful can happen until the hardware is initialised, then you may as well use your existing pattern in main() before starting the scheduler. However as a generalisation, waiting for something in a different context (task or interrupt) to occur is done using a synchronisation primitive such as a semaphore or task event flag (not all RTOS have task event flags). So in a simple case in main() you might create a semaphore:



      createSemaphore( hardware_ready ) ;


      Then in the context performing the process that must complete:



      // Init hardware
      ...

      // Tell waiting task hardware ready
      semaphoreGive( hardware_ready ) ;


      Then in some task that will wait for the hardware to be ready:



      void task2()
      {
      // wait for hardware ready
      semaphoreTake( hardware_ready ) ;

      // do something else
      for(;;)
      {
      // This loop must block is any lower-priority task
      // will run. Equal priority tasks may run is round-robin
      // scheduling is implemented.
      ...
      }
      }





      share|improve this answer


























        2












        2








        2






        In an RTOS you create and run tasks. If you are not running more than one task, then there is little advantage in using an RTOS.



        I don't use FreeRTOS (but have done), but the following applies to any RTOS, and is pseudo-code rather then FreeRTOS API specific - many details such as task priorities and stack allocation are deliberately missing.



        First in most simple RTOS, including FreeRTOS, main() is used for hardware initialisation, task creation, and scheduler start:



        int main( void )
        {
        // Necessary h/w & kernel initialisation
        initHardware() ;
        initKernel() ;

        // Create tasks
        createTask( task1 ) ;
        createTask( task2 ) ;

        // Start scheduling
        schedulerStart() ;

        // schedulerStart should not normally return
        return 0 ;
        }


        Now let us assume that your first example is implemented in task1. A typical RTOS will have both timer and delay functions. The simplest to use is a delay, and this is suitable when the periodic processing is guaranteed to take less than one OS tick period:



        void task1()
        {
        // do something every 100 ms
        for(;;)
        {
        delay( 100 ) ; // assuming 1ms tick period

        // something
        ...
        }
        }


        If the something takes more than 1ms in this case, it will not be executed every 100ms, but 100ms plus the something execution time, which may itself be variable or non-deterministic leading to undesirable timing jitter. In that case you should use a timer:



        void task1()
        {
        // do something every 100 ms
        TIMER timer = createTimer( 100 ) ; // assuming 1ms tick period
        for(;;)
        {
        timerWait() ;

        // something
        ...
        }
        }


        That way something can take up to 100ms and will still be executed accurately and deterministically every 100ms.



        Now to your second example; that is a little more complex. If nothing useful can happen until the hardware is initialised, then you may as well use your existing pattern in main() before starting the scheduler. However as a generalisation, waiting for something in a different context (task or interrupt) to occur is done using a synchronisation primitive such as a semaphore or task event flag (not all RTOS have task event flags). So in a simple case in main() you might create a semaphore:



        createSemaphore( hardware_ready ) ;


        Then in the context performing the process that must complete:



        // Init hardware
        ...

        // Tell waiting task hardware ready
        semaphoreGive( hardware_ready ) ;


        Then in some task that will wait for the hardware to be ready:



        void task2()
        {
        // wait for hardware ready
        semaphoreTake( hardware_ready ) ;

        // do something else
        for(;;)
        {
        // This loop must block is any lower-priority task
        // will run. Equal priority tasks may run is round-robin
        // scheduling is implemented.
        ...
        }
        }





        share|improve this answer














        In an RTOS you create and run tasks. If you are not running more than one task, then there is little advantage in using an RTOS.



        I don't use FreeRTOS (but have done), but the following applies to any RTOS, and is pseudo-code rather then FreeRTOS API specific - many details such as task priorities and stack allocation are deliberately missing.



        First in most simple RTOS, including FreeRTOS, main() is used for hardware initialisation, task creation, and scheduler start:



        int main( void )
        {
        // Necessary h/w & kernel initialisation
        initHardware() ;
        initKernel() ;

        // Create tasks
        createTask( task1 ) ;
        createTask( task2 ) ;

        // Start scheduling
        schedulerStart() ;

        // schedulerStart should not normally return
        return 0 ;
        }


        Now let us assume that your first example is implemented in task1. A typical RTOS will have both timer and delay functions. The simplest to use is a delay, and this is suitable when the periodic processing is guaranteed to take less than one OS tick period:



        void task1()
        {
        // do something every 100 ms
        for(;;)
        {
        delay( 100 ) ; // assuming 1ms tick period

        // something
        ...
        }
        }


        If the something takes more than 1ms in this case, it will not be executed every 100ms, but 100ms plus the something execution time, which may itself be variable or non-deterministic leading to undesirable timing jitter. In that case you should use a timer:



        void task1()
        {
        // do something every 100 ms
        TIMER timer = createTimer( 100 ) ; // assuming 1ms tick period
        for(;;)
        {
        timerWait() ;

        // something
        ...
        }
        }


        That way something can take up to 100ms and will still be executed accurately and deterministically every 100ms.



        Now to your second example; that is a little more complex. If nothing useful can happen until the hardware is initialised, then you may as well use your existing pattern in main() before starting the scheduler. However as a generalisation, waiting for something in a different context (task or interrupt) to occur is done using a synchronisation primitive such as a semaphore or task event flag (not all RTOS have task event flags). So in a simple case in main() you might create a semaphore:



        createSemaphore( hardware_ready ) ;


        Then in the context performing the process that must complete:



        // Init hardware
        ...

        // Tell waiting task hardware ready
        semaphoreGive( hardware_ready ) ;


        Then in some task that will wait for the hardware to be ready:



        void task2()
        {
        // wait for hardware ready
        semaphoreTake( hardware_ready ) ;

        // do something else
        for(;;)
        {
        // This loop must block is any lower-priority task
        // will run. Equal priority tasks may run is round-robin
        // scheduling is implemented.
        ...
        }
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 20 at 21:27

























        answered Nov 20 at 21:12









        Clifford

        58.1k858125




        58.1k858125

























            1














            You are facing two big gotchas...




            1. Since the old code is implemented using protothreads (coroutines), there is never any asynchronous resource contention between them. If you split these into FreeRTOS tasks, there there will be preemptive scheduling task switches; these switches may occur at places where the protothreads were not expecting, leaving data or other resources in an inconsistent state.

            2. If you convert any of your protothreads' PT_WAIT calls into real waits in FreeRTOS, the call will really block. But the protothreads assume that other protothreads continue while they're blocked.


            So, #1 implies you cannot just convert protothreads to tasks, and #2 implies you must convert protothreads to tasks (if you use FreeRTOS blocking primitives, like xEventGroupWaitBits().



            The most straightforward approach will be to put all your protothreads in one task, and continue polling within that task.






            share|improve this answer





















            • Thats exactly the kind of way I want to go. Please see my update in the question. You seam to have seen such stuff already. Any further hints for me?
              – Marcel
              Nov 21 at 10:49










            • your second point is a big issue on my list. My current idea is to convert most or all protothread code behind the scenes into a semi-blocking combination of waiting for the real event (e.g. data was sent on a serial channel) and asking a new internal timer module if any other protothread is un-blocking and we need to go there. I find it a very interesting puzzle to solve...
              – Marcel
              Nov 21 at 11:12












            • also @Marcel: I have never used FreeRTOS but glancing over the documentation it looks like they implemented exactly the ProtoThreads functionality - they termed it Coroutines there. Maybe the mapping is close to 1:1
              – Vroomfondel
              Nov 21 at 13:31










            • @Doug Currie Oh thats a missunderstanding. The legacy firmware use not based on FreeRTOS Coroutines / protothreads. I used directly Adam Dunkels protothread implementation. Its just under 50 lines of C headers. Nothing more. I won't port that to FreeRTOS.
              – Marcel
              Nov 22 at 9:35
















            1














            You are facing two big gotchas...




            1. Since the old code is implemented using protothreads (coroutines), there is never any asynchronous resource contention between them. If you split these into FreeRTOS tasks, there there will be preemptive scheduling task switches; these switches may occur at places where the protothreads were not expecting, leaving data or other resources in an inconsistent state.

            2. If you convert any of your protothreads' PT_WAIT calls into real waits in FreeRTOS, the call will really block. But the protothreads assume that other protothreads continue while they're blocked.


            So, #1 implies you cannot just convert protothreads to tasks, and #2 implies you must convert protothreads to tasks (if you use FreeRTOS blocking primitives, like xEventGroupWaitBits().



            The most straightforward approach will be to put all your protothreads in one task, and continue polling within that task.






            share|improve this answer





















            • Thats exactly the kind of way I want to go. Please see my update in the question. You seam to have seen such stuff already. Any further hints for me?
              – Marcel
              Nov 21 at 10:49










            • your second point is a big issue on my list. My current idea is to convert most or all protothread code behind the scenes into a semi-blocking combination of waiting for the real event (e.g. data was sent on a serial channel) and asking a new internal timer module if any other protothread is un-blocking and we need to go there. I find it a very interesting puzzle to solve...
              – Marcel
              Nov 21 at 11:12












            • also @Marcel: I have never used FreeRTOS but glancing over the documentation it looks like they implemented exactly the ProtoThreads functionality - they termed it Coroutines there. Maybe the mapping is close to 1:1
              – Vroomfondel
              Nov 21 at 13:31










            • @Doug Currie Oh thats a missunderstanding. The legacy firmware use not based on FreeRTOS Coroutines / protothreads. I used directly Adam Dunkels protothread implementation. Its just under 50 lines of C headers. Nothing more. I won't port that to FreeRTOS.
              – Marcel
              Nov 22 at 9:35














            1












            1








            1






            You are facing two big gotchas...




            1. Since the old code is implemented using protothreads (coroutines), there is never any asynchronous resource contention between them. If you split these into FreeRTOS tasks, there there will be preemptive scheduling task switches; these switches may occur at places where the protothreads were not expecting, leaving data or other resources in an inconsistent state.

            2. If you convert any of your protothreads' PT_WAIT calls into real waits in FreeRTOS, the call will really block. But the protothreads assume that other protothreads continue while they're blocked.


            So, #1 implies you cannot just convert protothreads to tasks, and #2 implies you must convert protothreads to tasks (if you use FreeRTOS blocking primitives, like xEventGroupWaitBits().



            The most straightforward approach will be to put all your protothreads in one task, and continue polling within that task.






            share|improve this answer












            You are facing two big gotchas...




            1. Since the old code is implemented using protothreads (coroutines), there is never any asynchronous resource contention between them. If you split these into FreeRTOS tasks, there there will be preemptive scheduling task switches; these switches may occur at places where the protothreads were not expecting, leaving data or other resources in an inconsistent state.

            2. If you convert any of your protothreads' PT_WAIT calls into real waits in FreeRTOS, the call will really block. But the protothreads assume that other protothreads continue while they're blocked.


            So, #1 implies you cannot just convert protothreads to tasks, and #2 implies you must convert protothreads to tasks (if you use FreeRTOS blocking primitives, like xEventGroupWaitBits().



            The most straightforward approach will be to put all your protothreads in one task, and continue polling within that task.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 20 at 20:57









            Doug Currie

            35.2k76108




            35.2k76108












            • Thats exactly the kind of way I want to go. Please see my update in the question. You seam to have seen such stuff already. Any further hints for me?
              – Marcel
              Nov 21 at 10:49










            • your second point is a big issue on my list. My current idea is to convert most or all protothread code behind the scenes into a semi-blocking combination of waiting for the real event (e.g. data was sent on a serial channel) and asking a new internal timer module if any other protothread is un-blocking and we need to go there. I find it a very interesting puzzle to solve...
              – Marcel
              Nov 21 at 11:12












            • also @Marcel: I have never used FreeRTOS but glancing over the documentation it looks like they implemented exactly the ProtoThreads functionality - they termed it Coroutines there. Maybe the mapping is close to 1:1
              – Vroomfondel
              Nov 21 at 13:31










            • @Doug Currie Oh thats a missunderstanding. The legacy firmware use not based on FreeRTOS Coroutines / protothreads. I used directly Adam Dunkels protothread implementation. Its just under 50 lines of C headers. Nothing more. I won't port that to FreeRTOS.
              – Marcel
              Nov 22 at 9:35


















            • Thats exactly the kind of way I want to go. Please see my update in the question. You seam to have seen such stuff already. Any further hints for me?
              – Marcel
              Nov 21 at 10:49










            • your second point is a big issue on my list. My current idea is to convert most or all protothread code behind the scenes into a semi-blocking combination of waiting for the real event (e.g. data was sent on a serial channel) and asking a new internal timer module if any other protothread is un-blocking and we need to go there. I find it a very interesting puzzle to solve...
              – Marcel
              Nov 21 at 11:12












            • also @Marcel: I have never used FreeRTOS but glancing over the documentation it looks like they implemented exactly the ProtoThreads functionality - they termed it Coroutines there. Maybe the mapping is close to 1:1
              – Vroomfondel
              Nov 21 at 13:31










            • @Doug Currie Oh thats a missunderstanding. The legacy firmware use not based on FreeRTOS Coroutines / protothreads. I used directly Adam Dunkels protothread implementation. Its just under 50 lines of C headers. Nothing more. I won't port that to FreeRTOS.
              – Marcel
              Nov 22 at 9:35
















            Thats exactly the kind of way I want to go. Please see my update in the question. You seam to have seen such stuff already. Any further hints for me?
            – Marcel
            Nov 21 at 10:49




            Thats exactly the kind of way I want to go. Please see my update in the question. You seam to have seen such stuff already. Any further hints for me?
            – Marcel
            Nov 21 at 10:49












            your second point is a big issue on my list. My current idea is to convert most or all protothread code behind the scenes into a semi-blocking combination of waiting for the real event (e.g. data was sent on a serial channel) and asking a new internal timer module if any other protothread is un-blocking and we need to go there. I find it a very interesting puzzle to solve...
            – Marcel
            Nov 21 at 11:12






            your second point is a big issue on my list. My current idea is to convert most or all protothread code behind the scenes into a semi-blocking combination of waiting for the real event (e.g. data was sent on a serial channel) and asking a new internal timer module if any other protothread is un-blocking and we need to go there. I find it a very interesting puzzle to solve...
            – Marcel
            Nov 21 at 11:12














            also @Marcel: I have never used FreeRTOS but glancing over the documentation it looks like they implemented exactly the ProtoThreads functionality - they termed it Coroutines there. Maybe the mapping is close to 1:1
            – Vroomfondel
            Nov 21 at 13:31




            also @Marcel: I have never used FreeRTOS but glancing over the documentation it looks like they implemented exactly the ProtoThreads functionality - they termed it Coroutines there. Maybe the mapping is close to 1:1
            – Vroomfondel
            Nov 21 at 13:31












            @Doug Currie Oh thats a missunderstanding. The legacy firmware use not based on FreeRTOS Coroutines / protothreads. I used directly Adam Dunkels protothread implementation. Its just under 50 lines of C headers. Nothing more. I won't port that to FreeRTOS.
            – Marcel
            Nov 22 at 9:35




            @Doug Currie Oh thats a missunderstanding. The legacy firmware use not based on FreeRTOS Coroutines / protothreads. I used directly Adam Dunkels protothread implementation. Its just under 50 lines of C headers. Nothing more. I won't port that to FreeRTOS.
            – Marcel
            Nov 22 at 9:35


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53390809%2fhow-to-best-convert-legacy-polling-embedded-firmware-architecture-into-an-event%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Wiesbaden

            Marschland

            Dieringhausen