You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2016/07/06 19:55:58 UTC

[2/2] incubator-mynewt-site git commit: Added a sample lesson unit for task management. Added function defs in a table for fcb. This closes #103

Added a sample lesson unit for task management. Added function defs in a table for fcb. This closes #103


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/commit/4d3003a5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/4d3003a5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/4d3003a5

Branch: refs/heads/asf-site
Commit: 4d3003a5f2eae2c62bdefd9ee2a38eabdad65bd2
Parents: b3005c0
Author: aditihilbert <ad...@runtime.io>
Authored: Wed Jul 6 12:55:32 2016 -0700
Committer: aditihilbert <ad...@runtime.io>
Committed: Wed Jul 6 12:55:32 2016 -0700

----------------------------------------------------------------------
 develop/mkdocs/search_index.json             |  18 +++----
 develop/os/modules/fcb/fcb/index.html        |  62 +++++++++++++++++-----
 develop/os/tutorials/pics/task_lesson.png    | Bin 12445 -> 12931 bytes
 develop/os/tutorials/tasks_lesson/index.html |  36 +++++++------
 develop/sitemap.xml                          |  20 +++----
 latest/sitemap.xml                           |  20 +++----
 sitemap.xml                                  |  20 +++----
 v0_9_0/sitemap.xml                           |  20 +++----
 8 files changed, 120 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4d3003a5/develop/mkdocs/search_index.json
