Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
TivaI2C.cxx
Go to the documentation of this file.
1
34#include <algorithm>
35
36#include <stdint.h>
37
38#include "inc/hw_types.h"
39#include "inc/hw_memmap.h"
40#include "inc/hw_ints.h"
41#include "inc/hw_i2c.h"
42#include "driverlib/rom.h"
43#include "driverlib/rom_map.h"
44#include "driverlib/i2c.h"
45#include "driverlib/interrupt.h"
46#include "driverlib/sysctl.h"
47
48#include "TivaDev.hxx"
49
56TivaI2C::TivaI2C(const char *name, unsigned long base, uint32_t interrupt, bool fast_mode)
57 : I2C(name)
58 , base(base)
59 , interrupt(interrupt)
60 , msg_(NULL)
61 , stop_(false)
62 , count_(0)
63 , sem()
64{
65 switch (base)
66 {
67 default:
68 HASSERT(0);
69 case I2C0_BASE:
70 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
71 break;
72 case I2C1_BASE:
73 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
74 break;
75 case I2C2_BASE:
76 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);
77 break;
78 case I2C3_BASE:
79 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);
80 break;
81 case I2C4_BASE:
82 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C4);
83 break;
84 case I2C5_BASE:
85 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C5);
86 break;
87 case I2C6_BASE:
88 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);
89 break;
90 case I2C7_BASE:
91 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C7);
92 break;
93 case I2C8_BASE:
94 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C8);
95 break;
96 case I2C9_BASE:
97 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C9);
98 break;
99 }
100
101 /* default to 100 KHz mode */
102 MAP_I2CMasterInitExpClk(base, cm3_cpu_clock_hz, fast_mode);
103
104 /* We set the priority so that it is slightly lower than the highest needed
105 * for FreeRTOS compatibility. This will ensure that CAN interrupts take
106 * precedence over UART. */
107 MAP_IntPrioritySet(interrupt,
108 std::min(0xff, configKERNEL_INTERRUPT_PRIORITY + 0x20));
109 MAP_I2CMasterIntEnableEx(base, I2C_MASTER_INT_TIMEOUT |
110 I2C_MASTER_INT_DATA);
111}
112
118int TivaI2C::transfer(struct i2c_msg *msg, bool stop)
119{
120 int bytes = msg->len;
121
122 if (msg->flags & I2C_M_RD)
123 {
124 /* this is a read transfer */
125 MAP_I2CMasterSlaveAddrSet(base, msg->addr, true);
126
127 /* generate start */
128 if (stop && msg->len == 1)
129 {
130 /* single byte transfer with stop */
131 MAP_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_RECEIVE);
132 }
133 else
134 {
135 /* more than one byte to transfer */
136 MAP_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_START);
137 }
138 }
139 else
140 {
141 /* this is a write transfer */
142 MAP_I2CMasterSlaveAddrSet(base, msg->addr, false);
143 MAP_I2CMasterDataPut(base, *msg->buf);
144
145 /* generate start */
146 if (stop && msg->len == 1)
147 {
148 /* single byte transfer with stop */
149 MAP_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_SEND);
150 }
151 else
152 {
153 /* more than one byte to transfer */
154 MAP_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_START);
155 }
156 }
157
158 msg_ = msg;
159 count_ = 0;
160 stop_ = stop;
161
162 MAP_IntEnable(interrupt);
163 sem.wait();
164
165 return count_ < 0 ? count_ : bytes;
166}
167
170volatile uint32_t g_error;
173volatile uint32_t g_status;
174
178{
179 int woken = 0;
180 uint32_t error;
181 uint32_t status;
182
183 g_error = error = I2CMasterErr(base);
184 g_status = status = MAP_I2CMasterIntStatusEx(base, true);
185 MAP_I2CMasterIntClearEx(base, status);
186
187 if (error & I2C_MCS_ARBLST)
188 {
189 count_ = -EIO;
190 goto post;
191 }
192 else if (error & I2C_MCS_DATACK)
193 {
194 count_ = -EIO;
195 goto post;
196 }
197 else if (error & I2C_MCS_ADRACK)
198 {
199 count_ = -EIO;
200 goto post;
201 }
202 else if (status & I2C_MASTER_INT_TIMEOUT)
203 {
204 count_ = -ETIMEDOUT;
205 goto post;
206 }
207 else if (status & I2C_MASTER_INT_DATA)
208 {
209 if (msg_->flags & I2C_M_RD)
210 {
211 /* this is a read transfer */
212 msg_->buf[count_++] = I2CMasterDataGet(base);
213 if (count_ == msg_->len)
214 {
215 /* transfer is complete */
216 goto post;
217 }
218 if (stop_ && count_ == (msg_->len - 1))
219 {
220 /* single byte transfer with stop */
221 MAP_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
222 }
223 else
224 {
225 /* more than one byte left to transfer */
226 MAP_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
227 }
228 }
229 else
230 {
231 /* this is a write transfer */
232 if (++count_ == msg_->len)
233 {
234 /* transfer is complete */
235 goto post;
236 }
237 MAP_I2CMasterDataPut(base, msg_->buf[count_]);
238 if (stop_ && count_ == (msg_->len - 1))
239 {
240 /* single byte transfer with stop */
241 MAP_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_FINISH);
242 }
243 else
244 {
245 /* more than one byte left to transfer */
246 MAP_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_CONT);
247 }
248 }
249 return;
250 }
251 else// if (error)
252 {
253 count_ = -EIO;
254 goto post;
255 }
256/* else
257 {
258 // should never get here
259 HASSERT(0 && "I2C invalid status");
260 }*/
261post:
262 MAP_IntDisable(interrupt);
263 sem.post_from_isr(&woken);
264 os_isr_exit_yield_test(woken);
265}
OSSem sem[1]
One semaphore required per instance pointer.
Definition CC32xxSPI.cxx:55
volatile uint32_t g_status
Debugging variable that holds the last master int status seen by the driver.
Definition TivaI2C.cxx:173
volatile uint32_t g_error
Debugging variable that holds the last error encountered by the driver.
Definition TivaI2C.cxx:170
Private data for an I2C device.
Definition I2C.hxx:51
void wait()
Wait on (decrement) a semaphore.
Definition OS.hxx:279
bool stop_
current transaction ends in a stop if true
Definition TivaDev.hxx:326
struct i2c_msg * msg_
message for current transaction
Definition TivaDev.hxx:325
TivaI2C()
Default constructor.
int count_
current count index within transaction
Definition TivaDev.hxx:327
OSSem sem
Semaphore to wakeup task level from ISR.
Definition TivaDev.hxx:330
unsigned long interrupt
interrupt of this device
Definition TivaDev.hxx:324
int transfer(struct i2c_msg *msg, bool stop) OVERRIDE
Method to transmit/receive the data.
Definition TivaI2C.cxx:118
void interrupt_handler()
handle an interrupt.
Definition TivaI2C.cxx:177
unsigned long base
base address of this device
Definition TivaDev.hxx:323
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138