Skip to content

FileHandle: Mbed OS 5.12 updates #992

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 4 commits into from
Mar 7, 2019
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
16 changes: 15 additions & 1 deletion docs/api/platform/FileHandle.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Blocking I/O | Yes (always) | Yes (default)
Nonblocking I/O | No | Yes | Yes
Poll | No | Yes (struct pollfd) | Yes (struct pollfh)
Sigio | No | No | Yes
Disable input or output | No | No | Yes
Device-specific extensions | No | No | Possible using derived types
Newline conversion | Yes (enabled with JSON) | No | No
Error indications | EOF, ferror, set errno | Return -1, set errno | Return negative error code
Expand All @@ -51,9 +52,13 @@ Calls are provided to attach already-opened lower levels to the higher levels:
- `FILE *fdopen(int fd, const char *mode)` bind a POSIX file descriptor to a stdio FILE.
- `FILE *fdopen(FileHandle *fh, const char *mode)` bind a FileHandle to a stdio FILE.

The only call provided to map from higher level to lower-level is:

- `FileHandle *mbed_file_handle(int fd)` obtain the FileHandle for a POSIX file descriptor

The standard POSIX function `int fileno(FILE *stream)` may be available to map from `FILE` to file descriptor, depending on the toolchain and C library in use - it is not usable in fully portable Mbed OS code.

As it is not possible to map from higher levels to lower levels, if code needs to access the lower levels, use a lower-level open call, so the lower-level handle is known. Then, bind that to the higher level..
It is not possible to map from `FILE` to lower levels. If code needs to access the lower levels, rather than use `fopen`, use a lower-level open call. Then, use `fdopen` to create the `FILE`.

The POSIX file descriptors for the console are available as `STDIN_FILENO`, `STDOUT_FILENO` and `STDERR_FILENO`, permitting operations such as `fsync(STDERR_FILENO)`, which would for example drain `UARTSerial`s output buffer.

Expand Down Expand Up @@ -112,6 +117,14 @@ Important notes on sigio:

Ordinary files do not generate sigio callbacks because they are always readable and writable.

#### Suspending a device

Having a device open through a `FileHandle` may cost power, especially if open for input. For example, for `UARTSerial` to be able to receive data, the system must not enter deep sleep, so deep sleep is prevented while the `UARTSerial` is active.

To permit power saving, you can close or destroy the `FileHandle`, or you can indicate that you do not currently require input or output by calling `FileHandle::enable_input` or `FileHandle::enable_output`. Disabling input or output effectively suspends the device in that direction, which can permit power saving.

This is particularly useful when an application does not require console input - it can indicate this by calling `mbed_file_handle(STDIN_FILENO)->enable_input(false)` once at the start of the program. This permits deep sleep when `platform.stdio-buffered-serial` is set to true.

#### Stream-derived FileHandles

`Stream` is a legacy class that provides an abstract interface for streams similar to the `FileHandle` class. The difference is that the `Stream` API is built around the `getc` and `putc` set of functions, whereas `FileHandle` is built around `read` and `write`. This makes implementations simpler but limits what is possible with the API. Because of this, implementing the `FileHandle` API directly is suggested API for new device drivers.
Expand Down Expand Up @@ -214,3 +227,4 @@ int main()
- [File](file.html).
- [FileSystem](filesystem.html).
- [Poll](poll.html).
- [Power management](powermanagement.html).
16 changes: 12 additions & 4 deletions docs/api/platform/PowerManagement.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,25 @@ These Mbed OS drivers can lock the deep sleep:
- `SPI`.
- `I2C`.
- `CAN`.
- `SerialBase`.
- `SerialBase` (and hence `Serial` and `UARTSerial`).

#### Console and deep sleep

By default, on entry to `main`, the deep sleep lock is not held, so deep sleep is possible until a driver or other code locks it.

However, if `platform.stdio-buffered-serial` is set to true, then `UARTSerial` installs an interrupt handler to receive serial data for `stdin`. This blocks deep sleep. To permit deep sleep, you must suspend input (permanently or temporarily). Making the call `mbed_file_handle(STDIN_FILENO)->enable_input(false)` from the application gives the console driver, whatever it is, permission to stop reception. If `UARTSerial` provides `stdin`, this removes the receive interrupt handler and releases the deep sleep lock.

For more information, please see [`FileHandle`](filehandle.html).

#### Sleep/Deep sleep profiling tool

Mbed OS can help you to understand the sleep patterns of your device, specifically who is holding a sleep locks preventing your board to enter the deep sleep. To enable the tracing, all you need to do is to define `MBED_SLEEP_TRACING_ENABLED` macro. You can do it by modifying your `mbed_app.json` config file or appending `-DMBED_SLEEP_TRACING_ENABLED` to `mbed compile` command.

Mbed OS will print sleep traces on the standard output, which by default is UART. Some of the events that we track:

* Locking deep sleep: `LOCK: <file name>, ln: <line in file>, lock count: <number of locks held>`
* Unlocking deep sleep: `UNLOCK: <file name>, ln: <line in file>, lock count: <number of locks held>`
* Entering sleep: Mbed OS will print a list of locks preventing the board from entering a deep sleep:
- Locking deep sleep: `LOCK: <file name>, ln: <line in file>, lock count: <number of locks held>`.
- Unlocking deep sleep: `UNLOCK: <file name>, ln: <line in file>, lock count: <number of locks held>`.
- Entering sleep: Mbed OS will print a list of locks preventing the board from entering a deep sleep:

```
Sleep locks held:
Expand Down