----------------------------------------------------------------------
diff --git a/develop/mkdocs/search_index.json b/develop/mkdocs/search_index.json
index eebbd68..3d8f1f7 100644
--- a/develop/mkdocs/search_index.json
+++ b/develop/mkdocs/search_index.json
@@ -937,7 +937,7 @@
         }, 
         {
             "location": "/os/tutorials/tasks_lesson/", 
-            "text": "Core OS Lesson: Tasks and Priority Management\n\n\nTarget Platform: Arduino M0 Pro\n (or legacy Arduino Zero or Zero Pro, but not Arduino M0)\n\n\nThis lesson is designed to teach core OS concepts and strategies encountered when building applications using Mynewt. Specifically, this lesson will cover tasks, simple multitasking, and priority management running on an Arduino M0 Pro.\n\n\nPrerequisites\n\n\nBefore starting, you should read about Mynewt in the \nIntroduction\n section and complete the \nQuickStart\n guide and the \nBlinky\n tutorial. Furthermore, it may be helpful to take a peek at the \ntask documentation\n for additional insights.\n\n\nEquipment\n\n\nYou will need the following equipment:\n\n\n\n\nArduino M0 Pro (or legacy Arduino Zero or Zero Pro, but not Arduino M0)\n\n\nComputer with Mynewt installed\n\n\nUSB to Micro USB Cable\n\n\n\n\nBuild Your Application\n\n\nTo save time, we will simply modify the Blinky app as it has the basic task struc
 ture already implemented. Follow the \nArduino Zero Blinky tutorial\n to create a new project and build your bootloader and application. Finally, build and load the application to your Arduino to verify that everything is in order. Now let\u2019s get started!\n\n\nCreate a New Task\n\n\nThe purpose of this section is to give an introduction to the important aspects of tasks and how to properly initialize them. First, let\u2019s define a second task called \nwork_task\n in main.c (located in apps/blinky/src):\n\n\nstruct\n \nos_task\n \nwork_task\n;\n\n\n\n\n\nA task is represented by the \nos_task\n  struct which will hold the task\u2019s information (name, state, priority, etc.). A task is made up of two main elements, a task function (also known as a task handler) and a task stack.\n\n\nNext, let\u2019s take a look at what is required to initialize our new task.\n\n\nTask Stack\n\n\nThe task stack is an array of type \nos_stack_t\n which holds the program stack frames. Mynewt give
 s us the ability to set the stack size for a task giving the application developer room to optimize memory usage. Since we\u2019re not short on memory, our \nblinky_stack\n and \nwork_stack\n are plenty large for the purpose of this lesson. Notice that the elements in our task stack are of type \nos_stack_t\n which are generally 32 bits, making our entire stack 1024 Bytes.\n\n\n  \n#define WORK_STACK_SIZE OS_STACK_ALIGN(256)\n\n  \nos_stack_t\n \nwork_stack\n[\nWORK_STACK_SIZE\n];\n\n\n\n\n\nNote: The \nOS_STACK_ALIGN\n macro is used to align the stack based on the hardware architecture.\n\n\nTask Function\n\n\nThe task function is essentially an infinite loop which waits for some \u201cevent\u201d to wake it up. In our Blinky app the task function, named \nblinky_task_handler()\n, is initially called when we call \nos_start()\n in \nmain()\n. In general, the task function is where the majority of work is done by a task. Let\u2019s write a task function for \nwork_task\n called \nwo
 rk_task_handler()\n:\n\n\nvoid\n\n\nwork_task_handler\n(\nvoid\n \n*arg\n)\n{\n    \nstruct\n \nos_task\n \n*t\n;\n\n    \ng_led_pin\n \n=\n \nLED_BLINK_PIN\n;\n    \nhal_gpio_init_out\n(\ng_led_pin\n, \n1\n);\n\n    \nwhile\n (\n1\n) {\n        \nt\n \n=\n \nos_sched_get_current_task\n();\n        \nassert\n(\nt-\nt_func\n \n==\n \nwork_task_handler\n);\n        \n/* Do work... */\n\n    }\n}\n\n\n\n\n\nThe task function is called when the task is initially put into the\n\nrunning\n state by the scheduler. We use an infinite loop to ensure that the task function never returns and assert that the current task\u2019s function is correct before doing any work.\n\n\nTask Priority\n\n\nAs a preemptive, multitasking RTOS, Mynewt decides which tasks to run based on which has a higher priority; the highest priority being 0 and the lowest 255. Thus, before initializing our task, we must choose a priority defined as a macro variable.\n\n\nLet\u2019s set the priority of \nwork_task\n to 0, be
 cause everyone knows that work is more important than blinking.\n\n\n  \n#define WORK_TASK_PRIO (0)\n\n\n\n\n\n\nInitialization\n\n\nTo initialize a new task we use \nos_task_init()\n which takes a number of arguments including our new task function, stack, and priority. Much like \nblinky_task\n, we\u2019re going to initialize \nwork_task\n inside \ninit_tasks\n to keep our main function clean.\n\n\nint\n\n\ninit_tasks\n(\nvoid\n)\n{\n    \n/* \u2026 */\n\n    \nos_task_init\n(\nwork_task\n, \nwork\n, \nwork_task_handler\n, \nNULL\n,\n            \nWORK_TASK_PRIO\n, \nOS_WAIT_FOREVER\n, \nwork_stack\n,\n            \nWORK_STACK_SIZE\n);\n\n    \ntasks_initialized\n \n=\n \n1\n;\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nReview\n\n\nBefore we run our new app, let\u2019s review what we need in order to create a task:\n\n\n1)\n   Define a new task, task stack, and priority\n\n\n/* My Task */\n\n\nos_task\n \nmytask\n\n\n/* My Task Stack */\n\n\n#define MYTASK_STACK_SIZE OS_STACK_ALIGN(256)\
 n\n\nos_stack_t\n \nmytask_stack\n[\nMYTASK_STACK_SIZE\n];\n\n/* My Task Priority */\n\n\n#define MYTASK_PRIO (0)\n\n\n\n\n\n\n2)\n Define task function\n\n\nvoid\n \n\nmytask_handler\n(\nvoid\n \n*arg\n)\n{\n    \n/* ... */\n\n}\n\n\n\n\n\n3)\n Initialize task before calling \nos_start()\n\n\nos_task_init\n(\nmytask\n, \nmytask\n, \nmytask_handler\n, \nNULL\n, \n            \nMYTASK_PRIO\n, \nOS_WAIT_FOREVER\n, \nmytask_stack\n,\n            \nMYTASK_STACK_SIZE\n);\n\n\n\n\n\nAnd that\u2019s it! Run your application and \u2026 \nwait, why doesn't our LED blink anymore?\n\n\nTask Priority, Preempting, and Context Switching\n\n\nA preemptive RTOS is one in which a higher priority task that is \nready to run\n will preempt (i.e. take the place of) the lower priority task which is \nrunning\n. When a lower priority task is preempted by a higher priority task, the lower priority task\u2019s context data (stack pointer, registers, etc.) is saved and the new task is switched in.\n\n\nIn o
 ur example, \nwork_task\n has a higher priority than \nblinky_task\n and, because it is never put into a \nsleep\n state, holds the processor focus on its context. Let\u2019s give \nwork_task\n a delay and some simulated work to keep it busy. Because the delay is measured in os ticks, the actual number of ticks per second is dependent on the board. Therefore, we multiply \nOS_TICKS_PER_SEC\n, which is defined in the MCU, by the number of seconds we wish to delay.\n\n\nvoid\n\n\nwork_task_handler\n(\nvoid\n \n*arg\n)\n{\n    \nstruct\n \nos_task\n \n*t\n;\n\n    \ng_led_pin\n \n=\n \nLED_BLINK_PIN\n;\n    \nhal_gpio_init_out\n(\ng_led_pin\n, \n1\n);\n\n    \nwhile\n (\n1\n) {\n        \nt\n \n=\n \nos_sched_get_current_t\n:ask\n();\n        \nassert\n(\nt-\nt_func\n \n==\n \nwork_task_handler\n);\n        \n/* Do work... */\n\n        \nint\n \ni\n;\n        \nfor\n(\ni\n \n=\n \n0\n; \ni\n \n \n1000000\n; \n++i\n) {\n            \n//simulate doing a noticeable amount of work\n\n    
         \nhal_gpio_set\n(\ng_led_pin\n);\n        }\n        \nos_time_delay\n(\n3\n*OS_TICKS_PER_SECOND\n);\n    }\n}\n\n\n\n\n\nIn order to notice the LED changing, modify the time delay in \nblinky_task_handler()\n to blink at a higher frequency.\n\n\nos_time_delay\n(\n100\n);\n\n\n\n\n\nBefore we run the app, let\u2019s predict the behavior. With the newest\nadditions to \nwork_task_handler()\n, our first action will be to sleep for three seconds. This will allow \nblinky_task\n to take over the CPU and blink to its heart\u2019s content. After three seconds, \nwork_task\n will wake up and be made \nready to run\n, causing it to preempt \nblinky_task\n. The LED will then remain lit for a short period while \nwork_task\n loops, then blink again for another three seconds while \nwork_task\n sleeps. \n\n\nViola, you should see that our prediction was correct! What would happen when both priorities are the same? Try it out for yourself!\n\n\nPriority Management Considerations\n\n\nWh
 en projects grow in scope, from blinking LEDs into more sophisticated applications, the number of tasks needed increases alongside complexity. It remains important, then, that each of our tasks is capable of doing its work within a reasonable amount of time.\n\n\nSome tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore, the Shell task should be given a high priority. On the other hand, tasks which may be communicating over a network, or processing data, should be given a low priority in order to not hog the CPU.\n\n\nThe diagram below showcases the different scheduling patterns we. would expect from swapping blinky and work tasks priorities.\n\n\n\n\nIn the second case where \nblinky_task\n has a higher priority, the \u201cwork\u201d done by \nwork_task\n would be executed during the millisecond delays in \nblinky_task\n, saving us idle time compared to the first case.\n\n\nComparing Priority Strategies\n\n\nInstead of stepping through
  a bunch of changes to our blinky app, clone my task lesson application from github and copy an existing target.\n\n\nChange directory into apps and clone the repository to get our new\nfiles:\n\n\n$ cd apps\n$ git clone https://github.com/bgiori/mynewt_tasks_lesson.git\n\n\n\n\n\nChange directory back to your project root and copy  the arduino_blinky target to a new target called task_tgt.\n\n\n$\n \nnewt\n \ntarget\n \ncopy\n \narduino_blinky\n \ntask_tgt\n\n\n\n\n\n\nSet a new app location.\n\n\n$\n \nnewt\n \ntarget\n \nset\n \ntask_tgt\n \napp=apps/mynewt_tasks_lesson\n\n\n\n\n\n\nNow let\u2019s take a look at our new code. First, notice that we have abandoned blinking, instead choosing to use the \nconsole\n and \nshell\n to follow our tasks through execution.\n\n\nAdditionally, we have a number of different tasks:\n\n\n\n\n\n\nTask A\n (\na_task\n):\n\n\n\n\nPriority\n: 3 \u2192 2\n\n\nDescription\n: Task A is supposed to represent a task which frequently does a small amount 
 of work, such as one which rapidly polls a sensor for data. Much like \nblinky_task\n, Task A will loop 10,000 times then wait 1 millisecond. Priority is changed by \ntimer_task\n after the first simulation.\n\n\n\n\n\n\n\n\nTask B\n (\nb_task\n):\n\n\n\n\nPriority\n: 2 \u2192 3\n\n\nDescription\n: Task B is supposed to represent a task which does a large amount of work relatively infrequently, such as one which sends/receives data from the cloud. Like work_task, Task B will loop 1,000,000 times then wait 3 seconds. Priority is changed by timer_task after the first simulation.\n\n\n\n\n\n\n\n\nTimer Task\n (\ntimer_task\n):\n\n\n\n\nPriority\n: 1\n\n\nDescription\n: With default settings, Timer Task will wait 20 seconds then print the first simulations data for Task A and B. Timer task will then swap A and B\u2019s priorities and restart the simulation. After the second simulation, timer will again print simulation data then compare the two and calculate a final speedup (simulation2
  / simulation1).\n\n\n\n\n\n\n\n\nShell Task\n:\n\n\n\n\nPriority\n: 0\n\n\nDescription\n: Task used by Shell behind the scenes to communicate with the serial port.\n\n\n\n\n\n\n\n\nConnecting to the Serial Console\n\n\nBefore running our new app, we must first connect to the serial console. First make sure the mynewt_arduino_zero repository is set to the develop branch. (Remove once changes have been moved to master). \n\n\n$ cd repos/mynewt_arduino_zero\n$ git checkout develop\n\n\n\n\n\nOpen a new terminal window and list your serial connections to find our Arduino.\n\n\n$\n \nls\n \n/dev/tty\n.\n*\n\n\n\n/dev/tty\n.\nBluetooth-Incoming-Port\n \n/dev/tty\n.\nusbmodem14132\n\n\n\n\n\n\nIn the same window, connect to the serial port using a serial communication program. In this case I\u2019ll be using mincom as it can scroll through output.\n\n\n$\n \nminicom\n \n-D\n \n/dev/tty\n.\nusbmodem14132\n \n-b\n \n115200\n\n\n\n\n\n\nIf you see minicom welcome you, you\u2019re ready to mo
 ve on!\n\n\nOutput Analysis\n\n\nRun our new target, task_sim, and you should see an output similar to this:\n\n\nStarting First Simulation...\n1:     Task B: 0% \n78:     Task B: 1% \n155:     Task B: 2% \n257:     Task B: 3% \n359:     Task B: 4% \n461:     Task B: 5% \n\n\nsnip\n\n\n========== Timer Expired ==========\n\n \n Task A \n\n  Priority: 3\n  Loop count: 162849\n  Cycle count: 16.28\n  Run time: 1.40 sec\n\n \n Task B \n\n  Priority: 2\n  Loop count: 1345852\n  Cycle count: 1.34\n  Run time: 17.0 sec\n\n Total loops: 1508709\n\n20023:   Switching priorities and restarting...\n20111:   Task A looped\n20113:     Task B: 0% \n20191:     Task B: 1% \n20297:   Task A looped\n20356:     Task B: 2% \n20483:   Task A looped\n20545:     Task B: 3% \n20669:   Task A looped\n20734:     Task B: 4% \n20855:   Task A looped\n20923:     Task B: 5% \n\n\nsnip\n\n\n========== Timer Expired ==========\n\n \n Task A \n\n  Priority: 2\n  Loop count: 1080000\n  Cycle count: 108.0\n  Run tim
 e: 9.28 sec\n\n \n Task B \n\n  Priority: 3\n  Loop count: 830356\n  Cycle count: 0.83\n  Run time: 10.72 sec\n\n Total loops: 1910404\n\n40058:\n\n Final Speedup (Sim2 / Sim1): 1.26\n\n\n\n\n\nThe console output reaffirms our previous prediction and makes both the scheduling differences and subsequent efficiency boost far more apparent. Let\u2019s take a look at scheduling differences before we delve into efficiency.\n\n\nIn the first case, where Task B\u2019s priority is higher than that of Task A, we see A get starved by Task B\u2019s long execution time. \nStarvation\n occurs when one task hogs the processor, essentially \u201cstarving\u201d other tasks which also need to run. At the end of the first 20 second simulation period, Task A has only run for 1.4 seconds compared to task B\u2019s 17 second running time \u2013 ouch. As explained before, processes which are expected to run for long periods of time (e.g. network communication, data processing) should be given higher prior
 ities in order to combat starvation.\n\n\nIn the second simulation with priorities swapped, we can see Task B only running during the millisecond delays when Task A is \nsleeping\n. Although having Task B only run during these delays slows its execution time, we benefit from un-starving Task A and using the processor at a higher efficiency.\n\n\nThe bottom line speedup gives us an immediate and clear indication that we have improved our ability to process work (i.e throughput). In our second run, we processed an additional 400,000 loop iterations, equating to a 26% increase in efficiency. On a standard multi-core processor found in every modern PC, a 1.26 speedup would be an ok result to adding multithreading capabilities to a serial program. However, we accomplished this by simply setting priorities on a single core processor \u2013 not bad!\n\n\nNOTE: Usually the the term \u201cspeedup\u201d is used within a parallel programming context and refers to the change in execution time b
 etween a serial and parallel program executing over the same problem. In this case we\u2019re using the term loosely to illustrate the priority change\u2019s effect on scheduling and throughput in our specific context.\n\n\nEfficiency Isn\u2019t Everything\n\n\nUsing the processor during every OS tick isn\u2019t always the best course of action. If we modify Task A\u2019s delay to a tenth of a millisecond and turn off the console output, we can boost our speedup to 1.44. This, however, reduces our ability to process work from Task B who ends up only completing 18% of its work cycle after the second simulation. That would mean, at that rate, Task B would take over a minute to finish one cycle.\n\n\nFeel free to play around with the testing parameters to study the different changes yourself!\n\n\nConclusion\n\n\nMoving forward, tasks are just the tip of the iceberg. The \nscheduler\n, \nevent queues\n, \nsemaphores\n, and \nmutexes\n also add to tasks functionality, increasing our abi
 lity as the developer to control greater numbers of tasks more intricately. For example, when we switch the tasks priority, we have to tell the scheduler that our tasks priorities have changed, allowing us us to use priorities dynamically. When running multiple tasks, logging through either the built-in \nLogs\n module (not covered in this lesson) or through the serial console/shell can be very useful for debugging your application. In the end, the way you manage your tasks depends on the context of your application. You should assign priorities based on execution time, urgency, and frequency, among other things.\n\n\nKeep blinking and happy hacking!", 
+            "text": "Core OS Lesson: Tasks and Priority Management\n\n\nTarget Platform: Arduino M0 Pro\n (or legacy Arduino Zero or Zero Pro, but not Arduino M0)\n\n\nThis lesson is designed to teach core OS concepts and strategies encountered when building applications using Mynewt. Specifically, this lesson will cover tasks, simple multitasking, and priority management running on an Arduino M0 Pro.\n\n\nPrerequisites\n\n\nBefore starting, you should read about Mynewt in the \nIntroduction\n section and complete the \nQuickStart\n guide and the \nBlinky\n tutorial. Furthermore, it may be helpful to take a peek at the \ntask documentation\n for additional insights.\n\n\nEquipment\n\n\nYou will need the following equipment:\n\n\n\n\nArduino M0 Pro (or legacy Arduino Zero or Zero Pro, but not Arduino M0)\n\n\nComputer with Mynewt installed\n\n\nUSB to Micro USB Cable\n\n\n\n\nBuild Your Application\n\n\nTo save time, we will simply modify the Blinky app as it has the basic task struc
 ture already implemented. Follow the \nArduino Zero Blinky tutorial\n to create a new project and build your bootloader and application. Finally, build and load the application to your Arduino to verify that everything is in order. Now let\u2019s get started!\n\n\nCreate a New Task\n\n\nThe purpose of this section is to give an introduction to the important aspects of tasks and how to properly initialize them. First, let\u2019s define a second task called \nwork_task\n in main.c (located in apps/blinky/src):\n\n\nstruct\n \nos_task\n \nwork_task\n;\n\n\n\n\n\nA task is represented by the \nos_task\n  struct which will hold the task\u2019s information (name, state, priority, etc.). A task is made up of two main elements, a task function (also known as a task handler) and a task stack.\n\n\nNext, let\u2019s take a look at what is required to initialize our new task.\n\n\nTask Stack\n\n\nThe task stack is an array of type \nos_stack_t\n which holds the program stack frames. Mynewt give
 s us the ability to set the stack size for a task giving the application developer room to optimize memory usage. Since we\u2019re not short on memory, our \nblinky_stack\n and \nwork_stack\n are plenty large for the purpose of this lesson. Notice that the elements in our task stack are of type \nos_stack_t\n which are generally 32 bits, making our entire stack 1024 Bytes.\n\n\n  \n#define WORK_STACK_SIZE OS_STACK_ALIGN(256)\n\n  \nos_stack_t\n \nwork_stack\n[\nWORK_STACK_SIZE\n];\n\n\n\n\n\nNote: The \nOS_STACK_ALIGN\n macro is used to align the stack based on the hardware architecture.\n\n\nTask Function\n\n\nThe task function is essentially an infinite loop which waits for some \u201cevent\u201d to wake it up. In our Blinky app the task function, named \nblinky_task_handler()\n, is initially called when we call \nos_start()\n in \nmain()\n. In general, the task function is where the majority of work is done by a task. Let\u2019s write a task function for \nwork_task\n called \nwo
 rk_task_handler()\n:\n\n\nvoid\n\n\nwork_task_handler\n(\nvoid\n \n*arg\n)\n{\n    \nstruct\n \nos_task\n \n*t\n;\n\n    \ng_led_pin\n \n=\n \nLED_BLINK_PIN\n;\n    \nhal_gpio_init_out\n(\ng_led_pin\n, \n1\n);\n\n    \nwhile\n (\n1\n) {\n        \nt\n \n=\n \nos_sched_get_current_task\n();\n        \nassert\n(\nt-\nt_func\n \n==\n \nwork_task_handler\n);\n        \n/* Do work... */\n\n    }\n}\n\n\n\n\n\nThe task function is called when the task is initially put into the \nrunning\n state by the scheduler. We use an infinite loop to ensure that the task function never returns. Our assertion that the current task's handler is the same as our task handler is for illustration purposes only and does not need to be in most task functions.\n\n\nTask Priority\n\n\nAs a preemptive, multitasking RTOS, Mynewt decides which tasks to run based on which has a higher priority; the highest priority being 0 and the lowest 255. Thus, before initializing our task, we must choose a priority defined as
  a macro variable.\n\n\nLet\u2019s set the priority of \nwork_task\n to 0, because everyone knows that work is more important than blinking.\n\n\n  \n#define WORK_TASK_PRIO (0)\n\n\n\n\n\n\nInitialization\n\n\nTo initialize a new task we use \nos_task_init()\n which takes a number of arguments including our new task function, stack, and priority. Much like \nblinky_task\n, we\u2019re going to initialize \nwork_task\n inside \ninit_tasks\n to keep our main function clean.\n\n\nint\n\n\ninit_tasks\n(\nvoid\n)\n{\n    \n/* \u2026 */\n\n    \nos_task_init\n(\nwork_task\n, \nwork\n, \nwork_task_handler\n, \nNULL\n,\n            \nWORK_TASK_PRIO\n, \nOS_WAIT_FOREVER\n, \nwork_stack\n,\n            \nWORK_STACK_SIZE\n);\n\n    \ntasks_initialized\n \n=\n \n1\n;\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nAnd that\u2019s it! Now run your application using the newt run command.\n\n\n$ newt run arduino_blinky 0.0.0\n\n\n\n\n\nWhen GDB appears press C then Enter to continue and \u2026 \nwait, why doe
 sn't our LED blink anymore?\n\n\nReview\n\n\nBefore we run our new app, let\u2019s review what we need in order to create a task. This is a general case for a new task called mytask:\n\n\n1)\n   Define a new task, task stack, and priority:\n\n\n/* My Task */\n\n\nstruct\n \nos_task\n \nmytask\n\n\n/* My Task Stack */\n\n\n#define MYTASK_STACK_SIZE OS_STACK_ALIGN(256)\n\n\nos_stack_t\n \nmytask_stack\n[\nMYTASK_STACK_SIZE\n];\n\n/* My Task Priority */\n\n\n#define MYTASK_PRIO (0)\n\n\n\n\n\n\n2)\n Define task function:\n\n\nvoid\n \n\nmytask_handler\n(\nvoid\n \n*arg\n)\n{\n  \nwhile\n (\n1\n) {\n      \n/* ... */\n\n  }\n}\n\n\n\n\n\n3)\n Initialize task before calling \nos_start()\n:\n\n\nos_task_init\n(\nmytask\n, \nmytask\n, \nmytask_handler\n, \nNULL\n, \n            \nMYTASK_PRIO\n, \nOS_WAIT_FOREVER\n, \nmytask_stack\n,\n            \nMYTASK_STACK_SIZE\n);\n\n\n\n\n\nTask Priority, Preempting, and Context Switching\n\n\nA preemptive RTOS is one in which a higher priority task 
 that is \nready to run\n will preempt (i.e. take the place of) the lower priority task which is \nrunning\n. When a lower priority task is preempted by a higher priority task, the lower priority task\u2019s context data (stack pointer, registers, etc.) is saved and the new task is switched in.\n\n\nIn our example, \nwork_task\n has a higher priority than \nblinky_task\n and, because it is never put into a \nsleep\n state, holds the processor focus on its context. Let\u2019s give \nwork_task\n a delay and some simulated work to keep it busy. Because the delay is measured in os ticks, the actual number of ticks per second is dependent on the board. Therefore, we multiply \nOS_TICKS_PER_SEC\n, which is defined in the MCU, by the number of seconds we wish to delay.\n\n\nvoid\n\n\nwork_task_handler\n(\nvoid\n \n*arg\n)\n{\n    \nstruct\n \nos_task\n \n*t\n;\n\n    \ng_led_pin\n \n=\n \nLED_BLINK_PIN\n;\n    \nhal_gpio_init_out\n(\ng_led_pin\n, \n1\n);\n\n    \nwhile\n (\n1\n) {\n        
 \nt\n \n=\n \nos_sched_get_current_t\n:ask\n();\n        \nassert\n(\nt-\nt_func\n \n==\n \nwork_task_handler\n);\n        \n/* Do work... */\n\n        \nint\n \ni\n;\n        \nfor\n(\ni\n \n=\n \n0\n; \ni\n \n \n1000000\n; \n++i\n) {\n            \n/* Simulate doing a noticeable amount of work */\n\n            \nhal_gpio_set\n(\ng_led_pin\n);\n        }\n        \nos_time_delay\n(\n3\n*OS_TICKS_PER_SECOND\n);\n    }\n}\n\n\n\n\n\nIn order to notice the LED changing, modify the time delay in \nblinky_task_handler()\n to blink at a higher frequency.\n\n\nos_time_delay\n(\nOS_TICKS_PER_SEC/\n10\n);\n\n\n\n\n\nBefore we run the app, let\u2019s predict the behavior. With the newest additions to \nwork_task_handler()\n, our first action will be to sleep for three seconds. This will allow \nblinky_task\n to take over the CPU and blink to its heart\u2019s content. After three seconds, \nwork_task\n will wake up and be made \nready to run\n, causing it to preempt \nblinky_task\n. The LED
  will then remain lit for a short period while \nwork_task\n loops, then blink again for another three seconds while \nwork_task\n sleeps. \n\n\nVoila, you should see that our prediction was correct! \n\n\nPriority Management Considerations\n\n\nWhen projects grow in scope, from blinking LEDs into more sophisticated applications, the number of tasks needed increases alongside complexity. It remains important, then, that each of our tasks is capable of doing its work within a reasonable amount of time.\n\n\nSome tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore, the Shell task should be given a high priority. On the other hand, tasks which may be communicating over a network, or processing data, should be given a low priority in order to not hog the CPU.\n\n\nThe diagram below showcases the different scheduling patterns we. would expect from swapping blinky and work tasks priorities.\n\n\n\n\nIn the second case where \nblinky_task\n h
 as a higher priority, the \u201cwork\u201d done by \nwork_task\n would be executed during the millisecond delays in \nblinky_task\n, saving us idle time compared to the first case.\n\n\nNote:\n Defining the same priority for two tasks leads to somewhat undefined behavior and should be avoided.\n\n\nComparing Priority Strategies\n\n\nInstead of stepping through a bunch of changes to our blinky app, clone my task lesson application from github and copy an existing target.\n\n\nChange directory into apps and clone the repository to get our new\nfiles:\n\n\n$ cd apps\n$ git clone https://github.com/bgiori/mynewt_tasks_lesson.git\n\n\n\n\n\nChange directory back to your project root and copy  the arduino_blinky target to a new target called task_tgt.\n\n\n$\n \nnewt\n \ntarget\n \ncopy\n \narduino_blinky\n \ntask_tgt\n\n\n\n\n\n\nSet a new app location.\n\n\n$\n \nnewt\n \ntarget\n \nset\n \ntask_tgt\n \napp=apps/mynewt_tasks_lesson\n\n\n\n\n\n\nNow let\u2019s take a look at our new code
 . First, notice that we have abandoned blinking, instead choosing to use the \nconsole\n and \nshell\n to follow our tasks through execution.\n\n\nAdditionally, we have a number of different tasks:\n\n\n\n\n\n\nTask A\n (\na_task\n):\n\n\n\n\nPriority\n: 3 \u2192 2\n\n\nDescription\n: Task A is supposed to represent a task which frequently does a small amount of work, such as one which rapidly polls a sensor for data. Much like \nblinky_task\n, Task A will loop 10,000 times then wait 1 millisecond. Priority is changed by \ntimer_task\n after the first simulation.\n\n\n\n\n\n\n\n\nTask B\n (\nb_task\n):\n\n\n\n\nPriority\n: 2 \u2192 3\n\n\nDescription\n: Task B is supposed to represent a task which does a large amount of work relatively infrequently, such as one which sends/receives data from the cloud. Like work_task, Task B will loop 1,000,000 times then wait 3 seconds. Priority is changed by timer_task after the first simulation.\n\n\n\n\n\n\n\n\nTimer Task\n (\ntimer_task\n):\n\n
 \n\n\nPriority\n: 1\n\n\nDescription\n: With default settings, Timer Task will wait 20 seconds then print the first simulations data for Task A and B. Timer task will then swap A and B\u2019s priorities and restart the simulation. After the second simulation, timer will again print simulation data then compare the two and calculate a final speedup (simulation2 / simulation1).\n\n\n\n\n\n\n\n\nShell Task\n:\n\n\n\n\nPriority\n: 0\n\n\nDescription\n: Task used by Shell behind the scenes to communicate with the serial port.\n\n\n\n\n\n\n\n\nConnecting to the Serial Console\n\n\nBefore running our new app, we must first connect to the serial console. First make sure the mynewt_arduino_zero repository is set to the develop branch. (Remove once changes have been moved to master). \n\n\n$ cd repos/mynewt_arduino_zero\n$ git checkout develop\n\n\n\n\n\nOpen a new terminal window and list your serial connections to find our Arduino.\n\n\n$\n \nls\n \n/dev/tty\n.\n*\n\n\n\n/dev/tty\n.\nBlueto
 oth-Incoming-Port\n \n/dev/tty\n.\nusbmodem14132\n\n\n\n\n\n\nIn the same window, connect to the serial port using a serial communication program. In this case I\u2019ll be using mincom as it can scroll through output.\n\n\n$\n \nminicom\n \n-D\n \n/dev/tty\n.\nusbmodem14132\n \n-b\n \n115200\n\n\n\n\n\n\nIf you see minicom welcome you, you\u2019re ready to move on!\n\n\nOutput Analysis\n\n\nRun our new target, task_tgt, and you should see an output similar to this:\n\n\nStarting First Simulation...\n1:     Task B: 0% \n78:     Task B: 1% \n155:     Task B: 2% \n257:     Task B: 3% \n359:     Task B: 4% \n461:     Task B: 5% \n\n\nsnip\n\n\n========== Timer Expired ==========\n\n \n Task A \n\n  Priority: 3\n  Loop count: 162849\n  Cycle count: 16.28\n  Run time: 1.40 sec\n\n \n Task B \n\n  Priority: 2\n  Loop count: 1345852\n  Cycle count: 1.34\n  Run time: 17.0 sec\n\n Total loops: 1508709\n\n20023:   Switching priorities and restarting...\n20111:   Task A looped\n20113:     Task
  B: 0% \n20191:     Task B: 1% \n20297:   Task A looped\n20356:     Task B: 2% \n20483:   Task A looped\n20545:     Task B: 3% \n20669:   Task A looped\n20734:     Task B: 4% \n20855:   Task A looped\n20923:     Task B: 5% \n\n\nsnip\n\n\n========== Timer Expired ==========\n\n \n Task A \n\n  Priority: 2\n  Loop count: 1080000\n  Cycle count: 108.0\n  Run time: 9.28 sec\n\n \n Task B \n\n  Priority: 3\n  Loop count: 830356\n  Cycle count: 0.83\n  Run time: 10.72 sec\n\n Total loops: 1910404\n\n40058:\n\n Final Speedup (Sim2 / Sim1): 1.26\n\n\n\n\n\nThe console output reaffirms our previous prediction and makes both the scheduling differences and subsequent efficiency boost far more apparent. Let\u2019s take a look at scheduling differences before we delve into efficiency.\n\n\nIn the first case, where Task B\u2019s priority is higher than that of Task A, we see A get starved by Task B\u2019s long execution time. \nStarvation\n occurs when one task hogs the processor, essentially \u
 201cstarving\u201d other tasks which also need to run. At the end of the first 20 second simulation period, Task A has only run for 1.4 seconds compared to task B\u2019s 17 second running time \u2013 ouch. As explained before, processes which are expected to run for long periods of time (e.g. network communication, data processing) should be given higher priorities in order to combat starvation.\n\n\nIn the second simulation with priorities swapped, we can see Task B only running during the millisecond delays when Task A is \nsleeping\n. Although having Task B only run during these delays slows its execution time, we benefit from un-starving Task A and using the processor at a higher efficiency.\n\n\nThe bottom line speedup gives us an immediate and clear indication that we have improved our ability to process work (i.e throughput). In our second run, we processed an additional 400,000 loop iterations, equating to a 26% increase in efficiency. On a standard multi-core processor foun
 d in every modern PC, a 1.26 speedup would be an ok result to adding multithreading capabilities to a serial program. However, we accomplished this by simply setting priorities on a single core processor \u2013 not bad!\n\n\nNOTE: Usually the the term \u201cspeedup\u201d is used within a parallel programming context and refers to the change in execution time between a serial and parallel program executing over the same problem. In this case we\u2019re using the term loosely to illustrate the priority change\u2019s effect on scheduling and throughput in our specific context.\n\n\nEfficiency Isn\u2019t Everything\n\n\nUsing the processor during every OS tick isn\u2019t always the best course of action. If we modify Task A\u2019s delay to a tenth of a millisecond and turn off the console output, we can boost our speedup to 1.44. This, however, reduces our ability to process work from Task B who ends up only completing 18% of its work cycle after the second simulation. That would mean, 
 at that rate, Task B would take over a minute to finish one cycle.\n\n\nFeel free to play around with the testing parameters to study the different changes yourself!\n\n\nConclusion\n\n\nMoving forward, tasks are just the tip of the iceberg. The \nscheduler\n, \nevent queues\n, \nsemaphores\n, and \nmutexes\n also add to tasks functionality, increasing our ability as the developer to control greater numbers of tasks more intricately. For example, when we switch the tasks priority, we have to tell the scheduler that our tasks priorities have changed, allowing us us to use priorities dynamically. When running multiple tasks, logging through either the built-in \nLogs\n module (not covered in this lesson) or through the serial console/shell can be very useful for debugging your application. In the end, the way you manage your tasks depends on the context of your application. You should assign priorities based on execution time, urgency, and frequency, among other things.\n\n\nKeep blin
 king and happy hacking!", 
             "title": "Lesson Unit on Tasks and Priority Management"
         }, 
         {
@@ -972,7 +972,7 @@
         }, 
         {
             "location": "/os/tutorials/tasks_lesson/#task-function", 
-            "text": "The task function is essentially an infinite loop which waits for some \u201cevent\u201d to wake it up. In our Blinky app the task function, named  blinky_task_handler() , is initially called when we call  os_start()  in  main() . In general, the task function is where the majority of work is done by a task. Let\u2019s write a task function for  work_task  called  work_task_handler() :  void  work_task_handler ( void   *arg )\n{\n     struct   os_task   *t ;\n\n     g_led_pin   =   LED_BLINK_PIN ;\n     hal_gpio_init_out ( g_led_pin ,  1 );\n\n     while  ( 1 ) {\n         t   =   os_sched_get_current_task ();\n         assert ( t- t_func   ==   work_task_handler );\n         /* Do work... */ \n    }\n}  The task function is called when the task is initially put into the running  state by the scheduler. We use an infinite loop to ensure that the task function never returns and assert that the current task\u2019s function is correct before doing any work.", 
+            "text": "The task function is essentially an infinite loop which waits for some \u201cevent\u201d to wake it up. In our Blinky app the task function, named  blinky_task_handler() , is initially called when we call  os_start()  in  main() . In general, the task function is where the majority of work is done by a task. Let\u2019s write a task function for  work_task  called  work_task_handler() :  void  work_task_handler ( void   *arg )\n{\n     struct   os_task   *t ;\n\n     g_led_pin   =   LED_BLINK_PIN ;\n     hal_gpio_init_out ( g_led_pin ,  1 );\n\n     while  ( 1 ) {\n         t   =   os_sched_get_current_task ();\n         assert ( t- t_func   ==   work_task_handler );\n         /* Do work... */ \n    }\n}  The task function is called when the task is initially put into the  running  state by the scheduler. We use an infinite loop to ensure that the task function never returns. Our assertion that the current task's handler is the same as our task handler is for ill
 ustration purposes only and does not need to be in most task functions.", 
             "title": "Task Function"
         }, 
         {
@@ -982,22 +982,22 @@
         }, 
         {
             "location": "/os/tutorials/tasks_lesson/#initialization", 
-            "text": "To initialize a new task we use  os_task_init()  which takes a number of arguments including our new task function, stack, and priority. Much like  blinky_task , we\u2019re going to initialize  work_task  inside  init_tasks  to keep our main function clean.  int  init_tasks ( void )\n{\n     /* \u2026 */ \n     os_task_init ( work_task ,  work ,  work_task_handler ,  NULL ,\n             WORK_TASK_PRIO ,  OS_WAIT_FOREVER ,  work_stack ,\n             WORK_STACK_SIZE );\n\n     tasks_initialized   =   1 ;\n     return   0 ;\n}", 
+            "text": "To initialize a new task we use  os_task_init()  which takes a number of arguments including our new task function, stack, and priority. Much like  blinky_task , we\u2019re going to initialize  work_task  inside  init_tasks  to keep our main function clean.  int  init_tasks ( void )\n{\n     /* \u2026 */ \n     os_task_init ( work_task ,  work ,  work_task_handler ,  NULL ,\n             WORK_TASK_PRIO ,  OS_WAIT_FOREVER ,  work_stack ,\n             WORK_STACK_SIZE );\n\n     tasks_initialized   =   1 ;\n     return   0 ;\n}  And that\u2019s it! Now run your application using the newt run command.  $ newt run arduino_blinky 0.0.0  When GDB appears press C then Enter to continue and \u2026  wait, why doesn't our LED blink anymore?", 
             "title": "Initialization"
         }, 
         {
             "location": "/os/tutorials/tasks_lesson/#review", 
-            "text": "Before we run our new app, let\u2019s review what we need in order to create a task:  1)    Define a new task, task stack, and priority  /* My Task */  os_task   mytask  /* My Task Stack */  #define MYTASK_STACK_SIZE OS_STACK_ALIGN(256)  os_stack_t   mytask_stack [ MYTASK_STACK_SIZE ]; /* My Task Priority */  #define MYTASK_PRIO (0)   2)  Define task function  void   mytask_handler ( void   *arg )\n{\n     /* ... */ \n}  3)  Initialize task before calling  os_start()  os_task_init ( mytask ,  mytask ,  mytask_handler ,  NULL , \n             MYTASK_PRIO ,  OS_WAIT_FOREVER ,  mytask_stack ,\n             MYTASK_STACK_SIZE );  And that\u2019s it! Run your application and \u2026  wait, why doesn't our LED blink anymore?", 
+            "text": "Before we run our new app, let\u2019s review what we need in order to create a task. This is a general case for a new task called mytask:  1)    Define a new task, task stack, and priority:  /* My Task */  struct   os_task   mytask  /* My Task Stack */  #define MYTASK_STACK_SIZE OS_STACK_ALIGN(256)  os_stack_t   mytask_stack [ MYTASK_STACK_SIZE ]; /* My Task Priority */  #define MYTASK_PRIO (0)   2)  Define task function:  void   mytask_handler ( void   *arg )\n{\n   while  ( 1 ) {\n       /* ... */ \n  }\n}  3)  Initialize task before calling  os_start() :  os_task_init ( mytask ,  mytask ,  mytask_handler ,  NULL , \n             MYTASK_PRIO ,  OS_WAIT_FOREVER ,  mytask_stack ,\n             MYTASK_STACK_SIZE );", 
             "title": "Review"
         }, 
         {
             "location": "/os/tutorials/tasks_lesson/#task-priority-preempting-and-context-switching", 
-            "text": "A preemptive RTOS is one in which a higher priority task that is  ready to run  will preempt (i.e. take the place of) the lower priority task which is  running . When a lower priority task is preempted by a higher priority task, the lower priority task\u2019s context data (stack pointer, registers, etc.) is saved and the new task is switched in.  In our example,  work_task  has a higher priority than  blinky_task  and, because it is never put into a  sleep  state, holds the processor focus on its context. Let\u2019s give  work_task  a delay and some simulated work to keep it busy. Because the delay is measured in os ticks, the actual number of ticks per second is dependent on the board. Therefore, we multiply  OS_TICKS_PER_SEC , which is defined in the MCU, by the number of seconds we wish to delay.  void  work_task_handler ( void   *arg )\n{\n     struct   os_task   *t ;\n\n     g_led_pin   =   LED_BLINK_PIN ;\n     hal_gpio_init_out ( g_led_pin ,  1 );\n\n    
  while  ( 1 ) {\n         t   =   os_sched_get_current_t :ask ();\n         assert ( t- t_func   ==   work_task_handler );\n         /* Do work... */ \n         int   i ;\n         for ( i   =   0 ;  i     1000000 ;  ++i ) {\n             //simulate doing a noticeable amount of work \n             hal_gpio_set ( g_led_pin );\n        }\n         os_time_delay ( 3 *OS_TICKS_PER_SECOND );\n    }\n}  In order to notice the LED changing, modify the time delay in  blinky_task_handler()  to blink at a higher frequency.  os_time_delay ( 100 );  Before we run the app, let\u2019s predict the behavior. With the newest\nadditions to  work_task_handler() , our first action will be to sleep for three seconds. This will allow  blinky_task  to take over the CPU and blink to its heart\u2019s content. After three seconds,  work_task  will wake up and be made  ready to run , causing it to preempt  blinky_task . The LED will then remain lit for a short period while  work_task  loops, then blink again 
 for another three seconds while  work_task  sleeps.   Viola, you should see that our prediction was correct! What would happen when both priorities are the same? Try it out for yourself!", 
+            "text": "A preemptive RTOS is one in which a higher priority task that is  ready to run  will preempt (i.e. take the place of) the lower priority task which is  running . When a lower priority task is preempted by a higher priority task, the lower priority task\u2019s context data (stack pointer, registers, etc.) is saved and the new task is switched in.  In our example,  work_task  has a higher priority than  blinky_task  and, because it is never put into a  sleep  state, holds the processor focus on its context. Let\u2019s give  work_task  a delay and some simulated work to keep it busy. Because the delay is measured in os ticks, the actual number of ticks per second is dependent on the board. Therefore, we multiply  OS_TICKS_PER_SEC , which is defined in the MCU, by the number of seconds we wish to delay.  void  work_task_handler ( void   *arg )\n{\n     struct   os_task   *t ;\n\n     g_led_pin   =   LED_BLINK_PIN ;\n     hal_gpio_init_out ( g_led_pin ,  1 );\n\n    
  while  ( 1 ) {\n         t   =   os_sched_get_current_t :ask ();\n         assert ( t- t_func   ==   work_task_handler );\n         /* Do work... */ \n         int   i ;\n         for ( i   =   0 ;  i     1000000 ;  ++i ) {\n             /* Simulate doing a noticeable amount of work */ \n             hal_gpio_set ( g_led_pin );\n        }\n         os_time_delay ( 3 *OS_TICKS_PER_SECOND );\n    }\n}  In order to notice the LED changing, modify the time delay in  blinky_task_handler()  to blink at a higher frequency.  os_time_delay ( OS_TICKS_PER_SEC/ 10 );  Before we run the app, let\u2019s predict the behavior. With the newest additions to  work_task_handler() , our first action will be to sleep for three seconds. This will allow  blinky_task  to take over the CPU and blink to its heart\u2019s content. After three seconds,  work_task  will wake up and be made  ready to run , causing it to preempt  blinky_task . The LED will then remain lit for a short period while  work_task  loop
 s, then blink again for another three seconds while  work_task  sleeps.   Voila, you should see that our prediction was correct!", 
             "title": "Task Priority, Preempting, and Context Switching"
         }, 
         {
             "location": "/os/tutorials/tasks_lesson/#priority-management-considerations", 
-            "text": "When projects grow in scope, from blinking LEDs into more sophisticated applications, the number of tasks needed increases alongside complexity. It remains important, then, that each of our tasks is capable of doing its work within a reasonable amount of time.  Some tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore, the Shell task should be given a high priority. On the other hand, tasks which may be communicating over a network, or processing data, should be given a low priority in order to not hog the CPU.  The diagram below showcases the different scheduling patterns we. would expect from swapping blinky and work tasks priorities.   In the second case where  blinky_task  has a higher priority, the \u201cwork\u201d done by  work_task  would be executed during the millisecond delays in  blinky_task , saving us idle time compared to the first case.", 
+            "text": "When projects grow in scope, from blinking LEDs into more sophisticated applications, the number of tasks needed increases alongside complexity. It remains important, then, that each of our tasks is capable of doing its work within a reasonable amount of time.  Some tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore, the Shell task should be given a high priority. On the other hand, tasks which may be communicating over a network, or processing data, should be given a low priority in order to not hog the CPU.  The diagram below showcases the different scheduling patterns we. would expect from swapping blinky and work tasks priorities.   In the second case where  blinky_task  has a higher priority, the \u201cwork\u201d done by  work_task  would be executed during the millisecond delays in  blinky_task , saving us idle time compared to the first case.  Note:  Defining the same priority for two tasks leads to somewha
 t undefined behavior and should be avoided.", 
             "title": "Priority Management Considerations"
         }, 
         {
@@ -1012,7 +1012,7 @@
         }, 
         {
             "location": "/os/tutorials/tasks_lesson/#output-analysis", 
-            "text": "Run our new target, task_sim, and you should see an output similar to this:  Starting First Simulation...\n1:     Task B: 0% \n78:     Task B: 1% \n155:     Task B: 2% \n257:     Task B: 3% \n359:     Task B: 4% \n461:     Task B: 5%  snip \n\n========== Timer Expired ==========\n\n   Task A  \n  Priority: 3\n  Loop count: 162849\n  Cycle count: 16.28\n  Run time: 1.40 sec\n\n   Task B  \n  Priority: 2\n  Loop count: 1345852\n  Cycle count: 1.34\n  Run time: 17.0 sec\n\n Total loops: 1508709\n\n20023:   Switching priorities and restarting...\n20111:   Task A looped\n20113:     Task B: 0% \n20191:     Task B: 1% \n20297:   Task A looped\n20356:     Task B: 2% \n20483:   Task A looped\n20545:     Task B: 3% \n20669:   Task A looped\n20734:     Task B: 4% \n20855:   Task A looped\n20923:     Task B: 5%  snip \n\n========== Timer Expired ==========\n\n   Task A  \n  Priority: 2\n  Loop count: 1080000\n  Cycle count: 108.0\n  Run time: 9.28 sec\n\n   Task B  \n  Prio
 rity: 3\n  Loop count: 830356\n  Cycle count: 0.83\n  Run time: 10.72 sec\n\n Total loops: 1910404\n\n40058:\n\n Final Speedup (Sim2 / Sim1): 1.26  The console output reaffirms our previous prediction and makes both the scheduling differences and subsequent efficiency boost far more apparent. Let\u2019s take a look at scheduling differences before we delve into efficiency.  In the first case, where Task B\u2019s priority is higher than that of Task A, we see A get starved by Task B\u2019s long execution time.  Starvation  occurs when one task hogs the processor, essentially \u201cstarving\u201d other tasks which also need to run. At the end of the first 20 second simulation period, Task A has only run for 1.4 seconds compared to task B\u2019s 17 second running time \u2013 ouch. As explained before, processes which are expected to run for long periods of time (e.g. network communication, data processing) should be given higher priorities in order to combat starvation.  In the second 
 simulation with priorities swapped, we can see Task B only running during the millisecond delays when Task A is  sleeping . Although having Task B only run during these delays slows its execution time, we benefit from un-starving Task A and using the processor at a higher efficiency.  The bottom line speedup gives us an immediate and clear indication that we have improved our ability to process work (i.e throughput). In our second run, we processed an additional 400,000 loop iterations, equating to a 26% increase in efficiency. On a standard multi-core processor found in every modern PC, a 1.26 speedup would be an ok result to adding multithreading capabilities to a serial program. However, we accomplished this by simply setting priorities on a single core processor \u2013 not bad!  NOTE: Usually the the term \u201cspeedup\u201d is used within a parallel programming context and refers to the change in execution time between a serial and parallel program executing over the same probl
 em. In this case we\u2019re using the term loosely to illustrate the priority change\u2019s effect on scheduling and throughput in our specific context.", 
+            "text": "Run our new target, task_tgt, and you should see an output similar to this:  Starting First Simulation...\n1:     Task B: 0% \n78:     Task B: 1% \n155:     Task B: 2% \n257:     Task B: 3% \n359:     Task B: 4% \n461:     Task B: 5%  snip \n\n========== Timer Expired ==========\n\n   Task A  \n  Priority: 3\n  Loop count: 162849\n  Cycle count: 16.28\n  Run time: 1.40 sec\n\n   Task B  \n  Priority: 2\n  Loop count: 1345852\n  Cycle count: 1.34\n  Run time: 17.0 sec\n\n Total loops: 1508709\n\n20023:   Switching priorities and restarting...\n20111:   Task A looped\n20113:     Task B: 0% \n20191:     Task B: 1% \n20297:   Task A looped\n20356:     Task B: 2% \n20483:   Task A looped\n20545:     Task B: 3% \n20669:   Task A looped\n20734:     Task B: 4% \n20855:   Task A looped\n20923:     Task B: 5%  snip \n\n========== Timer Expired ==========\n\n   Task A  \n  Priority: 2\n  Loop count: 1080000\n  Cycle count: 108.0\n  Run time: 9.28 sec\n\n   Task B  \n  Prio
 rity: 3\n  Loop count: 830356\n  Cycle count: 0.83\n  Run time: 10.72 sec\n\n Total loops: 1910404\n\n40058:\n\n Final Speedup (Sim2 / Sim1): 1.26  The console output reaffirms our previous prediction and makes both the scheduling differences and subsequent efficiency boost far more apparent. Let\u2019s take a look at scheduling differences before we delve into efficiency.  In the first case, where Task B\u2019s priority is higher than that of Task A, we see A get starved by Task B\u2019s long execution time.  Starvation  occurs when one task hogs the processor, essentially \u201cstarving\u201d other tasks which also need to run. At the end of the first 20 second simulation period, Task A has only run for 1.4 seconds compared to task B\u2019s 17 second running time \u2013 ouch. As explained before, processes which are expected to run for long periods of time (e.g. network communication, data processing) should be given higher priorities in order to combat starvation.  In the second 
 simulation with priorities swapped, we can see Task B only running during the millisecond delays when Task A is  sleeping . Although having Task B only run during these delays slows its execution time, we benefit from un-starving Task A and using the processor at a higher efficiency.  The bottom line speedup gives us an immediate and clear indication that we have improved our ability to process work (i.e throughput). In our second run, we processed an additional 400,000 loop iterations, equating to a 26% increase in efficiency. On a standard multi-core processor found in every modern PC, a 1.26 speedup would be an ok result to adding multithreading capabilities to a serial program. However, we accomplished this by simply setting priorities on a single core processor \u2013 not bad!  NOTE: Usually the the term \u201cspeedup\u201d is used within a parallel programming context and refers to the change in execution time between a serial and parallel program executing over the same probl
 em. In this case we\u2019re using the term loosely to illustrate the priority change\u2019s effect on scheduling and throughput in our specific context.", 
             "title": "Output Analysis"
         }, 
         {
@@ -6667,7 +6667,7 @@
         }, 
         {
             "location": "/os/modules/fcb/fcb/", 
-            "text": "Flash Circular Buffer (FCB)\n\n\nFlash circular buffer provides an abstration through which you can treat flash like a FIFO. You append entries to the end, and read data from the beginning.\n\n\nDescription\n\n\nElements in the flash contain the length of the element, the data within the element, and checksum over the element contents.\n\n\nStorage of elements in flash is done in a FIFO fashion. When user requests space for the next element, space is located at the end of the used area. When user starts reading, the first element served is the oldest element in flash.\n\n\nElements can be appended to the end of the area until storage space is exhausted. User has control over what happens next; either erase oldest block of data, thereby freeing up some space, or stop writing new data until existing data has been collected. FCB treats underlying storage as an array of flash sectors; when it erases old data, it does this a sector at a time.\n\n\nElements in the fla
 sh are checksummed. That is how FCB detects whether writing element to flash completed ok. It will skip over entries which don't have a valid checksum.\n\n\nUsage\n\n\nTo add an element to circular buffer:\n\n\n\n\nCall fcb_append() to get the location where data can be written. If this fails due to lack of space, you can call fcb_rotate() to make some. And then call fcb_append() again.\n\n\nUse flash_area_write() to write element contents.\n\n\nCall fcb_append_finish() when done. This completes the entry by calculating the checksum.\n\n\n\n\nTo read contents of the circular buffer:\n\n Call fcb_walk() with a pointer to your callback function.\n\n Within callback function copy in data from the element using flash_area_read(). You can tell when all data from within a sector has been read by monitoring returned element's area pointer. Then you can call fcb_rotate(), if you're done with that data.\n\n\nAlternatively:\n\n Call fcb_getnext() with 0 in element offset to get the pointer to
  oldest element.\n\n Use flash_area_read() to read element contents.\n* Call fcb_getnext() with pointer to current element to get the next one. And so on.\n\n\nData structures\n\n\nThis data structure describes the element location in the flash. You would use it figure out what parameters to pass to flash_area_read() to read element contents. Or to flash_area_write() when adding a new element.\n\n\nstruct\n \nfcb_entry\n {\n    \nstruct\n \nflash_area\n \n*fe_area\n;\n    \nuint32_t\n \nfe_elem_off\n;\n    \nuint32_t\n \nfe_data_off\n;\n    \nuint16_t\n \nfe_data_len\n;\n};\n\n\n\n\n\n\n\n\n\n\n\nElement\n\n\nDescription\n\n\n\n\n\n\n\n\n\n\nfe_area\n\n\nPointer to info about the flash sector. Pass this to flash_area_xx() routines.\n\n\n\n\n\n\nfe_elem_off\n\n\nByte offset from the start of the sector to beginning of element.\n\n\n\n\n\n\nfe_data_off\n\n\nByte offset from start of the sector to beginning of element data. Pass this to to flash_area_xx() routines.\n\n\n\n\n\n\nfe_data
 _len\n\n\nNumber of bytes in the element.\n\n\n\n\n\n\n\n\nThe following data structure describes the FCB itself. First part should be filled in by the user before calling fcb_init(). The second part is used by FCB for its internal bookkeeping.\n\n\nstruct\n \nfcb\n {\n    \n/* Caller of fcb_init fills this in */\n\n    \nuint32_t\n \nf_magic\n;           \n/* As placed on the disk */\n\n    \nuint8_t\n \nf_version\n;          \n/* Current version number of the data */\n\n    \nuint8_t\n \nf_sector_cnt\n;       \n/* Number of elements in sector array */\n\n    \nuint8_t\n \nf_scratch_cnt\n;      \n/* How many sectors should be kept empty */\n\n    \nstruct\n \nflash_area\n \n*f_sectors\n; \n/* Array of sectors, must be contiguous */\n\n\n    \n/* Flash circular buffer internal state */\n\n    \nstruct\n \nos_mutex\n \nf_mtx\n;      \n/* Locking for accessing the FCB data */\n\n    \nstruct\n \nflash_area\n \n*f_oldest\n;\n    \nstruct\n \nfcb_entry\n \nf_active\n;\n    \nuint16_t\n 
 \nf_active_id\n;\n    \nuint8_t\n \nf_align\n;            \n/* writes to flash have to aligned to this */\n\n};\n\n\n\n\n\n\n\n\n\n\n\nElement\n\n\nDescription\n\n\n\n\n\n\n\n\n\n\nf_magic\n\n\nMagic number in the beginning of FCB flash sector. FCB uses this when determining whether sector contains valid data or not.\n\n\n\n\n\n\nf_version\n\n\nCurrent version number of the data. Also stored in flash sector header.\n\n\n\n\n\n\nf_sector_cnt\n\n\nNumber of elements in the f_sectors array.\n\n\n\n\n\n\nf_scratch_cnt\n\n\nNumber of sectors to keep empty. This can be used if you need to have scratch space for garbage collecting when FCB fills up.\n\n\n\n\n\n\nf_sectors\n\n\nArray of entries describing flash sectors to use.\n\n\n\n\n\n\nf_mtx\n\n\nLock protecting access to FCBs internal data.\n\n\n\n\n\n\nf_oldest\n\n\nPointer to flash sector containing the oldest data. This is where data is served when read is started.\n\n\n\n\n\n\nf_active\n\n\nFlash location where the newest data is. 
 This is used by fcb_append() to figure out where the data should go to.\n\n\n\n\n\n\nf_active_id\n\n\nFlash sectors are assigned ever-increasing serial numbers. This is how FCB figures out where oldest data is on system restart.\n\n\n\n\n\n\nf_align\n\n\nSome flashes have restrictions on alignment for writes. FCB keeps a copy of this number for the flash here.\n\n\n\n\n\n\n\n\nList of Functions\n\n\nThe functions available in this OS feature are:\n\n\n\n\nfcb_init\n\n\nfcb_append\n\n\nfcb_append_finish\n\n\nfcb_walk\n\n\nfcb_getnext\n\n\nfcb_rotate\n\n\nfcb_append_to_scratch\n\n\nfcb_is_empty\n\n\nfcb_offset_last_n\n\n\nfcb_clear", 
+            "text": "Flash Circular Buffer (FCB)\n\n\nFlash circular buffer provides an abstration through which you can treat flash like a FIFO. You append entries to the end, and read data from the beginning.\n\n\nDescription\n\n\nElements in the flash contain the length of the element, the data within the element, and checksum over the element contents.\n\n\nStorage of elements in flash is done in a FIFO fashion. When user requests space for the next element, space is located at the end of the used area. When user starts reading, the first element served is the oldest element in flash.\n\n\nElements can be appended to the end of the area until storage space is exhausted. User has control over what happens next; either erase oldest block of data, thereby freeing up some space, or stop writing new data until existing data has been collected. FCB treats underlying storage as an array of flash sectors; when it erases old data, it does this a sector at a time.\n\n\nElements in the fla
 sh are checksummed. That is how FCB detects whether writing element to flash completed ok. It will skip over entries which don't have a valid checksum.\n\n\nUsage\n\n\nTo add an element to circular buffer:\n\n\n\n\nCall fcb_append() to get the location where data can be written. If this fails due to lack of space, you can call fcb_rotate() to make some. And then call fcb_append() again.\n\n\nUse flash_area_write() to write element contents.\n\n\nCall fcb_append_finish() when done. This completes the entry by calculating the checksum.\n\n\n\n\nTo read contents of the circular buffer:\n\n Call fcb_walk() with a pointer to your callback function.\n\n Within callback function copy in data from the element using flash_area_read(). You can tell when all data from within a sector has been read by monitoring returned element's area pointer. Then you can call fcb_rotate(), if you're done with that data.\n\n\nAlternatively:\n\n Call fcb_getnext() with 0 in element offset to get the pointer to
  oldest element.\n\n Use flash_area_read() to read element contents.\n* Call fcb_getnext() with pointer to current element to get the next one. And so on.\n\n\nData structures\n\n\nThis data structure describes the element location in the flash. You would use it figure out what parameters to pass to flash_area_read() to read element contents. Or to flash_area_write() when adding a new element.\n\n\nstruct\n \nfcb_entry\n {\n    \nstruct\n \nflash_area\n \n*fe_area\n;\n    \nuint32_t\n \nfe_elem_off\n;\n    \nuint32_t\n \nfe_data_off\n;\n    \nuint16_t\n \nfe_data_len\n;\n};\n\n\n\n\n\n\n\n\n\n\n\nElement\n\n\nDescription\n\n\n\n\n\n\n\n\n\n\nfe_area\n\n\nPointer to info about the flash sector. Pass this to flash_area_xx() routines.\n\n\n\n\n\n\nfe_elem_off\n\n\nByte offset from the start of the sector to beginning of element.\n\n\n\n\n\n\nfe_data_off\n\n\nByte offset from start of the sector to beginning of element data. Pass this to to flash_area_xx() routines.\n\n\n\n\n\n\nfe_data
 _len\n\n\nNumber of bytes in the element.\n\n\n\n\n\n\n\n\nThe following data structure describes the FCB itself. First part should be filled in by the user before calling fcb_init(). The second part is used by FCB for its internal bookkeeping.\n\n\nstruct\n \nfcb\n {\n    \n/* Caller of fcb_init fills this in */\n\n    \nuint32_t\n \nf_magic\n;           \n/* As placed on the disk */\n\n    \nuint8_t\n \nf_version\n;          \n/* Current version number of the data */\n\n    \nuint8_t\n \nf_sector_cnt\n;       \n/* Number of elements in sector array */\n\n    \nuint8_t\n \nf_scratch_cnt\n;      \n/* How many sectors should be kept empty */\n\n    \nstruct\n \nflash_area\n \n*f_sectors\n; \n/* Array of sectors, must be contiguous */\n\n\n    \n/* Flash circular buffer internal state */\n\n    \nstruct\n \nos_mutex\n \nf_mtx\n;      \n/* Locking for accessing the FCB data */\n\n    \nstruct\n \nflash_area\n \n*f_oldest\n;\n    \nstruct\n \nfcb_entry\n \nf_active\n;\n    \nuint16_t\n 
 \nf_active_id\n;\n    \nuint8_t\n \nf_align\n;            \n/* writes to flash have to aligned to this */\n\n};\n\n\n\n\n\n\n\n\n\n\n\nElement\n\n\nDescription\n\n\n\n\n\n\n\n\n\n\nf_magic\n\n\nMagic number in the beginning of FCB flash sector. FCB uses this when determining whether sector contains valid data or not.\n\n\n\n\n\n\nf_version\n\n\nCurrent version number of the data. Also stored in flash sector header.\n\n\n\n\n\n\nf_sector_cnt\n\n\nNumber of elements in the f_sectors array.\n\n\n\n\n\n\nf_scratch_cnt\n\n\nNumber of sectors to keep empty. This can be used if you need to have scratch space for garbage collecting when FCB fills up.\n\n\n\n\n\n\nf_sectors\n\n\nArray of entries describing flash sectors to use.\n\n\n\n\n\n\nf_mtx\n\n\nLock protecting access to FCBs internal data.\n\n\n\n\n\n\nf_oldest\n\n\nPointer to flash sector containing the oldest data. This is where data is served when read is started.\n\n\n\n\n\n\nf_active\n\n\nFlash location where the newest data is. 
 This is used by fcb_append() to figure out where the data should go to.\n\n\n\n\n\n\nf_active_id\n\n\nFlash sectors are assigned ever-increasing serial numbers. This is how FCB figures out where oldest data is on system restart.\n\n\n\n\n\n\nf_align\n\n\nSome flashes have restrictions on alignment for writes. FCB keeps a copy of this number for the flash here.\n\n\n\n\n\n\n\n\nList of Functions\n\n\nThe functions available in this OS feature are:\n\n\n\n\n\n\n\n\nFunction\n\n\nDescription\n\n\n\n\n\n\n\n\n\n\nfcb_init\n\n\nInitializes the FCB. After calling this, you can start reading/writing data from FCB.\n\n\n\n\n\n\nfcb_append\n\n\nStart writing a new element to flash.\n\n\n\n\n\n\nfcb_append_finish\n\n\nFinalizes the write of new element. FCB computes the checksum over the element and updates it in flash.\n\n\n\n\n\n\nfcb_walk\n\n\nWalks over all log entries in FCB.\n\n\n\n\n\n\nfcb_getnext\n\n\nFills given FCB location with information about next element.\n\n\n\n\n\n\nfcb_rota
 te\n\n\nErase the oldest sector in FCB.\n\n\n\n\n\n\nfcb_append_to_scratch\n\n\nIf FCB uses scratch blocks, use reserve blocks when FCB is filled.\n\n\n\n\n\n\nfcb_is_empty\n\n\nReturns 1 if there are no elements stored in FCB, otherwise returns 0.\n\n\n\n\n\n\nfcb_offset_last_n\n\n\nReturns the offset of n-th last element.\n\n\n\n\n\n\nfcb_clear\n\n\nWipes out all data in FCB.", 
             "title": "toc"
         }, 
         {
@@ -6692,7 +6692,7 @@
         }, 
         {
             "location": "/os/modules/fcb/fcb/#list-of-functions", 
-            "text": "The functions available in this OS feature are:   fcb_init  fcb_append  fcb_append_finish  fcb_walk  fcb_getnext  fcb_rotate  fcb_append_to_scratch  fcb_is_empty  fcb_offset_last_n  fcb_clear", 
+            "text": "The functions available in this OS feature are:     Function  Description      fcb_init  Initializes the FCB. After calling this, you can start reading/writing data from FCB.    fcb_append  Start writing a new element to flash.    fcb_append_finish  Finalizes the write of new element. FCB computes the checksum over the element and updates it in flash.    fcb_walk  Walks over all log entries in FCB.    fcb_getnext  Fills given FCB location with information about next element.    fcb_rotate  Erase the oldest sector in FCB.    fcb_append_to_scratch  If FCB uses scratch blocks, use reserve blocks when FCB is filled.    fcb_is_empty  Returns 1 if there are no elements stored in FCB, otherwise returns 0.    fcb_offset_last_n  Returns the offset of n-th last element.    fcb_clear  Wipes out all data in FCB.", 
             "title": "List of Functions"
         }, 
         {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4d3003a5/develop/os/modules/fcb/fcb/index.html
----------------------------------------------------------------------
diff --git a/develop/os/modules/fcb/fcb/index.html b/develop/os/modules/fcb/fcb/index.html
index 9bbd32b..a0d5045 100644
--- a/develop/os/modules/fcb/fcb/index.html
+++ b/develop/os/modules/fcb/fcb/index.html
@@ -621,18 +621,56 @@
 </table>
 <h3 id="list-of-functions">List of Functions</h3>
 <p>The functions available in this OS feature are:</p>
-<ul>
-<li><a href="../fcb_init/">fcb_init</a></li>
-<li><a href="../fcb_append/">fcb_append</a></li>
-<li><a href="../fcb_append_finish/">fcb_append_finish</a></li>
-<li><a href="../fcb_walk/">fcb_walk</a></li>
-<li><a href="../fcb_getnext/">fcb_getnext</a></li>
-<li><a href="../fcb_rotate/">fcb_rotate</a></li>
-<li><a href="../fcb_append_to_scratch/">fcb_append_to_scratch</a></li>
-<li><a href="../fcb_is_empty/">fcb_is_empty</a></li>
-<li><a href="../fcb_offset_last_n/">fcb_offset_last_n</a></li>
-<li><a href="../fcb_clear/">fcb_clear</a></li>
-</ul>
+<table>
+<thead>
+<tr>
+<th>Function</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td><a href="../fcb_init/">fcb_init</a></td>
+<td>Initializes the FCB. After calling this, you can start reading/writing data from FCB.</td>
+</tr>
+<tr>
+<td><a href="../fcb_append/">fcb_append</a></td>
+<td>Start writing a new element to flash.</td>
+</tr>
+<tr>
+<td><a href="../fcb_append_finish/">fcb_append_finish</a></td>
+<td>Finalizes the write of new element. FCB computes the checksum over the element and updates it in flash.</td>
+</tr>
+<tr>
+<td><a href="../fcb_walk/">fcb_walk</a></td>
+<td>Walks over all log entries in FCB.</td>
+</tr>
+<tr>
+<td><a href="../fcb_getnext/">fcb_getnext</a></td>
+<td>Fills given FCB location with information about next element.</td>
+</tr>
+<tr>
+<td><a href="../fcb_rotate/">fcb_rotate</a></td>
+<td>Erase the oldest sector in FCB.</td>
+</tr>
+<tr>
+<td><a href="../fcb_append_to_scratch/">fcb_append_to_scratch</a></td>
+<td>If FCB uses scratch blocks, use reserve blocks when FCB is filled.</td>
+</tr>
+<tr>
+<td><a href="../fcb_is_empty/">fcb_is_empty</a></td>
+<td>Returns 1 if there are no elements stored in FCB, otherwise returns 0.</td>
+</tr>
+<tr>
+<td><a href="../fcb_offset_last_n/">fcb_offset_last_n</a></td>
+<td>Returns the offset of n-th last element.</td>
+</tr>
+<tr>
+<td><a href="../fcb_clear/">fcb_clear</a></td>
+<td>Wipes out all data in FCB.</td>
+</tr>
+</tbody>
+</table>
                         
                         <div class="row">
                             

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4d3003a5/develop/os/tutorials/pics/task_lesson.png
----------------------------------------------------------------------
diff --git a/develop/os/tutorials/pics/task_lesson.png b/develop/os/tutorials/pics/task_lesson.png
index 16cbcd5..0ecb5e8 100644
Binary files a/develop/os/tutorials/pics/task_lesson.png and b/develop/os/tutorials/pics/task_lesson.png differ

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4d3003a5/develop/os/tutorials/tasks_lesson/index.html
----------------------------------------------------------------------
diff --git a/develop/os/tutorials/tasks_lesson/index.html b/develop/os/tutorials/tasks_lesson/index.html
index fee68d4..db17dcc 100644
--- a/develop/os/tutorials/tasks_lesson/index.html
+++ b/develop/os/tutorials/tasks_lesson/index.html
@@ -481,8 +481,7 @@
 </pre></div>
 
 
-<p>The task function is called when the task is initially put into the
-<em>running</em> state by the scheduler. We use an infinite loop to ensure that the task function never returns and assert that the current task\u2019s function is correct before doing any work.</p>
+<p>The task function is called when the task is initially put into the <em>running</em> state by the scheduler. We use an infinite loop to ensure that the task function never returns. Our assertion that the current task's handler is the same as our task handler is for illustration purposes only and does not need to be in most task functions.</p>
 <h3 id="task-priority">Task Priority</h3>
 <p>As a preemptive, multitasking RTOS, Mynewt decides which tasks to run based on which has a higher priority; the highest priority being 0 and the lowest 255. Thus, before initializing our task, we must choose a priority defined as a macro variable.</p>
 <p>Let\u2019s set the priority of <code>work_task</code> to 0, because everyone knows that work is more important than blinking.</p>
@@ -506,11 +505,17 @@
 </pre></div>
 
 
+<p>And that\u2019s it! Now run your application using the newt run command.</p>
+<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%">$ newt run arduino_blinky 0.0.0
+</pre></div>
+
+
+<p>When GDB appears press C then Enter to continue and \u2026 <em>wait, why doesn't our LED blink anymore?</em></p>
 <h4 id="review">Review</h4>
-<p>Before we run our new app, let\u2019s review what we need in order to create a task:</p>
-<p><strong>1)</strong>   Define a new task, task stack, and priority</p>
+<p>Before we run our new app, let\u2019s review what we need in order to create a task. This is a general case for a new task called mytask:</p>
+<p><strong>1)</strong>   Define a new task, task stack, and priority:</p>
 <div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%"><span style="color: #177500">/* My Task */</span>
