Skip to content

Updated the flow control tutorial #1287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -668,9 +668,6 @@
},
{
"path": "docs/api/bluetooth/HeartRateService.md"
},
{
"path": "docs/api/bluetooth/iBeacon.md"
}
]
},
Expand Down
41 changes: 26 additions & 15 deletions docs/api/io/flow_control.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,67 @@ We can use Blinky to explore flow control and task management in Arm Mbed OS app

If we want to automatically blink an LED, we have three main techniques:

1. [Busy wait](#busy-wait)
1. [Wait](#wait)
1. [Ticker](#ticker)
1. [Thread](#thread)

### Busy wait
### Wait

Busy wait is a method that blocks the processor for a period of time. This is an effective way to create time delays, but it’s inefficient because it wastes processor time and keeps the processor running at full power for the duration of the wait:
#### Busy wait

Busy wait is a method that blocks the processor for a period of time. This is an effective way to create time delays, but it is inefficient because it wastes processor time and keeps the processor running at full power for the duration of the wait:

[![View code](https://www.mbed.com/embed/?url=https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Busy-Wait)](https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Busy-Wait/main.cpp)

Notice `printf()`; you can enable this by uncommenting the line (remove the `//`). `printf()` prints to the terminal, so you can use it to get debug information.

<span class="tips">**Tip:** We recommend using [CoolTerm](http://freeware.the-meiers.org/), as it works the same on Windows, Linux and OS X. [Here is a handy video on how to use CoolTerm](https://www.youtube.com/watch?v=jAMTXK9HjfU) to connect to your board and view the `printf()` statements. For more information, see our [serial communication tutorials](../tutorials/serial-communication.html).</span>
<span class="tips">**Tip:** Busy wait is inefficient, and we recommend not using it. </span>

#### Suspend thread execution

A better alternative to busy wait is to suspend thread execution while waiting. Use:

* For C++: The `ThisThread::sleep_for` API
* For C: The `thread_sleep_for` API.

### Ticker

Tickers and timers are another way of creating a time interval. These methods are somewhat better than busy wait because they allow other code to run while you are waiting. It is even possible, though nontrivial, to sleep during the wait period.
Tickers and timers are another way of creating a time interval. These methods allow other code to run while you are waiting. During the wait period, if no threads are running, the idle thread can automatically put the system to sleep.

Here is an example that doesn't include sleeping:
If you don't need the precision of a high-frequency timer or ticker, we recommend that you use LowPowerTimer or LowPowerTicker instead. This allows the system to be put in deep sleep mode.

Here is an example that uses a ticker object:

[![View code](https://www.mbed.com/embed/?url=https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Ticker)](https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Ticker/main.cpp)

<span class="tips">**Tip:** You may want to read the [power optimization](../tutorials/power-optimization.html) tutorial to understand how to achieve power savings. </span>

### Thread

Threads are the most efficient way to blink an LED. During the waiting period, it is possible to take advantage of Mbed OS optimizations to automatically conserve power and deal with other tasks. While this is not the most visually appealing method, nor the simplest, it is the preferred way for large scale deployments:
If your application is running in RTOS mode then threads are another efficient way to blink an LED. During the waiting period, it is possible to take advantage of Mbed OS optimizations to automatically conserve power and deal with other tasks.

[![View code](https://www.mbed.com/embed/?url=https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Thread)](https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Thread/main.cpp)

## Flow control for manual actions

Let’s try using a DigitalIn pin from the button to control the application. There are two ways to read input data: we can either constantly poll the button in a busy wait, or set an interrupt to trigger when pressed. We’ll explore these methods below.

### Busy wait button
Let’s use a DigitalIn pin from the button to control the application. There are two ways to read input data: we can either constantly poll the button, or set an interrupt to trigger when pressed. We’ll explore these methods below.

We can wait for digital input the same way we waited for time to pass - using a `while()` loop. In the example below the digital input is a button press, which causes the application to flash the LED and then wait for 1 second.
### Active polling button

<span class="tips">**Tip:** You may need to change the `SW1` pin, as the button on your board may be called something else. Please refer to the pinmap on the [boards page](https://os.mbed.com/platforms/).</span>
We can wait for digital input the same way we waited for time to pass - using a `while()` loop. In the example below the digital input is a button press, which causes the application to flash the LED and then wait for one second.

[![View code](https://www.mbed.com/embed/?url=https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Active-Polling-Button)](https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Active-Polling-Button/main.cpp)

We constantly poll the button to see whether it has a value that matches `button_press`. If it matches, we toggle the LED and wait 1 second.
We constantly poll the button to see whether it has a value that matches `BUTTON_PRESS`. If it matches, we toggle the LED and wait one second.

`button_press` is used to denote what value the switch uses to represent the state *pushed*. Most switches are by default open (unpressed), so they will read as 0 while pressed. If you see your LED blinking without the button being pressed - try changing `button_press` to `1`.
`BUTTON_PRESS` is used to denote what value the switch uses to represent the state *pushed*. Most switches are by default open (unpressed), so they will read as 0 while pressed. If you see your LED blinking without the button being pressed - try changing `BUTTON_PRESS` to `1`.

### Interrupt button

An alternative way to poll the button is to use an interrupt. Interrupts let you say `when that pin changes value, call this function`. In other words, we can tell the MCU to call a function when the button is pressed. In our case, that function toggles the LED:

[![View code](https://www.mbed.com/embed/?url=https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Interrupt-Button)](https://github.com/ARMmbed/mbed-os-examples-docs_only/blob/master/Tutorials_UsingAPIs/Flow-Control-Interrupt-Button/main.cpp)

In the code above a heartbeat function runs on LED2, which lets you see that your code is running. Then we connect an InterruptIn object to the button and set it so that when the button rises from 0 to 1, the toggle function is called; the function toggles LED1. This way we can turn the LED on and off as needed, without needing to “waste” our time waiting or actively polling an inactive button. We (or rather - the MCU) are free to move on to other things .
In the code above a heartbeat function runs on LED2, which lets you see that your code is running. Then we connect an InterruptIn object to the button and set it so that when the button rises from 0 to 1, the toggle function is called; the function toggles LED1. This way the application can turn the LED on and off as needed, without needing to “waste” time waiting or actively polling an inactive button. The MCU is free to move on to other things .

Interrupt driven programming is one of the fundamental paradigms of microcontroller programming.