Merged revisions 4004-4036,4039-4048,4050-4095,4097-4100 via svnmerge from
[bertos.git] / bertos / cpu / avr / drv / i2c_avr.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos 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 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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 this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief Driver for the AVR ATMega TWI (implementation)
34  *
35  * \author Stefano Fedrigo <aleph@develer.com>
36  * \author Bernie Innocenti <bernie@codewiz.org>
37  * \author Daniele Basile <asterix@develer.com>
38  */
39
40 #include <hw/hw_cpufreq.h>  /* CPU_FREQ */
41
42 #include "cfg/cfg_i2c.h"
43
44 #define LOG_LEVEL  I2C_LOG_LEVEL
45 #define LOG_FORMAT I2C_LOG_FORMAT
46
47 #include <cfg/log.h>
48
49 #include <cfg/debug.h>
50 #include <cfg/macros.h> // BV()
51 #include <cfg/module.h>
52
53 #include <cpu/detect.h>
54 #include <cpu/irq.h>
55 #include <drv/timer.h>
56 #include <drv/i2c.h>
57
58 #include <cpu/power.h>
59
60 #include <compat/twi.h>
61
62
63 /* Wait for TWINT flag set: bus is ready */
64 #define WAIT_TWI_READY  do {} while (!(TWCR & BV(TWINT)))
65
66 /**
67  * Send START condition on the bus.
68  *
69  * \return true on success, false otherwise.
70  */
71 static bool i2c_builtin_start(void)
72 {
73         TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
74         WAIT_TWI_READY;
75
76         if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
77                 return true;
78
79         LOG_ERR("!TW_(REP)START: %x\n", TWSR);
80         return false;
81 }
82
83
84 /**
85  * Send START condition and select slave for write.
86  * \c id is the device id comprehensive of address left shifted by 1.
87  * The LSB of \c id is ignored and reset to 0 for write operation.
88  *
89  * \return true on success, false otherwise.
90  */
91 bool i2c_builtin_start_w(uint8_t id)
92 {
93         /*
94          * Loop on the select write sequence: when the eeprom is busy
95          * writing previously sent data it will reply to the SLA_W
96          * control byte with a NACK.  In this case, we must
97          * keep trying until the eeprom responds with an ACK.
98          */
99         ticks_t start = timer_clock();
100         while (i2c_builtin_start())
101         {
102                 TWDR = id & ~I2C_READBIT;
103                 TWCR = BV(TWINT) | BV(TWEN);
104                 WAIT_TWI_READY;
105
106                 if (TW_STATUS == TW_MT_SLA_ACK)
107                         return true;
108                 else if (TW_STATUS != TW_MT_SLA_NACK)
109                 {
110                         LOG_ERR("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
111                         break;
112                 }
113                 else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
114                 {
115                         LOG_ERR("Timeout on TWI_MT_START\n");
116                         break;
117                 }
118         }
119
120         return false;
121 }
122
123
124 /**
125  * Send START condition and select slave for read.
126  * \c id is the device id comprehensive of address left shifted by 1.
127  * The LSB of \c id is ignored and set to 1 for read operation.
128  *
129  * \return true on success, false otherwise.
130  */
131 bool i2c_builtin_start_r(uint8_t id)
132 {
133         if (i2c_builtin_start())
134         {
135                 TWDR = id | I2C_READBIT;
136                 TWCR = BV(TWINT) | BV(TWEN);
137                 WAIT_TWI_READY;
138
139                 if (TW_STATUS == TW_MR_SLA_ACK)
140                         return true;
141
142                 LOG_ERR("!TW_MR_SLA_ACK: %x\n", TWSR);
143         }
144
145         return false;
146 }
147
148
149 /**
150  * Send STOP condition.
151  */
152 void i2c_builtin_stop(void)
153 {
154         TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
155 }
156
157
158 /**
159  * Put a single byte in master transmitter mode
160  * to the selected slave device through the TWI bus.
161  *
162  * \return true on success, false on error.
163  */
164 bool i2c_builtin_put(const uint8_t data)
165 {
166         TWDR = data;
167         TWCR = BV(TWINT) | BV(TWEN);
168         WAIT_TWI_READY;
169         if (TW_STATUS != TW_MT_DATA_ACK)
170         {
171                 LOG_ERR("!TW_MT_DATA_ACK: %x\n", TWSR);
172                 return false;
173         }
174         return true;
175 }
176
177 /**
178  * Get 1 byte from slave in master transmitter mode
179  * to the selected slave device through the TWI bus.
180  * If \a ack is true issue a ACK after getting the byte,
181  * otherwise a NACK is issued.
182  *
183  * \return the byte read if ok, EOF on errors.
184  */
185 int i2c_builtin_get(bool ack)
186 {
187         TWCR = BV(TWINT) | BV(TWEN) | (ack ? BV(TWEA) : 0);
188         WAIT_TWI_READY;
189
190         if (ack)
191         {
192                 if (TW_STATUS != TW_MR_DATA_ACK)
193                 {
194                         LOG_ERR("!TW_MR_DATA_ACK: %x\n", TWSR);
195                         return EOF;
196                 }
197         }
198         else
199         {
200                 if (TW_STATUS != TW_MR_DATA_NACK)
201                 {
202                         LOG_ERR("!TW_MR_DATA_NACK: %x\n", TWSR);
203                         return EOF;
204                 }
205         }
206
207         /* avoid sign extension */
208         return (int)(uint8_t)TWDR;
209 }
210
211
212 MOD_DEFINE(i2c);
213
214 /**
215  * Initialize TWI module.
216  */
217 void i2c_builtin_init(void)
218 {
219         ATOMIC(
220                 /*
221                  * This is pretty useless according to AVR's datasheet,
222                  * but it helps us driving the TWI data lines on boards
223                  * where the bus pull-up resistors are missing.  This is
224                  * probably due to some unwanted interaction between the
225                  * port pin and the TWI lines.
226                  */
227 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281
228                 PORTD |= BV(PD0) | BV(PD1);
229                 DDRD  |= BV(PD0) | BV(PD1);
230 #elif CPU_AVR_ATMEGA8
231                 PORTC |= BV(PC4) | BV(PC5);
232                 DDRC  |= BV(PC4) | BV(PC5);
233 #elif CPU_AVR_ATMEGA32
234                 PORTC |= BV(PC1) | BV(PC0);
235                 DDRC  |= BV(PC1) | BV(PC0);
236 #else
237                 #error Unsupported architecture
238 #endif
239
240                 /*
241                  * Set speed:
242                  * F = CPU_FREQ / (16 + 2*TWBR * 4^TWPS)
243                  */
244                 #ifndef CONFIG_I2C_FREQ
245                         #warning Using default value of 300000L for CONFIG_I2C_FREQ
246                         #define CONFIG_I2C_FREQ  300000L /* ~300 kHz */
247                 #endif
248                 #define TWI_PRESC 1       /* 4 ^ TWPS */
249
250                 TWBR = (CPU_FREQ / (2 * CONFIG_I2C_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
251                 TWSR = 0;
252                 TWCR = BV(TWEN);
253         );
254         MOD_INIT(i2c);
255 }
256
257 /*
258  * New Api
259  */
260
261
262 struct I2cHardware
263 {
264 };
265
266
267 /* Wait for TWINT flag set: bus is ready */
268 #define WAIT_READY() \
269         do { \
270                 while (!(TWCR & BV(TWINT))) \
271                         cpu_relax(); \
272         } while (0)
273
274 /**
275  * Send START condition on the bus.
276  */
277 INLINE bool i2c_hw_start(void)
278 {
279         TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
280         WAIT_READY();
281
282         if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
283                 return true;
284
285         return false;
286 }
287
288 /**
289  * Send STOP condition.
290  */
291 INLINE void i2c_hw_stop(void)
292 {
293         TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
294 }
295
296 static void i2c_avr_start(I2c *i2c, uint16_t slave_addr)
297 {
298         /*
299          * Loop on the select write sequence: when the eeprom is busy
300          * writing previously sent data it will reply to the SLA_W
301          * control byte with a NACK.  In this case, we must
302          * keep trying until the slave responds with an ACK.
303          */
304         ticks_t start = timer_clock();
305         while (i2c_hw_start())
306         {
307                 uint8_t sla_ack = 0;
308                 uint8_t sla_nack = 0;
309                 if (I2C_TEST_START(i2c->flags) == I2C_START_W)
310                 {
311                         TWDR = slave_addr & ~I2C_READBIT;
312                         sla_ack = TW_MT_SLA_ACK;
313                         sla_nack = TW_MT_SLA_NACK;
314                 }
315                 else
316                 {
317                         TWDR = slave_addr | I2C_READBIT;
318                         sla_ack = TW_MR_SLA_ACK;
319                         sla_nack = TW_MR_SLA_NACK;
320                 }
321
322                 TWCR = BV(TWINT) | BV(TWEN);
323                 WAIT_READY();
324
325                 if (TW_STATUS == sla_ack)
326                         return;
327                 else if (TW_STATUS != sla_nack)
328                 {
329                         LOG_ERR("Start addr NACK[%x]\n", TWSR);
330                         i2c->errors |= I2C_NO_ACK;
331                         i2c_hw_stop();
332                         break;
333                 }
334                 else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
335                 {
336                         LOG_ERR("Start timeout\n");
337                         i2c->errors |= I2C_START_TIMEOUT;
338                         i2c_hw_stop();
339                         break;
340                 }
341         }
342
343         LOG_ERR("I2c error\n");
344         i2c->errors |= I2C_ERR;
345         i2c_hw_stop();
346 }
347
348 static void i2c_avr_putc(I2c *i2c, const uint8_t data)
349 {
350
351         TWDR = data;
352         TWCR = BV(TWINT) | BV(TWEN);
353         WAIT_READY();
354
355         if (TW_STATUS != TW_MT_DATA_ACK)
356         {
357                 LOG_ERR("Data nack[%x]\n", TWSR);
358                 i2c->errors |= I2C_DATA_NACK;
359                 i2c_hw_stop();
360         }
361
362         if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
363                 i2c_hw_stop();
364 }
365
366 static uint8_t i2c_avr_getc(I2c *i2c)
367 {
368         uint8_t data_flag = 0;
369         if (i2c->xfer_size == 1)
370         {
371                 TWCR = BV(TWINT) | BV(TWEN);
372                 data_flag = TW_MR_DATA_NACK;
373         }
374         else
375         {
376                 TWCR = BV(TWINT) | BV(TWEN) | BV(TWEA);
377                 data_flag = TW_MR_DATA_ACK;
378         }
379
380         WAIT_READY();
381
382         if (TW_STATUS != data_flag)
383         {
384                 LOG_ERR("Data nack[%x]\n", TWSR);
385                 i2c->errors |= I2C_DATA_NACK;
386                 i2c_hw_stop();
387
388                 return 0xFF;
389         }
390
391         uint8_t data = TWDR;
392
393         if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
394                 i2c_hw_stop();
395
396         return data;
397 }
398
399
400 static const I2cVT i2c_avr_vt =
401 {
402         .start = i2c_avr_start,
403         .getc = i2c_avr_getc,
404         .putc = i2c_avr_putc,
405         .write = i2c_genericWrite,
406         .read = i2c_genericRead,
407 };
408
409 struct I2cHardware i2c_avr_hw[] =
410 {
411         { /* I2C0 */
412         },
413 };
414
415 /**
416  * Initialize I2C module.
417  */
418 void i2c_hw_init(I2c *i2c, int dev, uint32_t clock)
419 {
420         i2c->hw = &i2c_avr_hw[dev];
421         i2c->vt = &i2c_avr_vt;
422
423         ATOMIC(
424                 /*
425                  * This is pretty useless according to AVR's datasheet,
426                  * but it helps us driving the TWI data lines on boards
427                  * where the bus pull-up resistors are missing.  This is
428                  * probably due to some unwanted interaction between the
429                  * port pin and the TWI lines.
430                  */
431         #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281
432                 PORTD |= BV(PD0) | BV(PD1);
433                 DDRD  |= BV(PD0) | BV(PD1);
434         #elif CPU_AVR_ATMEGA8
435                 PORTC |= BV(PC4) | BV(PC5);
436                 DDRC  |= BV(PC4) | BV(PC5);
437         #elif CPU_AVR_ATMEGA32
438                 PORTC |= BV(PC1) | BV(PC0);
439                 DDRC  |= BV(PC1) | BV(PC0);
440         #else
441                 #error Unsupported architecture
442         #endif
443
444                 /*
445                  * Set speed:
446                  * F = CPU_FREQ / (16 + 2*TWBR * 4^TWPS)
447                  */
448                 ASSERT(clock);
449                 #define TWI_PRESC    1       /* 4 ^ TWPS */
450
451                 TWBR = (CPU_FREQ / (2 * clock * TWI_PRESC)) - (8 / TWI_PRESC);
452                 TWSR = 0;
453                 TWCR = BV(TWEN);
454         );
455 }