1 |
60 |
zero_gravi |
<<<
|
2 |
|
|
:sectnums:
|
3 |
|
|
==== Two-Wire Serial Interface Controller (TWI)
|
4 |
|
|
|
5 |
|
|
[cols="<3,<3,<4"]
|
6 |
|
|
[frame="topbot",grid="none"]
|
7 |
|
|
|=======================
|
8 |
|
|
| Hardware source file(s): | neorv32_twi.vhd |
|
9 |
|
|
| Software driver file(s): | neorv32_twi.c |
|
10 |
|
|
| | neorv32_twi.h |
|
11 |
|
|
| Top entity port: | `twi_sda_io` | 1-bit bi-directional serial data
|
12 |
|
|
| | `twi_scl_io` | 1-bit bi-directional serial clock
|
13 |
|
|
| Configuration generics: | _IO_TWI_EN_ | implement TWI controller when _true_
|
14 |
|
|
| CPU interrupts: | fast IRQ channel 7 | transmission done interrupt (see <<_processor_interrupts>>)
|
15 |
|
|
|=======================
|
16 |
|
|
|
17 |
|
|
**Theory of Operation**
|
18 |
|
|
|
19 |
|
|
The two wire interface – also called "I²C" – is a quite famous interface for connecting several on-board
|
20 |
|
|
components. Since this interface only needs two signals (the serial data line `twi_sda_io` and the serial
|
21 |
|
|
clock line `twi_scl_io`) – despite of the number of connected devices – it allows easy interconnections of
|
22 |
|
|
several peripheral nodes.
|
23 |
|
|
|
24 |
|
|
The NEORV32 TWI implements a **TWI controller**. It features "clock stretching" (if enabled via the control
|
25 |
|
|
register), so a slow peripheral can halt the transmission by pulling the SCL line low. Currently, **no multi-controller
|
26 |
|
|
support** is available. Also, the NEORV32 TWI unit cannot operate in peripheral mode.
|
27 |
|
|
|
28 |
|
|
The TWI is enabled via the _TWI_CT_EN_ bit in the _TWI_CT_ control register. The user program can start / stop a
|
29 |
|
|
transmission by issuing a START or STOP condition. These conditions are generated by setting the
|
30 |
|
|
according bits (_TWI_CT_START_ or _TWI_CT_STOP_) in the control register.
|
31 |
|
|
|
32 |
|
|
Data is send by writing a byte to the _TWI_DATA_ register. Received data can also be read from this
|
33 |
|
|
register. The TWI controller is busy (transmitting data or performing a START or STOP condition) as long as the
|
34 |
|
|
_TWI_CT_BUSY_ bit in the control register is set.
|
35 |
|
|
|
36 |
|
|
An accessed peripheral has to acknowledge each transferred byte. When the _TWI_CT_ACK_ bit is set after a
|
37 |
|
|
completed transmission, the accessed peripheral has send an acknowledge. If it is cleared after a
|
38 |
|
|
transmission, the peripheral has send a not-acknowledge (NACK). The NEORV32 TWI controller can also
|
39 |
|
|
send an ACK by itself ("controller acknowledge _MACK_") after a transmission by pulling SDA low during the
|
40 |
|
|
ACK time slot. Set the _TWI_CT_MACK_ bit to activate this feature. If this bit is cleared, the ACK/NACK of the
|
41 |
|
|
peripheral is sampled in this time slot instead (normal mode).
|
42 |
|
|
|
43 |
|
|
In summary, the following independent TWI operations can be triggered by the application program:
|
44 |
|
|
|
45 |
|
|
* send START condition (also as REPEATED START condition)
|
46 |
|
|
* send STOP condition
|
47 |
|
|
* send (at least) one byte while also sampling one byte from the bus
|
48 |
|
|
|
49 |
|
|
[IMPORTANT]
|
50 |
|
|
The serial clock (SCL) and the serial data (SDA) lines can only be actively driven low by the
|
51 |
|
|
controller. Hence, external pull-up resistors are required for these lines.
|
52 |
|
|
|
53 |
|
|
The TWI clock frequency is defined via the 3-bit _TWI_CT_PRSCx_ clock prescaler. The following prescalers
|
54 |
|
|
are available:
|
55 |
|
|
|
56 |
|
|
.TWI prescaler configuration
|
57 |
|
|
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
|
58 |
|
|
[options="header",grid="rows"]
|
59 |
|
|
|=======================
|
60 |
|
|
| **`TWI_CT_PRSCx`** | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
|
61 |
|
|
| Resulting `clock_prescaler` | 2 | 4 | 8 | 64 | 128 | 1024 | 2048 | 4096
|
62 |
|
|
|=======================
|
63 |
|
|
|
64 |
|
|
Based on the _TWI_CT_PRSCx_ configuration, the actual TWI clock frequency f~SCL~ is derived from the processor main clock f~main~ and is determined by:
|
65 |
|
|
|
66 |
|
|
_**f~SCL~**_ = _f~main~[Hz]_ / (4 * `clock_prescaler`)
|
67 |
|
|
|
68 |
|
|
.TWI register map
|
69 |
|
|
[cols="<2,<2,<4,^1,<7"]
|
70 |
|
|
[options="header",grid="all"]
|
71 |
|
|
|=======================
|
72 |
|
|
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
73 |
|
|
.10+<| `0xffffffb0` .10+<| _TWI_CT_ <|`0` _TWI_CT_EN_ ^| r/w <| TWI enable
|
74 |
|
|
<|`1` _TWI_CT_START_ ^| r/w <| generate START condition
|
75 |
|
|
<|`2` _TWI_CT_STOP_ ^| r/w <| generate STOP condition
|
76 |
|
|
<|`3` _TWI_CT_PRSC0_ ^| r/w .3+<| 3-bit clock prescaler select
|
77 |
|
|
<|`4` _TWI_CT_PRSC1_ ^| r/w
|
78 |
|
|
<|`5` _TWI_CT_PRSC2_ ^| r/w
|
79 |
|
|
<|`6` _TWI_CT_MACK_ ^| r/w <| generate controller ACK for each transmission ("MACK")
|
80 |
|
|
<|`7` _TWI_CT_CKSTEN_ ^| r/w <| allow clock-stretching by peripherals when set
|
81 |
|
|
<|`30` _TWI_CT_ACK_ ^| r/- <| ACK received when set
|
82 |
|
|
<|`31` _TWI_CT_BUSY_ ^| r/- <| transfer/START/STOP in progress when set
|
83 |
|
|
| `0xffffffb4` | _TWI_DATA_ |`7:0` _TWI_DATA_MSB_ : TWI_DATA_LSB_ | r/w | receive/transmit data
|
84 |
|
|
|=======================
|