Skip to content

Commit 9512c56

Browse files
author
Amanda Butler
authored
Merge pull request #766 from ithinuel/spi_migration_guide
add SPI migration guide
2 parents c4a33b0 + c7180fd commit 9512c56

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

docs/porting/target/spi.md

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<h2 id="spi-port">Serial Peripheral Interface (SPI)</h2>
2+
3+
The **Serial Peripheral Interface** allows you to send or receive a data stream over a synchronous serial interface made of 3 to 4 lines.
4+
5+
- MISO: Master in, slave out.
6+
- MOSI: Master out, slave in.
7+
- MCLK: Clock.
8+
- SS: Slave select.
9+
10+
A typical use case of this interface is with SDCard, memory blocks and DACs or ADCs.
11+
12+
This highly configurable interface has elements you can adjust:
13+
14+
- Frame length.
15+
- Clocks polarity and phase.
16+
17+
<span class="warnings">**Warning:** We are introducing the SPI API in an upcoming release of Mbed OS. This page documents code that exists on a feature branch of Mbed OS. You can find details on how it may affect you in the [implementing the SPI API](#implementing-the-spi-api) section.
18+
19+
### Assumptions
20+
21+
#### Defined behaviors
22+
23+
- `spi_get_module()` returns the `SPIName` unique identifier to the peripheral associated to this SPI channel.
24+
- `spi_get_capabilities()` fills the given `spi_capabilities_t` instance.
25+
- `spi_get_capabilities()` should consider the `ssel` pin when evaluating the `support_slave_mode` capability.
26+
- If the given `ssel` pin cannot be managed by hardware in slave mode, `support_slave_mode` should be false.
27+
- At least a symbol width of 8 bit must be supported.
28+
- The supported frequency range must include the range 0.2-2 MHz.
29+
- The shortest part of the duty cycle must not be shorter than 50% of the expected period.
30+
- `spi_init()` initializes the pins leaving the configuration registers unchanged.
31+
- `spi_init()` if `is_slave` is false:
32+
- If `ssel` is `NC`, the HAL implementation ignores this pin.
33+
- If `ssel` is not `NC`, then the HAL implementation owns the pin and its management.
34+
- When managed by the HAL implementation, `ssel` is always considered active low.
35+
- When the hardware supports the half-duplex (3-wire) mode, if `miso` (exclusive) or `mosi` is missing in any function that expects pins, the bus is assumed to be half-duplex.
36+
- `spi_free()` resets the pins to their default state.
37+
- `spi_free()` disables the peripheral clock.
38+
- `spi_format()` sets:
39+
- The number of bits per symbol.
40+
- The mode:
41+
.0 Clock idle state is *low*, data are sampled when the clock becomes *active* (polarity = 0, phase = 0).
42+
.1 Clock idle state is *low*, data are sampled when the clock becomes *inactive* (polarity = 0, phase = 1).
43+
.2 Clock idle state is *high*, data are sampled when the clock becomes *active* (polarity = 1, phase = 0).
44+
.3 Clock idle state is *high*, data are sampled when the clock becomes *inactive* (polarity = 1, phase = 1).
45+
- The bit ordering (lsb/msb first).
46+
- `spi_format()` updates the configuration of the peripheral except the baud rate generator.
47+
- `spi_frequency()` sets the frequency to use during the transfer.
48+
- `spi_frequency()` returns the actual frequency that is used.
49+
- `spi_frequency()` updates the baud rate generator leaving other configurations unchanged.
50+
- `spi_init()`, `spi_frequency()` and `spi_format()` must be called at least once each before initiating any transfer.
51+
- `spi_transfer()`:
52+
- Writes `tx_len` symbols to the bus.
53+
- Reads `rx_len` symbols from the bus.
54+
- If `rx` is NULL, then inputs are discarded.
55+
- If `tx` is NULL, then `fill_symbol` is used instead.
56+
- Returns the number of symbol clocked on the bus during this transfer.
57+
- Expects symbols types to be the closest stdint type bigger or equal to its size following the platform's endianness. For example:
58+
- 7bits => uint8_t.
59+
- 15bits => uint16_t.
60+
- 16bits => uint16_t.
61+
- 17bits => uint32_t.
62+
- In full-duplex mode:
63+
- If `rx_len` > `tx_len` then it sends `(rx_len-tx_len)` additional `fill_symbol` to the bus.
64+
- In half-duplex mode:
65+
- As master, `spi_transfer()` sends `tx_len` symbols and then reads `rx_len` symbols.
66+
- As slave, `spi_transfer()` receives `rx_len` symbols and then sends `tx_len` symbols.
67+
- `spi_transter_async()` schedules a transfer to be process the same way `spi_transfer()` would have but asynchronously.
68+
- `spi_transter_async()` returns immediately with a boolean indicating whether the transfer was successfully scheduled or not.
69+
- The callback given to `spi_transfer_async()` is invoked when the transfer completes (with a success or an error).
70+
- `spi_transfer_async()` saves the handler and the `ctx` pointer.
71+
- The `ctx` is passed to the callback on transfer completion.
72+
- Unless the transfer is aborted, the callback is invoked on completion. The completion may be when all symbols have been transmitted
73+
or when, in slave mode, the master deasserts the chip select.
74+
- The `spi_transfer_async()` function may use the `DMAUsage` hint to select the appropriate asynchronous algorithm.
75+
- The `spi_async_event_t` must be filled with the number of symbols clocked on the bus during this transfer and a boolean value indicated if an error has occurred.
76+
- `spi_transfer_async_abort()` aborts an ongoing asynchronous transfer.
77+
78+
#### Undefined behaviors
79+
80+
- Calling `spi_init()` multiple times on the same `spi_t` without `spi_free()`'ing it first.
81+
- Calling any method other than `spi_init()` on an uninitialized or freed `spi_t`.
82+
- Passing both `miso` and `mosi` as `NC` to `spi_get_module` or `spi_init`.
83+
- Passing `miso` or `mosi` as `NC` on target that does not support half-duplex mode.
84+
- Passing `mclk` as `NC` to `spi_get_module` or `spi_init`.
85+
- Passing an invalid pointer as `cap` to `spi_get_capabilities`.
86+
- Passing pins that cannot be on the same peripheral.
87+
- Passing an invalid pointer as `obj` to any method.
88+
- Giving an `ssel` pin to `spi_init()` when using in master mode.
89+
- SS must be managed by hardware in slave mode and must **NOT** be managed by hardware in master mode.
90+
- Setting a frequency outside of the range given by `spi_get_capabilities()`.
91+
- Setting a frequency in slave mode.
92+
- Setting `bits` in `spi_format` to a value out of the range given by `spi_get_capabilities()`.
93+
- Passing an invalid pointer as `fill_symbol` to `spi_transfer` and `spi_transfer_async` while they would be required by the transfer (`rx_len != tx_len` or `tx==NULL`).
94+
- Passing an invalid pointer as `handler` to `spi_transfer_async`.
95+
- Calling `spi_transfer_async_abort()` while no asynchronous transfer is being processed (no transfer or a synchronous transfer).
96+
- In half-duplex mode, any mechanism (if any is present) to detect or prevent collision is implementation defined.
97+
98+
#### Other requirements
99+
100+
A target must also define these elements:
101+
102+
- `#define SPI_COUNT (xxxxxU)`.
103+
- The number of SPI peripherals available on the device. A good place for that macro is `PeripheralNames.h` next to the `SPIName` enumeration.
104+
105+
<span class="notes">**Note:** You can find more details about the design choices in the [SPI design document](https://github.com/ARMmbed/mbed-os/blob/feature-hal-spec-spi/docs/design-documents/hal/0000-spi-overhaul.md).</span>
106+
107+
### Dependencies
108+
109+
Hardware SPI capabilities.
110+
111+
### Implementing the SPI API
112+
113+
You can find the API and specification for the SPI API in the following class reference:
114+
115+
[![View code](https://www.mbed.com/embed/?type=library)](http://os.mbed.com/docs/development/feature-hal-spec-spi-doxy/classmbed_1_1_s_p_i.html)
116+
117+
To enable SPI support in Mbed OS, add the `SPI` label in the `device_has` option of the target's section in the `targets.json` file.
118+
You can also add the `SPI_ASYNCH` label in the `device_has` option to enable the asynchronous API.
119+
120+
### Testing
121+
122+
The Mbed OS HAL provides a set of conformance tests for SPI. You can use these tests to validate the correctness of your implementation. To run the SPI HAL tests, use the following command:
123+
124+
```
125+
mbed test -t <toolchain> -m <target> -n "tests-mbed_hal-spi*"
126+
```
127+
128+
You can read more about the test cases:
129+
130+
[![View code](https://www.mbed.com/embed/?type=library)](http://os.mbed.com/docs/development/feature-hal-spec-spi-doxy/group__hal__spi__tests.html)

0 commit comments

Comments
 (0)