-<span style="color: #000000">os_task</span> <span style="color: #000000">mytask</span>
+<span style="color: #A90D91">struct</span> <span style="color: #000000">os_task</span> <span style="color: #000000">mytask</span>
 <span style="color: #177500">/* My Task Stack */</span>
 <span style="color: #633820">#define MYTASK_STACK_SIZE OS_STACK_ALIGN(256)</span>
 <span style="color: #A90D91">os_stack_t</span> <span style="color: #000000">mytask_stack</span>[<span style="color: #000000">MYTASK_STACK_SIZE</span>];
@@ -519,23 +524,24 @@
 </pre></div>
 
 
-<p><strong>2)</strong> Define task function</p>
+<p><strong>2)</strong> Define task function:</p>
 <div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%"><span style="color: #A90D91">void</span> 
 <span style="color: #000000">mytask_handler</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
 {
-    <span style="color: #177500">/* ... */</span>
+  <span style="color: #A90D91">while</span> (<span style="color: #1C01CE">1</span>) {
+      <span style="color: #177500">/* ... */</span>
+  }
 }
 </pre></div>
 
 
-<p><strong>3)</strong> Initialize task before calling <code>os_start()</code></p>
+<p><strong>3)</strong> Initialize task before calling <code>os_start()</code>:</p>
 <div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%"><span style="color: #000000">os_task_init</span>(<span style="color: #000000">&amp;mytask</span>, <span style="color: #C41A16">&quot;mytask&quot;</span>, <span style="color: #000000">mytask_handler</span>, <span style="color: #A90D91">NULL</span>, 
             <span style="color: #000000">MYTASK_PRIO</span>, <span style="color: #000000">OS_WAIT_FOREVER</span>, <span style="color: #000000">mytask_stack</span>,
             <span style="color: #000000">MYTASK_STACK_SIZE</span>);
 </pre></div>
 
 
