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