Skip to content

Commit 5929c90

Browse files
kenbelldeadprogram
authored andcommitted
i2c: document i2c target mode
1 parent c1cfc23 commit 5929c90

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

content/docs/concepts/peripherals/i2c.md

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ You could think of this auto-increment behavior as reading a file. Step 1 opens
3535

3636
Writing is very similar. The main difference is that the controller writes data to the peripheral instead of starting to read bytes after the initial register number is written to the peripheral.
3737

38+
## Target mode
39+
40+
Typically, I2C peripherals are used in controller mode to communicate with sensors and other devices. In I2C target mode, the peripheral instead takes the role of the target (i.e. the role of a sensor/similar device). In this case, the application logic is responsible for processing and responding to messages initiated by an I2C controller, according to this flow diagram:
41+
42+
![I2C Target Flow](/images/i2c-target-flow.png)
43+
3844
## Interacting with a device
3945

4046
For this example, we'll use the [MPU6050](https://invensense.tdk.com/products/motion-tracking/6-axis/mpu-6050/) which is a very common (but old) sensor that measures acceleration and rotation. We won't be doing much interesting with it, but it serves as a great introduction into how to work with I2C peripherals with TinyGo.

content/docs/reference/machine.md

+36-2
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,17 @@ type I2CConfig struct {
148148
Frequency uint32
149149
SCL Pin
150150
SDA Pin
151+
Mode I2CMode
151152
}
152153
```
153154

154155
The `I2CConfig` struct contains the configuration for the I2C peripheral.
155156

156157
* `Frequency` can be set to either 100kHz (`100e3`), 400kHz (`400e3`), and sometimes to other values depending on the chip. The zero value defaults to 100kHz.
157158
* `SCL` and `SDA` can be set as desired, however support for different pins than the default is limited. Some chips are flexible and allow the use of any pin, while other boards only allow a limited range of pins or use fixed SCL/SDA pins. When both pins are left at the zero value, the default for the particular board is used.
158-
159+
* `Mode` is present on peripherals that support I2C target mode. The default
160+
is I2C controller mode, setting `Mode` to `I2CModeTarget` will configure the
161+
peripheral as an I2C target.
159162
```go
160163
type I2C struct {
161164
// values are unexported or vary by chip
@@ -179,8 +182,39 @@ The `Configure` call enables and configures the hardware I2C for use, setting th
179182
func (i2c I2C) Tx(addr uint16, w, r []byte) error
180183
```
181184

182-
The `Tx` call performs the actual I2C transaction. It first writes the bytes in `w` to the peripheral device indicated in `addr` and then reads `r` bytes from the peripheral and stores the read bytes in the `r` slice. It returns an error if the transaction failed. Both `w` and `r` can be `nil`.
185+
_I2C Controller Mode Only_: The `Tx` call performs the actual I2C transaction. It first writes the bytes in `w` to the peripheral device indicated in `addr` and then reads `r` bytes from the peripheral and stores the read bytes in the `r` slice. It returns an error if the transaction failed. Both `w` and `r` can be `nil`.
186+
187+
```go
188+
func (i2c I2C) Listen(addr uint16) error
189+
```
190+
191+
_I2C Target Mode Only_: The `Listen` call starts the I2C peripheral listening for I2C transactions sent
192+
to `addr` by the controller. The peripheral must have been configured in target
193+
mode (see `I2CConfig` struct) before `Listen` is called.
194+
195+
```go
196+
func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err error)
197+
```
198+
199+
_I2C Target Mode Only_: The `WaitForEvent` call blocks the current goroutine waiting for an I2C event. For `I2CReceive` events, the message will be placed in `buf` and return the `count` of bytes received. Oversize messages (those larger than `buf`) will be truncated.
200+
201+
The underlying peripheral will perform clock stretching, if necessary, in two cases:
202+
203+
1. A correctly addressed message is received and the application is not blocked on a call to `WaitForEvent`,
204+
205+
2. The application does not call `Reply` with a single I2C clock cycle for `I2CRequest` events.
206+
207+
Although the I2C target may perform clock stretching, controllers may implement arbitrary timeouts for pending devices. To avoid timeouts from the perspective a controller, the application should:
208+
209+
1. Handle the returned event in a timely manner, calling `Reply` if appropriate.
210+
211+
2. Not have any go routines that may block indefinitely as `WaitForEvent` may yield the CPU to another go routine while waiting for an event.
212+
213+
```go
214+
func (i2c I2C) Reply(buf []byte) error
215+
```
183216

217+
_I2C Target Mode Only_: The `Reply` call sends a response to the controller when an `I2CRequest` event is received by the target.
184218

185219
## UART
186220

static/images/i2c-target-flow.png

21.7 KB
Loading

0 commit comments

Comments
 (0)