-<p>And that\u2019s it! Run your application and \u2026 <em>wait, why doesn't our LED blink anymore?</em></p>
 <h2 id="task-priority-preempting-and-context-switching">Task Priority, Preempting, and Context Switching</h2>
 <p>A preemptive RTOS is one in which a higher priority task that is <em>ready to run</em> will preempt (i.e. take the place of) the lower priority task which is <em>running</em>. When a lower priority task is preempted by a higher priority task, the lower priority task\u2019s context data (stack pointer, registers, etc.) is saved and the new task is switched in.</p>
 <p>In our example, <code>work_task</code> has a higher priority than <code>blinky_task</code> and, because it is never put into a <em>sleep</em> state, holds the processor focus on its context. Let\u2019s give <code>work_task</code> a delay and some simulated work to keep it busy. Because the delay is measured in os ticks, the actual number of ticks per second is dependent on the board. Therefore, we multiply <code>OS_TICKS_PER_SEC</code>, which is defined in the MCU, by the number of seconds we wish to delay.</p>
@@ -553,7 +559,7 @@
         <span style="color: #177500">/* Do work... */</span>
         <span style="color: #A90D91">int</span> <span style="color: #000000">i</span>;
         <span style="color: #A90D91">for</span>(<span style="color: #000000">i</span> <span style="color: #000000">=</span> <span style="color: #1C01CE">0</span>; <span style="color: #000000">i</span> <span style="color: #000000">&lt;</span> <span style="color: #1C01CE">1000000</span>; <span style="color: #000000">++i</span>) {
-            <span style="color: #177500">//simulate doing a noticeable amount of work</span>
+            <span style="color: #177500">/* Simulate doing a noticeable amount of work */</span>
             <span style="color: #000000">hal_gpio_set</span>(<span style="color: #000000">g_led_pin</span>);
         }
         <span style="color: #000000">os_time_delay</span>(<span style="color: #1C01CE">3</span><span style="color: #000000">*OS_TICKS_PER_SECOND</span>);
