Skip to content
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

drivers/periph: Add documentation on thread safety and initialization #19794

Merged
merged 1 commit into from
Sep 5, 2023
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
58 changes: 58 additions & 0 deletions drivers/include/periph/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,64 @@
* defines a standardized interface to access MCU peripherals that is not tied
* to any specific vendor, platform or architecture.
*
* # Initialization and Thread Safety
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thread gets turned into a hyperlink thanks to automagic and mqtt paho.

Not sure whether there is anything we can do here -- escaping the word is probably a whack-a-mole...

*
* Peripheral drivers fall into three categories regarding to their
* initialization:
*
* 1. Drivers that do not need to be initialized
* (e.g. @ref drivers_periph_eeprom)
* 2. Drivers that are automatically initialized by the module `periph_init` at boot,
* (see @ref drivers_periph_init for details)
* 3. Drivers that require manual initialization (e.g. @ref drivers_periph_uart
* or @ref drivers_periph_adc)
*
* The initialization code of drivers initialized at boot up is *not* thread
* safe. This code is run sequentially anyway and never called by the user, so
* the overhead of thread safety would not be justified.
*
* All other peripheral APIs (including the initialization functions of drivers
* that are not initialized with `periph_init`) are fully or partially thread
* safe. Partially thread safe drivers require the user to make sure that the
* same peripheral entity (e.g. one UART device) is exclusively used by one
* thread. So two threads may concurrently use two *distinct* UART devices
* without any synchronization, but they *must* synchronize explicitly to access
* the same UART device.
*
* Fully thread safe are all bus peripherals: A call to e.g. @ref spi_acquire
* will start a period of exclusive access to the given SPI bus by the calling
* thread until that calls @ref spi_release.
*
* | Peripheral Driver | Initialized By | Thread Safety |
* |:------------------ |:----------------- |:----------------------------------------------------------------------------- |
* | `periph_adc` | user / driver | Partial (no concurrent use of the same ADC line allowed) |
* | `periph_can` | user / driver | Partial (no concurrent use of the same CAN device allowed) |
* | `periph_cpuid` | not needed | Full Thread Safety |
* | `periph_dac` | user / driver | Partial (no concurrent use of the same DAC line allowed) |
* | `periph_eeprom` | not needed | None (no concurrency whatsoever) |
* | `periph_flashpage` | not needed | None (no concurrency whatsoever) |
* | `periph_gpio` | not needed | Limited (reads are fine, concurrent writes to pins on distinct ports work) |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* | `periph_gpio` | not needed | Limited (reads are fine, concurrent writes to pins on distinct ports work) |
* | `periph_gpio` | not needed | Limited (reads are fine, concurrent writes to pins are allowed on distinct ports) |

A lot of things work that are not allowed.

* | `periph_gpio_ll` | not needed | Yes, except for concurrent initialization of the GPIO pin |
* | `periph_hwrng` | `periph_init` | None (no concurrency whatsoever) |
* | `periph_i2c` | `periph_init` | Full Thread Safety (except for initialization) |
* | `periph_pio` | `periph_init` | Full Thread Safety (except for initialization) |
* | `periph_pm` | not needed | Full Thread Safety |
* | `periph_ptp` | `periph_init` | Full Thread Safety (except for initialization) |
* | `periph_pwm` | user / driver | Partial (no concurrent use of the same PWM device) |
* | `periph_qdec` | user / driver | Partial (no concurrent use of the same QDEC device) |
* | `periph_rtc` | `periph_init` | None (no concurrency whatsoever) |
* | `periph_rtt` | `periph_init` | None (no concurrency whatsoever) |
* | `periph_spi` | `periph_init` | Full Thread Safety (except for initialization) |
* | `periph_timer` | user / driver | Yes, except for concurrent initialization of the same timer |
* | `periph_uart` | user / driver | Partial (no concurrent use of the same UART device allowed) |
* | `periph_usbdev` | user / driver (*) | Full Thread Safety (except for initialization) |
* | `periph_vbat` | `periph_init` | None (no concurrency whatsoever) |
* | `periph_wdt` | `periph_init` | Only `wdt_kick()` is thread-safe |
*
* @note `periph_usbdev` requires a low level initialization
* (@ref usbdev_init_lowlevel) that is done by `periph_init`. A per
* device initialization is needed in addition by the user.
*
* @todo describe concept in detail
* @todo link to driver model
* @todo describe/link implementation guide
Expand Down
4 changes: 4 additions & 0 deletions drivers/include/periph/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ extern "C" {
* configured peripheral drivers like SPI or I2C. This function SHOULD be called
* early in the boot process, e.g. before the actual kernel initialization is
* started.
*
* @note This function is called by the boot up code. Application developers
* do not need to care. Developers porting RIOT to a new MCU must make
* sure that this function is called during boot up early on.
*/
void periph_init(void);

Expand Down