Paparazzi UAS  v5.15_devel-99-g2ff7410
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
i2c_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2012 The Paparazzi Team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
30 #include "mcu_periph/i2c.h"
31 
32 #include "std.h"
33 #include BOARD_CONFIG
34 #include "armVIC.h"
35 
37 // I2C Automaton //
39 
40 __attribute__((always_inline)) static inline void I2cSendStart(struct i2c_periph *p)
41 {
42  p->status = I2CStartRequested;
43  ((i2cRegs_t *)(p->reg_addr))->conset = _BV(STA);
44 }
45 
46 __attribute__((always_inline)) static inline void I2cSendAck(void *reg)
47 {
48  ((i2cRegs_t *)reg)->conset = _BV(AA);
49 }
50 
51 __attribute__((always_inline)) static inline void I2cEndOfTransaction(struct i2c_periph *p)
52 {
53  // handle fifo here
54  p->trans_extract_idx++;
55  if (p->trans_extract_idx >= I2C_TRANSACTION_QUEUE_LEN) {
56  p->trans_extract_idx = 0;
57  }
58  // if no more transaction to process, stop here, else start next transaction
59  if (p->trans_extract_idx == p->trans_insert_idx) {
60  p->status = I2CIdle;
61  } else {
62  I2cSendStart(p);
63  }
64 }
65 
66 __attribute__((always_inline)) static inline void I2cSendStop(struct i2c_periph *p, struct i2c_transaction *t)
67 {
68  ((i2cRegs_t *)(p->reg_addr))->conset = _BV(STO);
69  // transaction finished with success
70  t->status = I2CTransSuccess;
72 }
73 
74 __attribute__((always_inline)) static inline void I2cFail(struct i2c_periph *p, struct i2c_transaction *t)
75 {
76  ((i2cRegs_t *)(p->reg_addr))->conset = _BV(STO);
77  // transaction failed
78  t->status = I2CTransFailed;
79  // FIXME I2C should be reseted here ?
81 }
82 
83 __attribute__((always_inline)) static inline void I2cSendByte(void *reg, uint8_t b)
84 {
85  ((i2cRegs_t *)reg)->dat = b;
86 }
87 
88 __attribute__((always_inline)) static inline void I2cReceive(void *reg, bool ack)
89 {
90  if (ack) { ((i2cRegs_t *)reg)->conset = _BV(AA); }
91  else { ((i2cRegs_t *)reg)->conclr = _BV(AAC); }
92 }
93 
94 __attribute__((always_inline)) static inline void I2cClearStart(void *reg)
95 {
96  ((i2cRegs_t *)reg)->conclr = _BV(STAC);
97 }
98 
99 __attribute__((always_inline)) static inline void I2cClearIT(void *reg)
100 {
101  ((i2cRegs_t *)reg)->conclr = _BV(SIC);
102 }
103 
104 __attribute__((always_inline)) static inline void I2cAutomaton(int32_t state, struct i2c_periph *p)
105 {
106  struct i2c_transaction *trans = p->trans[p->trans_extract_idx];
107  switch (state) {
108  case I2C_START:
109  case I2C_RESTART:
110  // Set R/W flag
111  switch (trans->type) {
112  case I2CTransRx :
113  SetBit(trans->slave_addr, 0);
114  break;
115  case I2CTransTx:
116  case I2CTransTxRx:
117  ClearBit(trans->slave_addr, 0);
118  break;
119  default:
120  break;
121  }
122  I2cSendByte(p->reg_addr, trans->slave_addr);
123  I2cClearStart(p->reg_addr);
124  p->idx_buf = 0;
125  break;
126  case I2C_MR_DATA_ACK:
127  if (p->idx_buf < trans->len_r) {
128  trans->buf[p->idx_buf] = ((i2cRegs_t *)(p->reg_addr))->dat;
129  p->idx_buf++;
130  I2cReceive(p->reg_addr, p->idx_buf < trans->len_r - 1);
131  } else {
132  /* error , we should have got NACK */
133  I2cFail(p, trans);
134  }
135  break;
136  case I2C_MR_DATA_NACK:
137  if (p->idx_buf < trans->len_r) {
138  trans->buf[p->idx_buf] = ((i2cRegs_t *)(p->reg_addr))->dat;
139  }
140  I2cSendStop(p, trans);
141  break;
142  case I2C_MR_SLA_ACK: /* At least one char */
143  /* Wait and reply with ACK or NACK */
144  I2cReceive(p->reg_addr, p->idx_buf < trans->len_r - 1);
145  break;
146  case I2C_MR_SLA_NACK:
147  case I2C_MT_SLA_NACK:
148  /* Slave is not responding, transaction is failed */
149  I2cFail(p, trans);
150  break;
151  case I2C_MT_SLA_ACK:
152  case I2C_MT_DATA_ACK:
153  if (p->idx_buf < trans->len_w) {
154  I2cSendByte(p->reg_addr, trans->buf[p->idx_buf]);
155  p->idx_buf++;
156  } else {
157  if (trans->type == I2CTransTxRx) {
158  trans->type = I2CTransRx; /* FIXME should not change type */
159  p->idx_buf = 0;
160  trans->slave_addr |= 1;
161  I2cSendStart(p);
162  } else {
163  I2cSendStop(p, trans);
164  }
165  }
166  break;
167  default:
168  I2cFail(p, trans);
169  /* FIXME log error */
170  break;
171  }
172 }
173 
174 
175 #if USE_I2C0
176 
177 /* default clock speed 37.5KHz with our 15MHz PCLK
178  I2C0_CLOCK = PCLK / (I2C0_SCLL + I2C0_SCLH) */
179 #ifndef I2C0_SCLL
180 #define I2C0_SCLL 200
181 #endif
182 
183 #ifndef I2C0_SCLH
184 #define I2C0_SCLH 200
185 #endif
186 
187 /* adjust for other PCLKs */
188 
189 #if (PCLK == 15000000)
190 #define I2C0_SCLL_D I2C0_SCLL
191 #define I2C0_SCLH_D I2C0_SCLH
192 #else
193 
194 #if (PCLK == 30000000)
195 #define I2C0_SCLL_D (2*I2C0_SCLL)
196 #define I2C0_SCLH_D (2*I2C0_SCLH)
197 #else
198 
199 #if (PCLK == 60000000)
200 #define I2C0_SCLL_D (4*I2C0_SCLL)
201 #define I2C0_SCLH_D (4*I2C0_SCLH)
202 #else
203 
204 #error unknown PCLK frequency
205 #endif
206 #endif
207 #endif
208 
209 #ifndef I2C0_VIC_SLOT
210 #define I2C0_VIC_SLOT 8
211 #endif
212 
213 
214 void i2c0_ISR(void) __attribute__((naked));
215 
216 void i2c0_ISR(void)
217 {
218  ISR_ENTRY();
219 
221  I2cAutomaton(state, &i2c0);
222  I2cClearIT(i2c0.reg_addr);
223 
224  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
225  ISR_EXIT(); // recover registers and return
226 }
227 
228 uint8_t i2c0_vic_channel;
229 
230 /* SDA0 on P0.3 */
231 /* SCL0 on P0.2 */
232 void i2c0_hw_init(void)
233 {
234 
235  i2c0.reg_addr = I2C0;
236  i2c0_vic_channel = VIC_I2C0;
237  i2c0.init_struct = (void *)(&i2c0_vic_channel);
238 
239  /* set P0.2 and P0.3 to I2C0 */
240  PINSEL0 |= 1 << 4 | 1 << 6;
241  /* clear all flags */
242  I2C0CONCLR = _BV(AAC) | _BV(SIC) | _BV(STAC) | _BV(I2ENC);
243  /* enable I2C */
244  I2C0CONSET = _BV(I2EN);
245  /* set bitrate */
246  I2C0SCLL = I2C0_SCLL_D;
247  I2C0SCLH = I2C0_SCLH_D;
248 
249  // initialize the interrupt vector
250  VICIntSelect &= ~VIC_BIT(VIC_I2C0); // I2C0 selected as IRQ
251  VICIntEnable = VIC_BIT(VIC_I2C0); // I2C0 interrupt enabled
252  _VIC_CNTL(I2C0_VIC_SLOT) = VIC_ENABLE | VIC_I2C0;
253  _VIC_ADDR(I2C0_VIC_SLOT) = (uint32_t)i2c0_ISR; // address of the ISR
254 }
255 
256 #endif /* USE_I2C0 */
257 
258 
259 
260 #if USE_I2C1
261 
262 /* default clock speed 37.5KHz with our 15MHz PCLK
263  I2C1_CLOCK = PCLK / (I2C1_SCLL + I2C1_SCLH) */
264 #ifndef I2C1_SCLL
265 #define I2C1_SCLL 200
266 #endif
267 
268 #ifndef I2C1_SCLH
269 #define I2C1_SCLH 200
270 #endif
271 
272 /* adjust for other PCLKs */
273 
274 #if (PCLK == 15000000)
275 #define I2C1_SCLL_D I2C1_SCLL
276 #define I2C1_SCLH_D I2C1_SCLH
277 #else
278 
279 #if (PCLK == 30000000)
280 #define I2C1_SCLL_D (2*I2C1_SCLL)
281 #define I2C1_SCLH_D (2*I2C1_SCLH)
282 #else
283 
284 #if (PCLK == 60000000)
285 #define I2C1_SCLL_D (4*I2C1_SCLL)
286 #define I2C1_SCLH_D (4*I2C1_SCLH)
287 #else
288 
289 #error unknown PCLK frequency
290 #endif
291 #endif
292 #endif
293 
294 #ifndef I2C1_VIC_SLOT
295 #define I2C1_VIC_SLOT 9
296 #endif
297 
298 
299 void i2c1_ISR(void) __attribute__((naked));
300 
301 void i2c1_ISR(void)
302 {
303  ISR_ENTRY();
304 
306  I2cAutomaton(state, &i2c1);
307  I2cClearIT(i2c1.reg_addr);
308 
309  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
310  ISR_EXIT(); // recover registers and return
311 }
312 
313 uint8_t i2c1_vic_channel;
314 
315 /* SDA1 on P0.14 */
316 /* SCL1 on P0.11 */
317 void i2c1_hw_init(void)
318 {
319 
320  i2c1.reg_addr = I2C1;
321  i2c1_vic_channel = VIC_I2C1;
322  i2c1.init_struct = (void *)(&i2c1_vic_channel);
323 
324  /* set P0.11 and P0.14 to I2C1 */
325  PINSEL0 |= 3 << 22 | 3 << 28;
326  /* clear all flags */
327  I2C1CONCLR = _BV(AAC) | _BV(SIC) | _BV(STAC) | _BV(I2ENC);
328  /* enable I2C */
329  I2C1CONSET = _BV(I2EN);
330  /* set bitrate */
331  I2C1SCLL = I2C1_SCLL_D;
332  I2C1SCLH = I2C1_SCLH_D;
333 
334  // initialize the interrupt vector
335  VICIntSelect &= ~VIC_BIT(VIC_I2C1); // I2C1 selected as IRQ
336  VICIntEnable = VIC_BIT(VIC_I2C1); // I2C1 interrupt enabled
337  _VIC_CNTL(I2C1_VIC_SLOT) = VIC_ENABLE | VIC_I2C1;
338  _VIC_ADDR(I2C1_VIC_SLOT) = (uint32_t)i2c1_ISR; // address of the ISR
339 }
340 
341 #endif /* USE_I2C1 */
342 
343 
344 bool i2c_idle(struct i2c_periph *p)
345 {
346  return p->status == I2CIdle;
347 }
348 
349 bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
350 {
351 
352  uint8_t idx;
353  idx = p->trans_insert_idx + 1;
354  if (idx >= I2C_TRANSACTION_QUEUE_LEN) { idx = 0; }
355  if (idx == p->trans_extract_idx) {
356  /* queue full */
357  p->errors->queue_full_cnt++;
358  t->status = I2CTransFailed;
359  return false;
360  }
361  t->status = I2CTransPending;
362 
363  /* disable I2C interrupt */
364  //uint8_t* vic = (uint8_t*)(p->init_struct);
365  //VICIntEnClear = VIC_BIT(*vic);
366  disableIRQ();
367 
368  p->trans[p->trans_insert_idx] = t;
369  p->trans_insert_idx = idx;
370  /* if peripheral is idle, start the transaction */
371  if (p->status == I2CIdle) {
372  I2cSendStart(p);
373  }
374  /* else it will be started by the interrupt handler */
375  /* when the previous transactions completes */
376 
377  /* enable I2C interrupt again */
378  //VICIntEnable = VIC_BIT(*vic);
379  enableIRQ();
380 
381  return true;
382 }
383 
384 void i2c_event(void) { }
385 
386 void i2c_setbitrate(struct i2c_periph *p, int bitrate)
387 {
388  int period = 15000000 / 2 / bitrate;
389  // Max 400kpbs
390  if (period < 19) {
391  period = 19;
392  }
393  // Min 5kbps
394  if (period > 1500) {
395  period = 1500;
396  }
397 
398 #if (PCLK == 30000000)
399  period *= 2;
400 #endif
401 
402 #if (PCLK == 60000000)
403  period *= 4;
404 #endif
405 
406  /* default clock speed 37.5KHz with our 15MHz PCLK
407  * I2C_CLOCK = PCLK / (I2C_SCLL + I2C_SCLH)
408  */
409 
410  /* set bitrate */
411  ((i2cRegs_t *)(p->reg_addr))->scll = period;
412  ((i2cRegs_t *)(p->reg_addr))->sclh = period;
413 }
414 
415 
#define VICIntSelect
Definition: LPC21xx.h:430
#define STAC
Definition: LPC21xx.h:189
#define I2C_TRANSACTION_QUEUE_LEN
I2C transaction queue length.
Definition: i2c.h:133
static uint32_t idx
#define I2C1
Definition: LPC21xx.h:166
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition: i2c.h:122
uint16_t len_r
Number of bytes to read/receive.
Definition: i2c.h:110
static void I2cClearIT(void *reg)
Definition: i2c_arch.c:99
static void I2cClearStart(void *reg)
Definition: i2c_arch.c:94
static void I2cSendAck(void *reg)
Definition: i2c_arch.c:46
transaction successfully finished by I2C driver
Definition: i2c.h:57
#define I2C_MT_SLA_ACK
Definition: i2c_arch.h:39
#define _VIC_CNTL(idx)
Definition: armVIC.h:19
transmit and receive transaction
Definition: i2c.h:49
#define I2C_MR_DATA_NACK
Definition: i2c_arch.h:45
uint8_t trans_extract_idx
Definition: i2c.h:142
bool i2c_idle(struct i2c_periph *p)
i2c_idle() function
Definition: i2c_arch.c:472
Definition: i2c.h:66
volatile uint16_t queue_full_cnt
Definition: i2c.h:156
void i2c_setbitrate(struct i2c_periph *p, int bitrate)
i2c_setbitrate() function
Definition: i2c_arch.c:414
static void I2cEndOfTransaction(struct i2c_periph *p)
Definition: i2c_arch.c:51
struct i2c_errors * errors
Definition: i2c.h:148
#define I2C0SCLH
Definition: LPC21xx.h:161
enum I2CStatus status
Definition: i2c.h:144
#define I2C0SCLL
Definition: LPC21xx.h:162
#define _VIC_ADDR(idx)
Definition: armVIC.h:20
#define I2C1STAT
Definition: LPC21xx.h:169
static void I2cSendStop(struct i2c_periph *p, struct i2c_transaction *t)
Definition: i2c_arch.c:66
#define I2C_MR_DATA_ACK
Definition: i2c_arch.h:44
void * reg_addr
Definition: i2c.h:146
#define I2C_MR_SLA_ACK
Definition: i2c_arch.h:42
#define I2ENC
Definition: LPC21xx.h:190
#define I2C0CONSET
Definition: LPC21xx.h:157
uint8_t len_w
Number of bytes to write/transmit.
Definition: i2c.h:116
#define AAC
Definition: LPC21xx.h:187
#define I2C1CONCLR
Definition: LPC21xx.h:174
#define I2EN
Definition: LPC21xx.h:183
unsigned enableIRQ(void)
Definition: armVIC.c:51
static void I2cAutomaton(int32_t state, struct i2c_periph *p)
Definition: i2c_arch.c:104
#define I2C0CONCLR
Definition: LPC21xx.h:163
#define VICVectAddr
Definition: LPC21xx.h:436
unsigned long uint32_t
Definition: types.h:18
struct i2c_transaction * trans[I2C_TRANSACTION_QUEUE_LEN]
Definition: i2c.h:140
#define I2C1SCLH
Definition: LPC21xx.h:172
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
i2c_submit() function
Definition: i2c_arch.c:433
static void I2cFail(struct i2c_periph *p, struct i2c_transaction *t)
Definition: i2c_arch.c:74
transaction failed
Definition: i2c.h:58
#define STA
Definition: LPC21xx.h:182
#define I2C_MR_SLA_NACK
Definition: i2c_arch.h:43
#define AA
Definition: LPC21xx.h:179
I2C transaction structure.
Definition: i2c.h:93
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
signed long int32_t
Definition: types.h:19
#define VIC_BIT(chan)
Definition: lpcVIC.h:105
static void I2cSendStart(struct i2c_periph *p)
Definition: i2c_arch.c:40
#define PINSEL0
Definition: LPC21xx.h:347
#define VIC_I2C0
Definition: lpcVIC.h:78
uint8_t slave_addr
Slave address.
Definition: i2c.h:104
I2C peripheral structure.
Definition: i2c.h:138
#define I2C_RESTART
Definition: i2c_arch.h:38
#define I2C_START
Definition: i2c_arch.h:37
unsigned char uint8_t
Definition: types.h:14
unsigned disableIRQ(void)
Definition: armVIC.c:33
#define ISR_EXIT()
Definition: armVIC.h:61
#define I2C1SCLL
Definition: LPC21xx.h:173
#define VICIntEnable
Definition: LPC21xx.h:431
static void I2cReceive(void *reg, bool ack)
Definition: i2c_arch.c:88
transmit only transaction
Definition: i2c.h:47
static void I2cSendByte(void *reg, uint8_t b)
Definition: i2c_arch.c:83
static float p[2][2]
#define I2C0STAT
Definition: LPC21xx.h:158
#define STO
Definition: LPC21xx.h:181
void i2c_event(void)
i2c_event() function
Definition: i2c_arch.c:406
enum I2CTransactionType type
Transaction type.
Definition: i2c.h:98
uint8_t trans_insert_idx
Definition: i2c.h:141
#define I2C_MT_SLA_NACK
Definition: i2c_arch.h:40
#define SIC
Definition: LPC21xx.h:188
receive only transaction
Definition: i2c.h:48
#define I2C1CONSET
Definition: LPC21xx.h:168
#define ISR_ENTRY()
Definition: armVIC.h:40
#define I2C0
Definition: LPC21xx.h:154
transaction is pending in queue
Definition: i2c.h:55
#define VIC_ENABLE
Definition: lpcVIC.h:102
struct State state
Definition: state.c:36
#define VIC_I2C1
Definition: lpcVIC.h:89
#define I2C_MT_DATA_ACK
Definition: i2c_arch.h:41
Architecture independent I2C (Inter-Integrated Circuit Bus) API.