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