BeRTOS
i2c_avr.c
Go to the documentation of this file.
00001 
00041 #include "cfg/cfg_i2c.h"
00042 
00043 #include <hw/hw_cpufreq.h>  /* CPU_FREQ */
00044 
00045 #define LOG_LEVEL  I2C_LOG_LEVEL
00046 #define LOG_FORMAT I2C_LOG_FORMAT
00047 
00048 #include <cfg/log.h>
00049 
00050 #include <cfg/debug.h>
00051 #include <cfg/macros.h> // BV()
00052 #include <cfg/module.h>
00053 
00054 #include <cpu/detect.h>
00055 #include <cpu/irq.h>
00056 #include <drv/timer.h>
00057 #include <drv/i2c.h>
00058 
00059 #include <cpu/power.h>
00060 
00061 #include <compat/twi.h>
00062 
00063 #if !CONFIG_I2C_DISABLE_OLD_API
00064 
00065 /* Wait for TWINT flag set: bus is ready */
00066 #define WAIT_TWI_READY  do {} while (!(TWCR & BV(TWINT)))
00067 
00073 static bool i2c_builtin_start(void)
00074 {
00075     TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
00076     WAIT_TWI_READY;
00077 
00078     if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
00079         return true;
00080 
00081     LOG_ERR("!TW_(REP)START: %x\n", TWSR);
00082     return false;
00083 }
00084 
00085 
00093 bool i2c_builtin_start_w(uint8_t id)
00094 {
00095     /*
00096      * Loop on the select write sequence: when the eeprom is busy
00097      * writing previously sent data it will reply to the SLA_W
00098      * control byte with a NACK.  In this case, we must
00099      * keep trying until the eeprom responds with an ACK.
00100      */
00101     ticks_t start = timer_clock();
00102     while (i2c_builtin_start())
00103     {
00104         TWDR = id & ~I2C_READBIT;
00105         TWCR = BV(TWINT) | BV(TWEN);
00106         WAIT_TWI_READY;
00107 
00108         if (TW_STATUS == TW_MT_SLA_ACK)
00109             return true;
00110         else if (TW_STATUS != TW_MT_SLA_NACK)
00111         {
00112             LOG_ERR("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
00113             break;
00114         }
00115         else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00116         {
00117             LOG_ERR("Timeout on TWI_MT_START\n");
00118             break;
00119         }
00120     }
00121 
00122     return false;
00123 }
00124 
00125 
00133 bool i2c_builtin_start_r(uint8_t id)
00134 {
00135     if (i2c_builtin_start())
00136     {
00137         TWDR = id | I2C_READBIT;
00138         TWCR = BV(TWINT) | BV(TWEN);
00139         WAIT_TWI_READY;
00140 
00141         if (TW_STATUS == TW_MR_SLA_ACK)
00142             return true;
00143 
00144         LOG_ERR("!TW_MR_SLA_ACK: %x\n", TWSR);
00145     }
00146 
00147     return false;
00148 }
00149 
00150 
00154 void i2c_builtin_stop(void)
00155 {
00156     TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
00157 }
00158 
00159 
00166 bool i2c_builtin_put(const uint8_t data)
00167 {
00168     TWDR = data;
00169     TWCR = BV(TWINT) | BV(TWEN);
00170     WAIT_TWI_READY;
00171     if (TW_STATUS != TW_MT_DATA_ACK)
00172     {
00173         LOG_ERR("!TW_MT_DATA_ACK: %x\n", TWSR);
00174         return false;
00175     }
00176     return true;
00177 }
00178 
00187 int i2c_builtin_get(bool ack)
00188 {
00189     TWCR = BV(TWINT) | BV(TWEN) | (ack ? BV(TWEA) : 0);
00190     WAIT_TWI_READY;
00191 
00192     if (ack)
00193     {
00194         if (TW_STATUS != TW_MR_DATA_ACK)
00195         {
00196             LOG_ERR("!TW_MR_DATA_ACK: %x\n", TWSR);
00197             return EOF;
00198         }
00199     }
00200     else
00201     {
00202         if (TW_STATUS != TW_MR_DATA_NACK)
00203         {
00204             LOG_ERR("!TW_MR_DATA_NACK: %x\n", TWSR);
00205             return EOF;
00206         }
00207     }
00208 
00209     /* avoid sign extension */
00210     return (int)(uint8_t)TWDR;
00211 }
00212 
00213 #endif /* !CONFIG_I2C_DISABLE_OLD_API */
00214 
00215 /*
00216  * New Api
00217  */
00218 struct I2cHardware
00219 {
00220 };
00221 
00222 
00223 /* Wait for TWINT flag set: bus is ready */
00224 #define WAIT_READY() \
00225     do { \
00226         while (!(TWCR & BV(TWINT))) \
00227             cpu_relax(); \
00228     } while (0)
00229 
00233 INLINE bool i2c_hw_start(void)
00234 {
00235     TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
00236     WAIT_READY();
00237 
00238     if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
00239         return true;
00240 
00241     return false;
00242 }
00243 
00247 INLINE void i2c_hw_stop(void)
00248 {
00249     TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
00250 }
00251 
00252 static void i2c_avr_start(I2c *i2c, uint16_t slave_addr)
00253 {
00254     /*
00255      * Loop on the select write sequence: when the eeprom is busy
00256      * writing previously sent data it will reply to the SLA_W
00257      * control byte with a NACK.  In this case, we must
00258      * keep trying until the slave responds with an ACK.
00259      */
00260     ticks_t start = timer_clock();
00261     while (i2c_hw_start())
00262     {
00263         uint8_t sla_ack = 0;
00264         uint8_t sla_nack = 0;
00265         if (I2C_TEST_START(i2c->flags) == I2C_START_W)
00266         {
00267             TWDR = slave_addr & ~I2C_READBIT;
00268             sla_ack = TW_MT_SLA_ACK;
00269             sla_nack = TW_MT_SLA_NACK;
00270         }
00271         else
00272         {
00273             TWDR = slave_addr | I2C_READBIT;
00274             sla_ack = TW_MR_SLA_ACK;
00275             sla_nack = TW_MR_SLA_NACK;
00276         }
00277 
00278         TWCR = BV(TWINT) | BV(TWEN);
00279         WAIT_READY();
00280 
00281         if (TW_STATUS == sla_ack)
00282             return;
00283         else if (TW_STATUS != sla_nack)
00284         {
00285             LOG_ERR("Start addr NACK[%x]\n", TWSR);
00286             i2c->errors |= I2C_NO_ACK;
00287             i2c_hw_stop();
00288             break;
00289         }
00290         else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00291         {
00292             LOG_ERR("Start timeout\n");
00293             i2c->errors |= I2C_START_TIMEOUT;
00294             i2c_hw_stop();
00295             break;
00296         }
00297     }
00298 
00299     LOG_ERR("I2c error\n");
00300     i2c->errors |= I2C_ERR;
00301     i2c_hw_stop();
00302 }
00303 
00304 static void i2c_avr_putc(I2c *i2c, const uint8_t data)
00305 {
00306 
00307     TWDR = data;
00308     TWCR = BV(TWINT) | BV(TWEN);
00309     WAIT_READY();
00310 
00311     if (TW_STATUS != TW_MT_DATA_ACK)
00312     {
00313         LOG_ERR("Data nack[%x]\n", TWSR);
00314         i2c->errors |= I2C_DATA_NACK;
00315         i2c_hw_stop();
00316     }
00317 
00318     if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
00319         i2c_hw_stop();
00320 }
00321 
00322 static uint8_t i2c_avr_getc(I2c *i2c)
00323 {
00324     uint8_t data_flag = 0;
00325     if (i2c->xfer_size == 1)
00326     {
00327         TWCR = BV(TWINT) | BV(TWEN);
00328         data_flag = TW_MR_DATA_NACK;
00329     }
00330     else
00331     {
00332         TWCR = BV(TWINT) | BV(TWEN) | BV(TWEA);
00333         data_flag = TW_MR_DATA_ACK;
00334     }
00335 
00336     WAIT_READY();
00337 
00338     if (TW_STATUS != data_flag)
00339     {
00340         LOG_ERR("Data nack[%x]\n", TWSR);
00341         i2c->errors |= I2C_DATA_NACK;
00342         i2c_hw_stop();
00343 
00344         return 0xFF;
00345     }
00346 
00347     uint8_t data = TWDR;
00348 
00349     if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
00350         i2c_hw_stop();
00351 
00352     return data;
00353 }
00354 
00355 
00356 static const I2cVT i2c_avr_vt =
00357 {
00358     .start = i2c_avr_start,
00359     .getc = i2c_avr_getc,
00360     .putc = i2c_avr_putc,
00361     .write = i2c_genericWrite,
00362     .read = i2c_genericRead,
00363 };
00364 
00365 struct I2cHardware i2c_avr_hw[] =
00366 {
00367     { /* I2C0 */
00368     },
00369 };
00370 
00374 void i2c_hw_init(I2c *i2c, int dev, uint32_t clock)
00375 {
00376     i2c->hw = &i2c_avr_hw[dev];
00377     i2c->vt = &i2c_avr_vt;
00378 
00379     ATOMIC(
00380         /*
00381          * This is pretty useless according to AVR's datasheet,
00382          * but it helps us driving the TWI data lines on boards
00383          * where the bus pull-up resistors are missing.  This is
00384          * probably due to some unwanted interaction between the
00385          * port pin and the TWI lines.
00386          */
00387     #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560
00388         PORTD |= BV(PD0) | BV(PD1);
00389         DDRD  |= BV(PD0) | BV(PD1);
00390     #elif CPU_AVR_ATMEGA8
00391         PORTC |= BV(PC4) | BV(PC5);
00392         DDRC  |= BV(PC4) | BV(PC5);
00393     #elif CPU_AVR_ATMEGA32
00394         PORTC |= BV(PC1) | BV(PC0);
00395         DDRC  |= BV(PC1) | BV(PC0);
00396     #else
00397         #error Unsupported architecture
00398     #endif
00399 
00400         /*
00401          * Set speed:
00402          * F = CPU_FREQ / (16 + 2*TWBR * 4^TWPS)
00403          */
00404         ASSERT(clock);
00405         #define TWI_PRESC    1       /* 4 ^ TWPS */
00406 
00407         TWBR = (CPU_FREQ / (2 * clock * TWI_PRESC)) - (8 / TWI_PRESC);
00408         TWSR = 0;
00409         TWCR = BV(TWEN);
00410     );
00411 }