BeRTOS
|
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 }