@@ -563,19 +569,19 @@
 
 
 <p>In order to notice the LED changing, modify the time delay in <code>blinky_task_handler()</code> to blink at a higher frequency.</p>
-<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%"><span style="color: #000000">os_time_delay</span>(<span style="color: #1C01CE">100</span>);
+<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%"><span style="color: #000000">os_time_delay</span>(<span style="color: #000000">OS_TICKS_PER_SEC/</span><span style="color: #1C01CE">10</span>);
 </pre></div>
 
 
-<p>Before we run the app, let\u2019s predict the behavior. With the newest
-additions to <code>work_task_handler()</code>, our first action will be to sleep for three seconds. This will allow <code>blinky_task</code> to take over the CPU and blink to its heart\u2019s content. After three seconds, <code>work_task</code> will wake up and be made <em>ready to run</em>, causing it to preempt <code>blinky_task</code>. The LED will then remain lit for a short period while <code>work_task</code> loops, then blink again for another three seconds while <code>work_task</code> sleeps. </p>
-<p>Viola, you should see that our prediction was correct! What would happen when both priorities are the same? Try it out for yourself!</p>
+<p>Before we run the app, let\u2019s predict the behavior. With the newest additions to <code>work_task_handler()</code>, our first action will be to sleep for three seconds. This will allow <code>blinky_task</code> to take over the CPU and blink to its heart\u2019s content. After three seconds, <code>work_task</code> will wake up and be made <em>ready to run</em>, causing it to preempt <code>blinky_task</code>. The LED will then remain lit for a short period while <code>work_task</code> loops, then blink again for another three seconds while <code>work_task</code> sleeps. </p>
+<p>Voila, you should see that our prediction was correct! </p>
 <h3 id="priority-management-considerations">Priority Management Considerations</h3>
 <p>When projects grow in scope, from blinking LEDs into more sophisticated applications, the number of tasks needed increases alongside complexity. It remains important, then, that each of our tasks is capable of doing its work within a reasonable amount of time.</p>
 <p>Some tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore, the Shell task should be given a high priority. On the other hand, tasks which may be communicating over a network, or processing data, should be given a low priority in order to not hog the CPU.</p>
 <p>The diagram below showcases the different scheduling patterns we. would expect from swapping blinky and work tasks priorities.</p>
 <p><img alt="Task Scheduling" src="../pics/task_lesson.png" /></p>
 <p>In the second case where <code>blinky_task</code> has a higher priority, the \u201cwork\u201d done by <code>work_task</code> would be executed during the millisecond delays in <code>blinky_task</code>, saving us idle time compared to the first case.</p>
