Skip to content

Commit 526f98a

Browse files
committed
docs(libraries): add missing built-in library pages
Document the I3C, IWatchdog, RGB_LED_TLC59731, SoftwareSerial and SubGhz built-in libraries under docs/libraries/built-in and add them to the navigation and to the libraries overview. Remove the IWatchdog README, now duplicated by its documentation page, and point its library.properties url and the libraries overview to the new page. Signed-off-by: Frederic Pillon <frederic.pillon@st.com> Assisted-by: GitHub Copilot: Claude Sonnet 5.5
1 parent 76602b0 commit 526f98a

9 files changed

Lines changed: 495 additions & 139 deletions

File tree

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
# I3C
2+
3+
## Introduction
4+
5+
The I3C library gives access to the I3C peripheral (MIPI I3C) of the STM32
6+
series that provide it (the core enables it for STM32C5, STM32H5 and STM32U3). The
7+
peripheral can work as a **controller** or as a **target**, on a pure I3C bus or
8+
on a mixed bus with legacy I2C devices.
9+
10+
The library defines the `I3CBus` class and a predefined instance named `I3C`.
11+
Everything is only available when the device has an I3C peripheral
12+
(`I3C1_BASE` or `I3C2_BASE`).
13+
14+
```Arduino
15+
#include <I3C.h>
16+
```
17+
18+
Conventions:
19+
20+
* Addresses are 7-bit addresses.
21+
* Timeouts are in milliseconds (default: 1000).
22+
* Transfer functions return `0` on success and a negative value on error: `-1`
23+
if the arguments are invalid or the bus is not initialized in the expected
24+
role, otherwise the opposite of the HAL error code.
25+
26+
The default pins are `I3C_SDA` and `I3C_SCL`. SDA and SCL must belong to the
27+
same I3C peripheral.
28+
29+
## Controller
30+
31+
### Initialization
32+
33+
```Arduino
34+
#include <I3C.h>
35+
36+
I3CDiscoveredDevice devices[8];
37+
38+
void setup() {
39+
if (!I3C.begin(I3C_SDA, I3C_SCL, 1000000U)) {
40+
while (1) {}
41+
}
42+
43+
size_t found = 0;
44+
I3C.discover(devices, 8, &found); // assign dynamic addresses (DAA)
45+
46+
uint8_t value;
47+
for (size_t i = 0; i < found; i++) {
48+
I3C.readReg(devices[i].dynAddr, 0x0F, value);
49+
}
50+
}
51+
```
52+
53+
| Method | Description |
54+
| ------ | ----------- |
55+
| `bool begin(uint32_t freq = 1000000, I3CBusType type = I3CBusType::Pure, uint32_t mixedOdHz = 1000000)` | Starts the controller on the default pins. `freq` is the push-pull frequency in Hz. |
56+
| `bool begin(pin_size_t sda, pin_size_t scl, uint32_t freq = 1000000, I3CBusType type = I3CBusType::Pure, uint32_t mixedOdHz = 1000000)` | Starts the controller on the given pins. |
57+
| `bool begin(..., const I3CControllerConfig &ctrlCfg)` | Same as above with a controller configuration (FIFO thresholds, stall options, ...). Both pin variants exist. |
58+
| `bool setClock(uint32_t hz)` | Changes the push-pull frequency. |
59+
| `void setBusType(I3CBusType type)` / `I3CBusType getBusType()` | Sets or gets the bus type for the next timing computation: `I3CBusType::Pure` or `I3CBusType::Mixed`. |
60+
| `void setMixedBusOpenDrainFrequency(uint32_t hz)` / `uint32_t getMixedBusOpenDrainFrequency()` | Sets or gets the open-drain frequency of a mixed bus. |
61+
| `I3CRole getRole()` | `I3CRole::None`, `I3CRole::Controller` or `I3CRole::Target`. |
62+
| `bool isController()` / `bool isTarget()` | Role of the instance. |
63+
| `bool flushAllFifos()` | Flushes all the FIFOs of the peripheral. |
64+
| `void end()` | Disables the peripheral, its pins and its clock. |
65+
66+
### Transfers to I3C targets
67+
68+
Private SDR transfers using the dynamic address of the target.
69+
70+
| Method | Description |
71+
| ------ | ----------- |
72+
| `int write(uint8_t dynAddr, const uint8_t *buf, size_t len, uint32_t timeout = 1000)` | Writes `len` bytes (`len` must not be 0). |
73+
| `int read(uint8_t dynAddr, uint8_t *buf, size_t len, uint32_t timeout = 1000)` | Reads `len` bytes. |
74+
| `int writeReg(uint8_t dynAddr, uint8_t reg, uint8_t value, uint32_t timeout = 1000)` | Writes a register. |
75+
| `int readReg(uint8_t dynAddr, uint8_t reg, uint8_t &value, uint32_t timeout = 1000)` | Reads a register. |
76+
| `int writeRegBuffer(uint8_t dynAddr, uint8_t reg, const uint8_t *pData, size_t len, uint32_t timeout = 1000)` | Writes consecutive registers. |
77+
| `int readRegBuffer(uint8_t dynAddr, uint8_t reg, uint8_t *pData, size_t len, uint32_t timeout = 1000)` | Reads consecutive registers. |
78+
79+
### Unified transfers
80+
81+
The same functions exist with an extra `I3CTransferType type` parameter before
82+
the timeout, to select the transport at run time: `I3CTransferType::I3C`
83+
(`addr` is the dynamic address) or `I3CTransferType::I2C` (`addr` is the static
84+
address). This allows a driver to talk to a device whichever the bus it is on.
85+
86+
### Legacy I2C devices (mixed bus)
87+
88+
Available only in controller mode, when the bus type is `I3CBusType::Mixed`.
89+
Static addresses range from 0x08 to 0x77.
90+
91+
| Method | Description |
92+
| ------ | ----------- |
93+
| `int i2cWrite(uint8_t staticAddr, const uint8_t *buf, size_t len, uint32_t timeout = 1000)` | Writes data. |
94+
| `int i2cRead(uint8_t staticAddr, uint8_t *buf, size_t len, uint32_t timeout = 1000)` | Reads data. |
95+
| `int i2cWriteRead(uint8_t staticAddr, const uint8_t *txBuf, size_t txLen, uint8_t *rxBuf, size_t rxLen, uint32_t timeout = 1000)` | Writes then reads with a repeated start. |
96+
| `int i2cWriteReg(...)` / `int i2cReadReg(...)` | Writes or reads one register. |
97+
| `int i2cWriteRegBuffer(...)` / `int i2cReadRegBuffer(...)` | Writes or reads consecutive registers. |
98+
| `int scanI2CDevices(uint8_t *addrs, size_t maxAddrs, size_t *foundCount, uint32_t trials = 2, uint32_t timeout = 10)` | Scans the legacy I2C devices and marks their addresses as used. |
99+
100+
### Device readiness
101+
102+
| Method | Description |
103+
| ------ | ----------- |
104+
| `bool isI3CDeviceReady(uint8_t dynAddr, uint32_t trials = 3, uint32_t timeout = 10)` | Checks that an I3C device acknowledges its dynamic address. |
105+
| `bool isI2CDeviceReady(uint8_t staticAddr, uint32_t trials = 3, uint32_t timeout = 10)` | Checks that an I2C device acknowledges its address. |
106+
107+
### Discovery and dynamic addresses
108+
109+
| Method | Description |
110+
| ------ | ----------- |
111+
| `int discover(I3CDiscoveredDevice *discovered, size_t maxDiscovered, size_t *outCount, uint8_t firstDynAddr = 0x10)` | Resets the dynamic addresses, then assigns them to all the devices with the DAA (ENTDAA). |
112+
| `int discover(const I3CKnownDevice *knownDevices, size_t numKnownDevices, I3CDiscoveredDevice *discovered, size_t maxDiscovered, size_t *outCount, bool discoverUnknown = true, uint8_t firstDynAddr = 0x10)` | Assigns the known devices (SETDASA), then optionally discovers the unknown ones. |
113+
| `int discover(const I3CBusBeginConfig &cfg, const I3CKnownDevice *knownDevices, size_t numKnownDevices, I3CDiscoveredDevice *discovered, size_t maxDiscovered, size_t *outCount)` | Runs the full initialization sequence selected by `cfg`. |
114+
| `int assignDynamicAddresses(I3CDiscoveredDevice *devices, size_t maxDevices, uint8_t firstDynAddr = 0x10, uint32_t timeout = 1000)` | Runs the DAA only. Returns the number of devices found, or a negative value on error. |
115+
116+
`discover()` returns `0` on success and stores the number of devices in `outCount`.
117+
118+
Descriptions used by these functions:
119+
120+
* `I3CDiscoveredDevice`: `dynAddr`, `staticAddr`, `bcr`, `dcr`, `pid` (48 bits),
121+
and the flags `fromDaa`, `assignedBySetdasa` and `matchedKnown`.
122+
* `I3CKnownDevice`: `pid`, `staticAddr`, `preferredDynAddr`, `supportsSetaasa`
123+
and `present`.
124+
* `I3CBusBeginConfig`: selects the steps of the sequence (`doRstact`,
125+
`doRstdaa`, `disableEvents`, `doSetdasa`, `doDaa`, `retryDaaOnce`,
126+
`allowHotJoinAfterInit`, `firstAutoDynAddr`, `discoverUnknownAfterKnown`).
127+
128+
### Common command codes (CCC)
129+
130+
| Method | Description |
131+
| ------ | ----------- |
132+
| `bool resetDynamicAddresses()` | RSTDAA broadcast. |
133+
| `bool disableEvents(const uint8_t *pCCCData, uint16_t length)` | DISEC broadcast. |
134+
| `bool assignAllStaticAsDynamic()` | SETAASA broadcast. |
135+
| `bool assignDynamicAddress(uint8_t staticAddr, uint8_t dynAddr)` | SETDASA direct command. |
136+
| `bool getbcr(uint8_t dynAddr, uint8_t &bcr, uint32_t timeout = 1000)` | GETBCR. |
137+
| `bool getdcr(uint8_t dynAddr, uint8_t &dcr, uint32_t timeout = 1000)` | GETDCR. |
138+
| `bool getpid(uint8_t dynAddr, uint64_t &pid, uint32_t timeout = 1000)` | GETPID. |
139+
| `bool setEvents(uint8_t dynAddr, bool enable, uint8_t events, uint32_t timeout = 1000)` | ENEC/DISEC direct command. `events`: `0x01` In-Band Interrupt, `0x02` controller role request, `0x08` Hot-Join. |
140+
141+
### In-Band Interrupts (IBI)
142+
143+
| Method | Description |
144+
| ------ | ----------- |
145+
| `int configureControllerDevice(uint8_t deviceIndex, uint8_t dynAddr, bool ibiAck, bool ibiPayload, bool ctrlRoleReqAck = false, bool stopTransfer = false)` | Configures how the controller handles the requests of a target. `deviceIndex` is from 1 to 4. |
146+
| `int enableIbi(uint8_t deviceIndex, uint8_t dynAddr, bool withPayload, bool stopTransfer = false, uint32_t timeout = 1000)` | Configures the controller and enables the IBI event on the target. |
147+
| `int enableControllerEvents(uint32_t interruptMask = LL_I3C_IER_IBIIE)` / `int disableControllerEvents(...)` | Enables or disables the controller event notifications. |
148+
| `bool hasIbi()` | `true` if an IBI was received and not read yet. |
149+
| `bool readIbi(I3CControllerIbiInfo &out)` | Reads and clears the last IBI. |
150+
| `bool peekIbi(I3CControllerIbiInfo &out)` | Reads the last IBI without clearing it. |
151+
| `void onIbi(I3CIbiCallback cb, void *user = nullptr)` | Registers a callback, `NULL` to unregister. |
152+
153+
`I3CControllerIbiInfo` contains `pending`, `eventId`, `sourceDa`, `payloadSize`,
154+
`payloadRaw` and `timestampMs`.
155+
156+
> [!NOTE]
157+
> The callback registered with `onIbi()` is called from the interrupt context.
158+
159+
## Target
160+
161+
```Arduino
162+
#include <I3C.h>
163+
164+
uint8_t rxBuf[16];
165+
166+
void setup() {
167+
I3CTargetConfig cfg{};
168+
cfg.identifier = 0x62; // DCR
169+
cfg.mipiIdentifier = 0x1;
170+
171+
if (!I3C.beginTarget(I3C_SDA, I3C_SCL, cfg)) {
172+
while (1) {}
173+
}
174+
175+
while (!I3C.hasAddress()) { // wait for the controller to assign an address
176+
delay(10);
177+
}
178+
179+
I3C.receive(rxBuf, sizeof(rxBuf), 10000);
180+
}
181+
```
182+
183+
| Method | Description |
184+
| ------ | ----------- |
185+
| `bool beginTarget(const I3CTargetConfig &cfg)` | Starts the target on the default pins. |
186+
| `bool beginTarget(pin_size_t sda, pin_size_t scl, const I3CTargetConfig &cfg)` | Starts the target on the given pins. |
187+
| `int configureTarget(const I3CTargetConfig &cfg)` | Applies a target configuration. |
188+
| `bool hasAddress()` / `uint8_t address()` | Tells whether the controller assigned a dynamic address, and returns it (`0` if none). |
189+
| `int send(uint8_t *buf, uint16_t len, uint32_t timeout = 1000)` | Sends data to the controller. |
190+
| `int receive(uint8_t *buf, uint16_t len, uint32_t timeout = 1000)` | Receives data from the controller. |
191+
| `int sendIbi(const uint8_t *payload, uint8_t payloadSize, uint32_t timeout = 1000)` | Requests an IBI. |
192+
| `int enableTargetEvents(const I3CTargetEventConfig &cfg, uint32_t interruptMask)` / `int disableTargetEvents(uint32_t interruptMask)` | Enables or disables the notification of the target events. |
193+
| `bool hasTargetEvent()` | `true` if an event was notified and not read yet. |
194+
| `bool readTargetEvent(uint32_t &eventId)` | Reads and clears the last event. |
195+
| `bool getTargetCccInfo(uint32_t eventId, I3CTargetCccInfo &out)` | Gets the content of an ENEC/DISEC CCC received by the target. |
196+
197+
`I3CTargetConfig` sets, among others, the DCR (`identifier`), the MIPI instance
198+
ID (`mipiIdentifier`), the requests the target can raise (`hotJoinRequest`,
199+
`ibiRequest`, `ibiPayload`, `ctrlRoleRequest`) and the maximum read and write
200+
sizes.
201+
202+
## Examples
203+
204+
The library provides these examples: `BasicBegin`, `ScanBus`, `DeviceReady`,
205+
`Controller_Target` (`ControllerWrite` and `TargetReceive`), `TargetIBI` and
206+
`TargetNotifications` (each with a `Controller` and a `Target` sketch).
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# IWatchdog
2+
3+
## Introduction
4+
5+
The IWatchdog library provides an interface to the independent watchdog
6+
(IWDG) of the STM32 microcontrollers. The IWDG generates a reset of the CPU
7+
when the software becomes stuck or unresponsive.
8+
9+
The IWDG contains a down-counter. When it reaches zero, the microcontroller is
10+
reset. In normal operation the software reloads the counter periodically to
11+
prevent the reset. If a software error keeps the CPU away from the reload for
12+
too long, the IWDG resets the CPU.
13+
14+
## Usage
15+
16+
The library is delivered with the STM32 core. Include its header in the sketch:
17+
18+
```Arduino
19+
#include <IWatchdog.h>
20+
21+
void setup() {
22+
// Reset the CPU if the watchdog is not reloaded within 4 seconds.
23+
IWatchdog.begin(4000000);
24+
}
25+
26+
void loop() {
27+
// ... code executed in less than 2 seconds to keep 50% headroom ...
28+
IWatchdog.reload();
29+
}
30+
```
31+
32+
A default instance named `IWatchdog` is available. See the `IWDG_Button`
33+
example of the library.
34+
35+
> [!WARNING]
36+
> Once started, the IWDG cannot be stopped. A debugging session can be reset
37+
> by the watchdog while the CPU is halted. Also consider the watchdog when the
38+
> CPU is put in a low power mode.
39+
40+
## Timeout and window
41+
42+
Timeouts are in **microseconds**. Plan to reload the counter at least twice as
43+
often as the timeout: `reload()` is not expensive. A very large timeout leaves
44+
the system stuck for a long time before the reset.
45+
46+
The valid range depends on the LSI clock. With a 32 kHz LSI it goes from 125 µs
47+
to about 32.8 s, and the precision depends on the value:
48+
49+
| Timeout range | Precision |
50+
| ------------------- | --------- |
51+
| 125 µs - 512 ms | 125 µs |
52+
| 513 ms - 1024 ms | 250 µs |
53+
| 1025 ms - 2048 ms | 500 µs |
54+
| 2049 ms - 4096 ms | 1 ms |
55+
| 4097 ms - 8192 ms | 2 ms |
56+
| 8193 ms - 16384 ms | 4 ms |
57+
| 16385 ms - 32768 ms | 8 ms |
58+
59+
The optional window must be less than the timeout. When the window is enabled,
60+
the counter has to be reloaded inside the window, otherwise a reset is
61+
generated.
62+
63+
> [!NOTE]
64+
> The window feature is not available on all STM32 series.
65+
66+
## API
67+
68+
| Method | Description |
69+
| ------ | ----------- |
70+
| `void begin(uint32_t timeout, uint32_t window = IWDG_TIMEOUT_MAX)` | Initializes and starts the IWDG. `timeout` and `window` are in microseconds. Returns without starting the IWDG if `timeout` is out of the valid range. |
71+
| `void reload()` | Reloads the counter. Call it periodically once the IWDG is started. |
72+
| `void set(uint32_t timeout, uint32_t window = IWDG_TIMEOUT_MAX)` | Sets the timeout and window values. Same parameters as `begin()`. |
73+
| `void get(uint32_t *timeout, uint32_t *window = NULL)` | Gets the current timeout and window values, in microseconds. |
74+
| `bool isEnabled()` | Returns `true` if the IWDG has been started. |
75+
| `bool isReset(bool clear = false)` | Returns `true` if the last reset was caused by the IWDG. Clears the IWDG reset flag if `clear` is `true`. |
76+
| `void clearReset()` | Clears the IWDG reset flag. |
77+
78+
| Constant | Description |
79+
| -------- | ----------- |
80+
| `IWDG_TIMEOUT_MIN` | Minimal timeout in microseconds. |
81+
| `IWDG_TIMEOUT_MAX` | Maximal timeout in microseconds. |
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# RGB_LED_TLC59731
2+
3+
## Introduction
4+
5+
The RGB_LED_TLC59731 library drives an RGB LED controlled by a TLC59731 driver
6+
through its single wire interface. For example, the STM32WB5MM-DK board has
7+
such a LED.
8+
9+
## Usage
10+
11+
```Arduino
12+
#include <RGB_LED_TLC59731.h>
13+
14+
RGB_LED_TLC59731 myLED;
15+
16+
void setup() {
17+
myLED.setBrightness(0x10);
18+
}
19+
20+
void loop() {
21+
myLED.on(RGB_LED_TLC59731::RED);
22+
delay(500);
23+
myLED.off();
24+
delay(500);
25+
}
26+
```
27+
28+
On the STM32WB5MM-DK, the LED data pin is `RGB_LED` and the enable pin is
29+
`LED_SELECT`: `RGB_LED_TLC59731 myLED(RGB_LED, LED_SELECT);`.
30+
It also requires JP5 on and JP4 off. See the `RGB_LED_TLC59731` example of the
31+
library.
32+
33+
## API
34+
35+
| Method | Description |
36+
| ------ | ----------- |
37+
| `RGB_LED_TLC59731(pin_size_t rgb_pin = LED_BUILTIN, pin_size_t enable_pin = NC)` | Creates the driver. `rgb_pin` is connected to the TLC59731 data input and `enable_pin` to its enable line, `NC` if not used. |
38+
| `void on(uint8_t rgb[3])` | Sets the LED color from an array of red, green and blue values in `[0-255]`. The pins are configured on the first call. |
39+
| `void on(uint8_t red, uint8_t green, uint8_t blue)` | Sets the LED color from the red, green and blue values in `[0-255]`. |
40+
| `void off()` | Turns the LED off and releases its pins. |
41+
| `void setBrightness(uint8_t value)` | Sets the brightness in `[0-255]`, applied to the predefined colors. The LED is only updated by a following call to `on()` with a predefined color. |
42+
| `uint8_t getBrightness()` | Returns the current brightness value. |
43+
44+
### Predefined colors
45+
46+
`RGB_LED_TLC59731::OFF`, `RED`, `GREEN`, `BLUE`, `MAGENTA`, `CYAN`, `YELLOW`
47+
and `WHITE`. They are `uint8_t[3]` arrays whose active channels use the
48+
brightness value (default `0x41`, can be changed with `DEFAULT_BRIGHTNESS` or
49+
`setBrightness()`).

0 commit comments

Comments
 (0)