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