+<p><strong>Note:</strong> Defining the same priority for two tasks leads to somewhat undefined behavior and should be avoided.</p>
 <h2 id="comparing-priority-strategies">Comparing Priority Strategies</h2>
 <p>Instead of stepping through a bunch of changes to our blinky app, clone my task lesson application from github and copy an existing target.</p>
 <p>Change directory into apps and clone the repository to get our new
@@ -648,7 +654,7 @@ $ git checkout develop
 
 <p>If you see minicom welcome you, you\u2019re ready to move on!</p>
 <h3 id="output-analysis">Output Analysis</h3>
-<p>Run our new target, task_sim, and you should see an output similar to this:</p>
+<p>Run our new target, task_tgt, and you should see an output similar to this:</p>
 <div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%">Starting First Simulation...
 1:     Task B: 0% 
 78:     Task B: 1% 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4d3003a5/develop/sitemap.xml
----------------------------------------------------------------------
diff --git a/develop/sitemap.xml b/develop/sitemap.xml
index cf3a0f6..fa07bcc 100644
--- a/develop/sitemap.xml
+++ b/develop/sitemap.xml
@@ -4,7 +4,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -12,7 +12,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/quick-start/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -20,7 +20,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/about/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -28,7 +28,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/download/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -36,7 +36,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/community/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -44,7 +44,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/events/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -53,7 +53,7 @@
         
     <url>
      <loc>http://mynewt.apache.org/os/introduction/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
