|
| 1 | +# Inter-integrated circuit (I2C) |
| 2 | + |
| 3 | +I2C is a serial protocol for two-wire interface to connect low-speed devices in embedded systems. The I2C API allows control and configuration of this interface. |
| 4 | + |
| 5 | +The interface is made up of two lines for all communication: |
| 6 | + |
| 7 | +- Serial Clock (SCL). |
| 8 | +- Serial Data (SDA). |
| 9 | + |
| 10 | +<span class="warnings">**Warning:** We are introducing the I2C 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 I2C API](#implementing-the-i2c-api) section. |
| 11 | + |
| 12 | +## Defined behaviors |
| 13 | + |
| 14 | +- `i2c_init`: |
| 15 | + - Initializes the peripheral pins specified in the input parameters. |
| 16 | + - Initializes the peripheral in master mode if `is_slave` is false. |
| 17 | + - Initializes the peripheral in slave mode if `is_slave` is true and `supports_slave_mode` is true. |
| 18 | + - Initializes all `i2c_t` object fields. |
| 19 | +- `i2c_free`: |
| 20 | + - Resets the pins used to initialize the peripheral to their default state. |
| 21 | + - Disables the peripheral clock. |
| 22 | +- `i2c_get_capabilities`: |
| 23 | + - Fills the contents of the `i2c_capabilities_t` parameter. |
| 24 | +- `i2c_frequency`: |
| 25 | + - Sets the frequency to use for the transfer. |
| 26 | + - Returns the actual frequency used. |
| 27 | + - Must leave all other configuration unchanged. |
| 28 | +- `i2c_set_clock_stretching`: |
| 29 | + - Enables or disables clock stretching for the peripheral when in slave mode. |
| 30 | + - Does nothing when called in master mode. |
| 31 | +- `i2c_timeout`: |
| 32 | + - Sets the transmision timeout to use for the following blocking transfers. |
| 33 | + - If the timeout is not set, the default timeout is used. |
| 34 | + - Default timeout value is based on I2C frequency and computed as triple the amount of time it takes to send data over I2C. |
| 35 | +- `i2c_write`: |
| 36 | + - Writes `length` number of symbols to the bus. |
| 37 | + - Returns the number of symbols sent to the bus. |
| 38 | + - Returns an error code if transfer fails. |
| 39 | + - Generates a stop condition on the bus at the end of the transfer if `stop` parameter is true. |
| 40 | + - Handles transfer collisions and loss of arbitration if the platform supports multimaster in hardware. |
| 41 | + - The transfer times out and returns `I2C_ERROR_TIMEOUT ` if the transfer takes longer than the configured timeout duration. |
| 42 | +- `i2c_read`: |
| 43 | + - Reads `length` symbols from the bus. |
| 44 | + - Returns the number of symbols received from the bus. |
| 45 | + - Returns an error code if transfer fails. |
| 46 | + - Generates a stop condition on the bus at the end of the transfer if `stop` parameter is true. |
| 47 | + - Handles transfer collisions and loss of arbitration if the platform supports multimaster in hardware. |
| 48 | + - The transfer times out and returns `I2C_ERROR_TIMEOUT ` if the transfer takes longer than the configured timeout duration. |
| 49 | +- `i2c_start`: |
| 50 | + - Generates I2C START condition on the bus in master mode. |
| 51 | + - Does nothing if called when the peripheral is configured in slave mode. |
| 52 | +- `i2c_stop`: |
| 53 | + - Generates I2C STOP condition on the bus in master mode. |
| 54 | + - Does nothing if called when the peripheral is configured in slave mode. |
| 55 | +- `i2c_slave_status`: |
| 56 | + - Indicates in which mode the peripheral has been addressed. |
| 57 | + - Returns not addressed when called in master mode. |
| 58 | +- `i2c_slave_address`: |
| 59 | + - Sets the address of the peripheral to the `address` parameter. |
| 60 | + - Does nothing if called in master mode. |
| 61 | +- `i2c_transfer_async`: |
| 62 | + - Returns immediately with a `bool` indicating whether the transfer was successfully scheduled. |
| 63 | + - The callback given to `i2c_transfer_async` is invoked when the transfer finishes or error occurs. |
| 64 | + - Must save the handler and context pointers inside the `obj` pointer. |
| 65 | + - The context pointer is passed to the callback on transfer completion. |
| 66 | + - The callback must be invoked on completion unless the transfer is aborted. |
| 67 | + - May handle transfer collisions and loss of arbitration if the platform supports multimaster in hardware and enabled in API. |
| 68 | + - `i2c_async_event_t` must be filled with the number of symbols sent to the bus during transfer. |
| 69 | +- `i2c_abort_async`: |
| 70 | + - Aborts any ongoing async transfers. |
| 71 | + |
| 72 | +## Undefined behaviors |
| 73 | + |
| 74 | +- Use of a `null` pointer as an argument to any function. |
| 75 | +- Calling any `I2C` function before calling `i2c_init` or after calling `i2c_free`. |
| 76 | +- Initializing the `I2C` peripheral with invalid `SDA` and `SCL` pins. |
| 77 | +- Initializing the peripheral in slave mode if slave mode is not supported, indicated by `i2c_get_capabilities`. |
| 78 | +- Operating the peripheral in slave mode without first specifying and address using `i2c_slave_address`. |
| 79 | +- Setting an address using `i2c_slave_address` after initializing the peripheral in master mode. |
| 80 | +- Setting an address to an `I2C` reserved value. |
| 81 | +- Setting an address larger than the 7-bit supported maximum if 10-bit addressing is not supported. |
| 82 | +- Setting an address larger than the 10-bit supported maximum. |
| 83 | +- Setting a frequency outside the supported range given by `i2c_get_capabilities`. |
| 84 | +- Using the device in a multimaster configuration when `supports_multimaster_mode` is false. |
| 85 | +- Specifying an invalid address when calling any `read` or `write` functions. |
| 86 | +- Setting the length of the transfer or receive buffers to larger than the buffers are. |
| 87 | +- Passing an invalid pointer as `handler` to `i2c_transfer_async`. |
| 88 | +- Calling `i2c_transfer_abort` when no transfer is currently in progress. |
| 89 | + |
| 90 | +## Notes |
| 91 | + |
| 92 | +You can find more details about the design choices in the [HAL code design document](https://github.com/ARMmbed/mbed-os/blob/feature-i2c/docs/design-documents/hal/0001-i2c-overhaul.md). |
| 93 | + |
| 94 | +## Dependencies |
| 95 | + |
| 96 | +Hardware I2C capabilities. |
| 97 | + |
| 98 | +## Implementing the I2C API |
| 99 | + |
| 100 | +You can find the API and specification for the I2C API in the following class reference: |
| 101 | + |
| 102 | +[](https://os.mbed.com/docs/mbed-os/development/feature-i2c-doxy/classmbed_1_1_i2_c.html) |
| 103 | + |
| 104 | +To enable I2C support in Mbed OS, add the `I2C` label in the `device_has` option of the target's section in the `targets.json` file. |
| 105 | + |
| 106 | +You can also add the `I2C_ASYNCH` label in the `device_has` option to enable the asynchronous API, |
| 107 | +and `I2CSLAVE` to enable the I2CSlave API. |
| 108 | + |
| 109 | +## Testing |
| 110 | + |
| 111 | +The Mbed OS HAL provides a set of conformance tests for I2C. You can use these tests to validate the correctness of your implementation. To run the I2C HAL tests, use the following command: |
| 112 | + |
| 113 | +``` |
| 114 | +mbed test -t <toolchain> -m <target> -n "tests-mbed_hal_fpga_ci_test_shield-i2c" |
| 115 | +``` |
| 116 | + |
| 117 | +You can read more about the test cases: |
| 118 | + |
| 119 | +[](https://os.mbed.com/docs/mbed-os/development/feature-i2c-doxy/group__hal__i2c__tests.html) |
| 120 | + |
0 commit comments