i2c_xmega.c
Go to the documentation of this file.
00001 00040 #include "cfg/cfg_i2c.h" 00041 00042 00043 #define LOG_LEVEL I2C_LOG_LEVEL 00044 #define LOG_FORMAT I2C_LOG_FORMAT 00045 #include <cfg/log.h> 00046 00047 #include <cfg/debug.h> 00048 #include <cfg/macros.h> // BV() 00049 #include <cfg/module.h> 00050 00051 #include <cpu/detect.h> 00052 #include <cpu/irq.h> 00053 #include <cpu/types.h> 00054 00055 #include <drv/timer.h> 00056 #include <drv/i2c.h> 00057 00058 #include <cpu/power.h> 00059 00060 #include <avr/io.h> 00061 #include <util/twi.h> //AVRLIBC TWI bit mask definitions 00062 #include <stdbool.h> 00063 00064 #if !CONFIG_I2C_DISABLE_OLD_API 00065 #error I2C_OLD_API is not implemented 00066 #endif 00067 00068 /* 00069 * New Api 00070 */ 00071 struct I2cHardware 00072 { 00073 volatile TWI_t *twi; 00074 }; 00075 00076 /* Baud register setting calculation. Formula described in datasheet. */ 00077 #define TWI_BAUD(F_SYS, F_TWI) (DIV_ROUND(F_SYS, (2 * F_TWI)) - 5) 00078 00079 // Wait until write interrupt is set 00080 #define WAIT_UNTIL_WRITE_INTERRUPT_SET(TWI) \ 00081 do { \ 00082 while (((TWI)->MASTER.STATUS & TWI_MASTER_WIF_bm) == 0) \ 00083 cpu_relax(); \ 00084 } while (0) 00085 00086 #define WAIT_UNTIL_READ_OR_WRITE_INTERRUPT_SET(TWI) \ 00087 do { \ 00088 while (((TWI)->MASTER.STATUS & (TWI_MASTER_WIF_bm | TWI_MASTER_RIF_bm)) == 0) \ 00089 cpu_relax(); \ 00090 } while (0) 00091 00092 #define MASTER_STATE_IS_IDLE(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_BUSSTATE_gm) == TWI_MASTER_BUSSTATE_IDLE_gc) 00093 #define MASTER_STATE_IS_OWNER(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_BUSSTATE_gm) == TWI_MASTER_BUSSTATE_OWNER_gc) 00094 #define MASTER_STATE_IS_BUSY(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_BUSSTATE_gm) == TWI_MASTER_BUSSTATE_BUSY_gc) 00095 #define MASTER_STATE_IS_UNKOWN(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_BUSSTATE_gm) == TWI_MASTER_BUSSTATE_UNKNOWN_gc) 00096 00097 // Wait until ready for the next transaction 00098 #define WAIT_UNTIL_READY_FOR_TRANSACTION(TWI) \ 00099 do { \ 00100 while (MASTER_STATE_IS_BUSY(TWI))\ 00101 cpu_relax(); \ 00102 } while (0) 00103 00104 00105 #define READ_INTERRUPT_FLAG_IS_SET(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_RIF_bm) != 0) 00106 #define ARBLOST_OR_BUSERR_OCCURED(TWI) (((TWI)->MASTER.STATUS & (TWI_MASTER_BUSERR_bm | TWI_MASTER_ARBLOST_bm)) != 0) 00107 #define ARBLOST_OCCURED(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_ARBLOST_bm) != 0) 00108 #define BUSERR_OCCURED(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_BUSERR_bm) != 0) 00109 #define ACK_RECEIVED(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_RXACK_bm) == 0) 00110 #define NACK_RECEIVED(TWI) (((TWI)->MASTER.STATUS & TWI_MASTER_RXACK_bm) != 0) 00111 #define CLEAR_BUSERROR(TWI) ((TWI)->MASTER.STATUS |= TWI_MASTER_BUSERR_bm) 00112 #define SET_IDLESTATE(TWI) ((TWI)->MASTER.STATUS = ((TWI)->MASTER.STATUS & (~TWI_MASTER_BUSSTATE_gm)) | TWI_MASTER_BUSSTATE_IDLE_gc) 00113 00117 INLINE void i2c_hw_stop(volatile TWI_t *twi) 00118 { 00119 twi->MASTER.CTRLC |= TWI_MASTER_CMD_STOP_gc; 00120 } 00121 00122 static void i2c_xmega_start(I2c *i2c, uint16_t slave_addr) 00123 { 00124 /* 00125 * Loop on the select write sequence: when the eeprom is busy 00126 * writing previously sent data it will reply to the SLA_W 00127 * control byte with a NACK. In this case, we must 00128 * keep trying until the slave responds with an ACK. 00129 */ 00130 ticks_t start = timer_clock(); 00131 volatile TWI_t *twi = i2c->hw->twi; 00132 bool stop_loop = false; 00133 00134 //check if there is a buserror 00135 //if so, try to clear it! 00136 if (BUSERR_OCCURED(twi)) 00137 { 00138 LOG_WARN("Clearing BusError from TWI device\r\n"); 00139 CLEAR_BUSERROR(twi); 00140 LOG_WARN("Forcing TWI Device to IDLE state\r\n"); 00141 SET_IDLESTATE(twi); 00142 LOG_WARN("Current status is: %d\r\n", twi->MASTER.STATUS); 00143 } 00144 00145 while (!stop_loop) 00146 { 00147 //Wait until we are in IDLE state. 00148 //Due to a set timeout, we will always retun to IDLE state 00149 //in due time. 00150 WAIT_UNTIL_READY_FOR_TRANSACTION(twi); 00151 00152 //Write the address 00153 //This will first generate the start condition 00154 if (I2C_TEST_START(i2c->flags) == I2C_START_W) 00155 { 00156 //start a write action 00157 uint8_t write_address = ((uint8_t)slave_addr << 1) & ~0x01; 00158 twi->MASTER.ADDR = write_address; 00159 00160 //Wait until the write interrupt flag is set. 00161 //this will also be set when an error occurs. 00162 WAIT_UNTIL_WRITE_INTERRUPT_SET(twi); 00163 } 00164 else 00165 { 00166 uint8_t read_address = ((uint8_t)slave_addr << 1) | 0x01; 00167 twi->MASTER.ADDR = read_address; 00168 00169 //Wait until the read or write interrupt flag is set. 00170 //In this case, a write interrupt flag is set on an error 00171 //a read interrupt on an ack 00172 WAIT_UNTIL_READ_OR_WRITE_INTERRUPT_SET(twi); 00173 } 00174 00175 00176 //check if Arbitration Lost of Buserror has occured 00177 if (ARBLOST_OR_BUSERR_OCCURED(twi)) 00178 { 00179 if (ARBLOST_OCCURED(twi)) 00180 { 00181 i2c->errors |= I2C_ARB_LOST; 00182 } 00183 00184 if (BUSERR_OCCURED(twi)) 00185 { 00186 i2c->errors |= I2C_ERR; 00187 } 00188 LOG_ERR("Start error [%x]\n", twi->MASTER.STATUS); 00189 00190 // reset i2c 00191 i2c->xfer_size = 0; 00192 // try to send a stop signal 00193 i2c_hw_stop(twi); 00194 stop_loop = true; 00195 } 00196 else if (ACK_RECEIVED(twi)) 00197 { 00198 //ack received 00199 stop_loop = true; 00200 } 00201 else 00202 { 00203 //nack received 00204 //ignore if writing, the slave device might just be busy 00205 //with a precious command. 00206 if (I2C_TEST_START(i2c->flags) == I2C_START_W) 00207 { 00208 //Just check if the start timeout has occured 00209 if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT)) 00210 { 00211 LOG_ERR("Start timeout\n"); 00212 i2c->errors |= I2C_START_TIMEOUT; 00213 i2c_hw_stop(twi); 00214 stop_loop = true; 00215 } 00216 } 00217 else 00218 { 00219 //while reading.... stop 00220 LOG_ERR("Start addr NACK[%x]\n", twi->MASTER.STATUS); 00221 i2c->errors |= I2C_NO_ACK; 00222 i2c_hw_stop(twi); 00223 stop_loop = true; 00224 } 00225 } 00226 } 00227 } 00228 00229 static void i2c_xmega_putc(I2c *i2c, const uint8_t data) 00230 { 00231 volatile TWI_t *twi = i2c->hw->twi; 00232 00233 twi->MASTER.DATA = data; 00234 00235 WAIT_UNTIL_WRITE_INTERRUPT_SET(twi); 00236 00237 if (ARBLOST_OR_BUSERR_OCCURED(twi)) 00238 { 00239 if (ARBLOST_OCCURED(twi)) 00240 { 00241 i2c->errors |= I2C_ARB_LOST; 00242 } 00243 00244 if (BUSERR_OCCURED(twi)) 00245 { 00246 i2c->errors |= I2C_ERR; 00247 } 00248 00249 LOG_ERR("Data write error [%x]\n", twi->MASTER.STATUS); 00250 i2c_hw_stop(twi); 00251 } 00252 else if (NACK_RECEIVED(twi)) 00253 { 00254 LOG_ERR("Data nack[%x]\n", twi->MASTER.STATUS); 00255 i2c->errors |= I2C_DATA_NACK; 00256 i2c_hw_stop(twi); 00257 } 00258 00259 if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP)) 00260 { 00261 i2c_hw_stop(twi); 00262 } 00263 } 00264 00265 static uint8_t i2c_xmega_getc(I2c *i2c) 00266 { 00267 volatile TWI_t *twi = i2c->hw->twi; 00268 00269 //check if the RIF flag is set 00270 if (READ_INTERRUPT_FLAG_IS_SET(twi)) 00271 { 00272 //read the available data 00273 uint8_t data = twi->MASTER.DATA; 00274 //if this is the last byte to receive, send nack otherwise ack. 00275 if (i2c->xfer_size == 1) 00276 { 00277 //nack needs to be send 00278 //check if a stop needs to be generated afther the ack, of a repeat start. 00279 if (I2C_TEST_STOP(i2c->flags) == I2C_STOP) 00280 { 00281 //send nack and stop 00282 twi->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc; 00283 } 00284 else 00285 { 00286 //only set the nack. The repeated start will be send on the next 00287 //call to i2c_xmega_start 00288 twi->MASTER.CTRLC = TWI_MASTER_ACKACT_bm; 00289 } 00290 } 00291 else 00292 { 00293 //send ack and request next byte 00294 twi->MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc; 00295 //Wait until the read or write interrupt flag is set. 00296 //In this case, a write interrupt flag is set on an error 00297 //a read interrupt on an ack 00298 WAIT_UNTIL_READ_OR_WRITE_INTERRUPT_SET(twi); 00299 //check if Arbitration Lost of Buserror has occured 00300 if ( ARBLOST_OR_BUSERR_OCCURED(twi)) 00301 { 00302 if (ARBLOST_OCCURED(twi)) 00303 { 00304 i2c->errors |= I2C_ARB_LOST; 00305 } 00306 00307 if (BUSERR_OCCURED(twi)) 00308 { 00309 i2c->errors |= I2C_ERR; 00310 } 00311 00312 LOG_ERR("Data error [%x]\n", twi->MASTER.STATUS); 00313 i2c_hw_stop(twi); 00314 return 0xFF; 00315 } 00316 } 00317 return data; 00318 } 00319 else 00320 { 00321 LOG_ERR("Data RIF not set[%x]\n", twi->MASTER.STATUS); 00322 i2c->errors |= I2C_ERR; 00323 i2c_hw_stop(twi); 00324 return 0xFF; 00325 } 00326 } 00327 00328 00329 static const I2cVT i2c_xmega_vt = 00330 { 00331 .start = i2c_xmega_start, 00332 .getc = i2c_xmega_getc, 00333 .putc = i2c_xmega_putc, 00334 .write = i2c_genericWrite, 00335 .read = i2c_genericRead, 00336 }; 00337 00338 struct I2cHardware i2c_xmega_hw[] = 00339 { 00340 { /* I2C0 */ 00341 .twi = &TWIC, 00342 }, 00343 { /* ICC1 */ 00344 .twi = &TWIE, 00345 }, 00346 #if CPU_AVR_XMEGA_A1 00347 { /* I2C2 */ 00348 .twi = &TWID, 00349 }, 00350 { /* ICC3 */ 00351 .twi = &TWIF, 00352 }, 00353 #endif 00354 }; 00355 00359 void i2c_hw_init(I2c *i2c, int dev, uint32_t clock) 00360 { 00361 i2c->hw = &i2c_xmega_hw[dev]; 00362 i2c->vt = &i2c_xmega_vt; 00363 00364 volatile TWI_t *twi = i2c->hw->twi; 00365 00366 //enable TWI Master Mode 00367 twi->MASTER.CTRLA = TWI_MASTER_ENABLE_bm; 00368 //set an Interactive Bus Timeout 00369 twi->MASTER.CTRLB = TWI_MASTER_TIMEOUT_50US_gc; 00370 //set baud rate 00371 ASSERT(clock); 00372 twi->MASTER.BAUD = TWI_BAUD(CPU_FREQ, clock); 00373 //set status to idle 00374 twi->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc; 00375 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)