diff --git a/examples/chapter11_07/chapter11_07.vcxproj b/examples/chapter11_07/chapter11_07.vcxproj index 2dd79908b..6113d9db8 100644 --- a/examples/chapter11_07/chapter11_07.vcxproj +++ b/examples/chapter11_07/chapter11_07.vcxproj @@ -382,6 +382,7 @@ + true true diff --git a/examples/chapter11_07/chapter11_07.vcxproj.filters b/examples/chapter11_07/chapter11_07.vcxproj.filters index 6047f7184..2607667c8 100644 --- a/examples/chapter11_07/chapter11_07.vcxproj.filters +++ b/examples/chapter11_07/chapter11_07.vcxproj.filters @@ -100,6 +100,9 @@ {b584eda9-37f6-4508-86cd-73f8a70a246c} + + {ff14b2e1-f38c-4081-8657-97e5320e1911} + @@ -571,5 +574,8 @@ src\util\STL + + _doc + \ No newline at end of file diff --git a/examples/chapter11_07/images/scope11_07.jpg b/examples/chapter11_07/images/scope11_07.jpg index 3530fbd8c..110589a81 100644 Binary files a/examples/chapter11_07/images/scope11_07.jpg and b/examples/chapter11_07/images/scope11_07.jpg differ diff --git a/examples/chapter11_07/readme.md b/examples/chapter11_07/readme.md index 233b59a09..fe8e8b79f 100644 --- a/examples/chapter11_07/readme.md +++ b/examples/chapter11_07/readme.md @@ -9,16 +9,17 @@ that features a main task and a low-priority background task. This example features two preemptive tasks within a multitasking envoronment. The application task supports the _blinky_ functionality with LED on/off each 1s. -The application task has higher priority and also yields every $70~\text{ms}$. +The application task has higher priority and also yields every $125~\text{ms}$. The second task is a background task. It runs continuously, without cooperative yield. The background task, however, by virtue of having lower task priority will be interrupted by the higher priority application task. The background task -toggles a second LED each $50~\text{ms}$. +toggles a second LED on `portd.3` every $50~\text{ms}$ +resulting in a frequency of approximately $10~\text{Hz}$. These days there are numerous choices available when selecting OS-es and/or multitasking schedulers for embedded systems. The selection -ranges from either commercially available, free-ware or self-written options. +includes a variety of either commercially available, free-ware or self-written options. In this particular expression of Example Chapter11_07, we select [FreeRTOS](https://www.freertos.org). @@ -34,18 +35,21 @@ The tasks are summarized in the code snippet below. extern "C" void app_led_task_background(void*) { - // This background task runs perpetually without pause, break or yield. - // This task has lowest priority and will be interrupted by the task - // having higher priority. + // This background task runs perpetually without pause, break or yield + // This task has lowest priority and will be interrupted by any other + // task having higher priority, such as the LED 1/2 Hz toggle task + // (i.e., app_led_timer_toggle_led0). for(;;) { while((!app_led_timer_background.timeout())) { - ; + mcal::cpu::nop(); } - app_led_timer_background.start_interval(app_led_timer_type::milliseconds(50U)); + app_led_timer_background.start_interval(app_led_timer_type::milliseconds(app_led_tick_type { UINT8_C(50) })); + + // Toggle led1 every 50ms. mcal::led::led1().toggle(); } @@ -54,22 +58,34 @@ void app_led_task_background(void*) extern "C" void app_led_task_toggle_led0(void*) { - // This application task is intended to yield every 70 ms. It has higher - // priority than the background task. This task will, in fact, preemptively - // interrupt the lower-priority background task. + // When using FreeRTOS, this task has higher priority than + // the background task. Due to its higher task-priority, + // this task is, in fact, intended to preemptively interrupt + // the lower-priority background task. + + // If using the simulated host (such as _MSC_VER or GCC on x86_64), + // FreeRTOS is not used, but rather the C++ and + // libraries are used for simulated task scheduling. The + // library does not use adjustable priorities in this case, but the + // thread scheduler supports preemptive scheduling and emulates + // the desired timing quite well. for(;;) { mcal::wdg::secure::trigger(); + // Toggle led0 every 1s. + if(app_led_timer_toggle_led0.timeout()) { - app_led_timer_toggle_led0.start_interval(app_led_timer_type::seconds(1U)); + app_led_timer_toggle_led0.start_interval(app_led_timer_type::seconds(app_led_tick_type { UINT8_C(1) })); mcal::led::led0().toggle(); } - OS_TASK_WAIT_YIELD(OS_TASK_MSEC(70U)); + // This application task is programmed to yield every 125ms. + + OS_TASK_WAIT_YIELD(TickType_t { UINT8_C(125) }); } } ``` @@ -80,12 +96,16 @@ The port for the ATmega328P target can be found in [port.cpp](./src/os/FreeRTOS/Source/portable/GCC-ATMega328/port.cpp). This OS-portable part has been modified for this example via changes including switching from a C to a C++ file, -cleaning up spaces, tabs and alignment of typing, -OS tick using `timer1` compare-match-a to generate -a tick interrupt at $100~\text{Hz}$ (every 10ms), -using an undecorated ISR handle name `__vector_11`, -and using C++ register template access to setup the timer -for the OS tick. +cleaning up spaces, tabs and alignment of typing. +The OS tick uses `compare-match-a` from `timer1` to generate +a tick interrupt at $100~\text{Hz}$ (i.e., approximately every $10~\text{ms}$) +using an undecorated ISR handle named `__vector_11`. + +If using the simulated host (such as `_MSC_VER` or GCC on `x86_64`), +FreeRTOS is not used, but rather the C++ `` and `` libraries +are used for simulated task scheduling. The `` library +does not use adjustable priorities in this case, but the thread scheduler +supports preemptive scheduling and emulates the desired timing quite well. ## Hardware Setup @@ -97,12 +117,7 @@ The background $10~\text{Hz}$ toggle pin can be found on `portd.3`. ![](./images/board11_07.jpg) The oscilloscope image below captures the toggle cycle -of the LED in the background task. -The background task, although programmed to toggle its -pin every $50~\text{ms}$ does have slight, occasional variations -in its toggle cycle. These are due to task jitter -and the fact that the background task is interrupted -by the call cycle and subsequent execution of the -application task (which has higher priority). +of the LED in the background task at a frequency +of approximately $10~\text{Hz}$ ![](./images/scope11_07.jpg) diff --git a/examples/chapter11_07/src/app/led/app_led.cpp b/examples/chapter11_07/src/app/led/app_led.cpp index 81081c26c..b3b5fe748 100644 --- a/examples/chapter11_07/src/app/led/app_led.cpp +++ b/examples/chapter11_07/src/app/led/app_led.cpp @@ -52,11 +52,12 @@ void app_led_task_toggle_led0(void*) // this task is, in fact, intended to preemptively interrupt // the lower-priority background task. - // If using the host (such as _MSC_VER or GCC on x86_64), - // FreeRTOS is not used, but rather the C++ library - // is used for simulated task scheduling. These do not have - // priorities, but the thread scheduler supports preemptive - // scheduling and emulates the desired timing quite well. + // If using the simulated host (such as _MSC_VER or GCC on x86_64), + // FreeRTOS is not used, but rather the C++ and + // libraries are used for simulated task scheduling. The + // library does not use adjustable priorities in this case, but the + // thread scheduler supports preemptive scheduling and emulates + // the desired timing quite well. for(;;) {