@@ -65,7 +65,7 @@
         
     <url>
      <loc>http://mynewt.apache.org/os/get_started/vocabulary/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
@@ -105,13 +105,13 @@
         
     <url>
      <loc>http://mynewt.apache.org/faq/how_to_edit_docs/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
     <url>
      <loc>http://mynewt.apache.org/faq/answers/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4d3003a5/latest/sitemap.xml
----------------------------------------------------------------------
diff --git a/latest/sitemap.xml b/latest/sitemap.xml
index cf3a0f6..fa07bcc 100644
--- a/latest/sitemap.xml
+++ b/latest/sitemap.xml
@@ -4,7 +4,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -12,7 +12,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/quick-start/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -20,7 +20,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/about/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -28,7 +28,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/download/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -36,7 +36,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/community/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -44,7 +44,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/events/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -53,7 +53,7 @@
         
     <url>
      <loc>http://mynewt.apache.org/os/introduction/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
@@ -65,7 +65,7 @@
         
     <url>
      <loc>http://mynewt.apache.org/os/get_started/vocabulary/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
@@ -105,13 +105,13 @@
         
     <url>
      <loc>http://mynewt.apache.org/faq/how_to_edit_docs/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
     <url>
      <loc>http://mynewt.apache.org/faq/answers/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4d3003a5/sitemap.xml
----------------------------------------------------------------------
diff --git a/sitemap.xml b/sitemap.xml
index cf3a0f6..fa07bcc 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -4,7 +4,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -12,7 +12,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/quick-start/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -20,7 +20,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/about/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -28,7 +28,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/download/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -36,7 +36,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/community/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -44,7 +44,7 @@
     
     <url>
      <loc>http://mynewt.apache.org/events/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
     
@@ -53,7 +53,7 @@
         
     <url>
      <loc>http://mynewt.apache.org/os/introduction/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
@@ -65,7 +65,7 @@
         
     <url>
      <loc>http://mynewt.apache.org/os/get_started/vocabulary/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
@@ -105,13 +105,13 @@
         
     <url>
      <loc>http://mynewt.apache.org/faq/how_to_edit_docs/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>
         
     <url>
      <loc>http://mynewt.apache.org/faq/answers/</loc>
-     <lastmod>2016-07-05</lastmod>
+     <lastmod>2016-07-06</lastmod>
      <changefreq>daily</changefreq>
     </url>