Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00088 #include <cfg/os.h>
00089 #include <cfg/twi.h>
00090 #include <cfg/arch/gpio.h>
00091
00092 #include <dev/twif.h>
00093
00094 #if defined(__arm__)
00095
00096 #include <arch/arm.h>
00097
00103 #if !defined(TWI_PIO_ID)
00104 #if defined(MCU_AT91SAM7X) || defined(MCU_AT91SAM7S256) || defined(MCU_AT91SAM7SE512)
00105 #define TWI_PIO_ID PIOA_ID
00106 #elif defined(MCU_AT91SAM9260)
00107 #define TWI_PIO_ID PIOB_ID
00108 #else
00109 #define TWI_PIO_ID PIO_ID
00110 #endif
00111 #endif
00112
00118 #ifndef TWI_SDA_BIT
00119 #if defined(MCU_AT91SAM9260)
00120 #define TWI_SDA_BIT 12
00121 #else
00122 #define TWI_SDA_BIT 10
00123 #endif
00124 #endif
00125
00129 #ifndef TWI_DELAY
00130 #if defined(MCU_AT91SAM9260)
00131 #define TWI_DELAY 16
00132 #else
00133 #define TWI_DELAY 8
00134 #endif
00135 #endif
00136
00142 #ifndef TWI_SCL_BIT
00143 #if defined(MCU_AT91SAM9260)
00144 #define TWI_SCL_BIT 13
00145 #else
00146 #define TWI_SCL_BIT 11
00147 #endif
00148 #endif
00149
00155 #if TWI_PIO_ID == PIOA_ID
00156
00157 #ifndef TWI_SDA_PE_REG
00158 #define TWI_SDA_PE_REG PIOA_PER
00159 #endif
00160 #ifndef TWI_SDA_OE_REG
00161 #define TWI_SDA_OE_REG PIOA_OER
00162 #endif
00163 #ifndef TWI_SDA_OD_REG
00164 #define TWI_SDA_OD_REG PIOA_ODR
00165 #endif
00166 #ifndef TWI_SDA_COD_REG
00167 #define TWI_SDA_COD_REG PIOA_CODR
00168 #endif
00169 #ifndef TWI_SDA_SOD_REG
00170 #define TWI_SDA_SOD_REG PIOA_SODR
00171 #endif
00172 #ifndef TWI_SDA_PDS_REG
00173 #define TWI_SDA_PDS_REG PIOA_PDSR
00174 #endif
00175
00176 #ifndef TWI_SCL_PE_REG
00177 #define TWI_SCL_PE_REG PIOA_PER
00178 #endif
00179 #ifndef TWI_SCL_OE_REG
00180 #define TWI_SCL_OE_REG PIOA_OER
00181 #endif
00182 #ifndef TWI_SCL_OD_REG
00183 #define TWI_SCL_OD_REG PIOA_ODR
00184 #endif
00185 #ifndef TWI_SCL_COD_REG
00186 #define TWI_SCL_COD_REG PIOA_CODR
00187 #endif
00188 #ifndef TWI_SCL_SOD_REG
00189 #define TWI_SCL_SOD_REG PIOA_SODR
00190 #endif
00191 #ifndef TWI_SCL_PDS_REG
00192 #define TWI_SCL_PDS_REG PIOA_PDSR
00193 #endif
00194
00195 #elif TWI_PIO_ID == PIOB_ID
00196
00197 #ifndef TWI_SDA_PE_REG
00198 #define TWI_SDA_PE_REG PIOB_PER
00199 #endif
00200 #ifndef TWI_SDA_OE_REG
00201 #define TWI_SDA_OE_REG PIOB_OER
00202 #endif
00203 #ifndef TWI_SDA_OD_REG
00204 #define TWI_SDA_OD_REG PIOB_ODR
00205 #endif
00206 #ifndef TWI_SDA_COD_REG
00207 #define TWI_SDA_COD_REG PIOB_CODR
00208 #endif
00209 #ifndef TWI_SDA_SOD_REG
00210 #define TWI_SDA_SOD_REG PIOB_SODR
00211 #endif
00212 #ifndef TWI_SDA_PDS_REG
00213 #define TWI_SDA_PDS_REG PIOB_PDSR
00214 #endif
00215
00216 #ifndef TWI_SCL_PE_REG
00217 #define TWI_SCL_PE_REG PIOB_PER
00218 #endif
00219 #ifndef TWI_SCL_OE_REG
00220 #define TWI_SCL_OE_REG PIOB_OER
00221 #endif
00222 #ifndef TWI_SCL_OD_REG
00223 #define TWI_SCL_OD_REG PIOB_ODR
00224 #endif
00225 #ifndef TWI_SCL_COD_REG
00226 #define TWI_SCL_COD_REG PIOB_CODR
00227 #endif
00228 #ifndef TWI_SCL_SOD_REG
00229 #define TWI_SCL_SOD_REG PIOB_SODR
00230 #endif
00231 #ifndef TWI_SCL_PDS_REG
00232 #define TWI_SCL_PDS_REG PIOB_PDSR
00233 #endif
00234
00235 #elif TWI_PIO_ID == PIOC_ID
00236
00237 #ifndef TWI_SDA_PE_REG
00238 #define TWI_SDA_PE_REG PIOC_PER
00239 #endif
00240 #ifndef TWI_SDA_OE_REG
00241 #define TWI_SDA_OE_REG PIOC_OER
00242 #endif
00243 #ifndef TWI_SDA_OD_REG
00244 #define TWI_SDA_OD_REG PIOC_ODR
00245 #endif
00246 #ifndef TWI_SDA_COD_REG
00247 #define TWI_SDA_COD_REG PIOC_CODR
00248 #endif
00249 #ifndef TWI_SDA_SOD_REG
00250 #define TWI_SDA_SOD_REG PIOC_SODR
00251 #endif
00252 #ifndef TWI_SDA_PDS_REG
00253 #define TWI_SDA_PDS_REG PIOC_PDSR
00254 #endif
00255
00256 #ifndef TWI_SCL_PE_REG
00257 #define TWI_SCL_PE_REG PIOC_PER
00258 #endif
00259 #ifndef TWI_SCL_OE_REG
00260 #define TWI_SCL_OE_REG PIOC_OER
00261 #endif
00262 #ifndef TWI_SCL_OD_REG
00263 #define TWI_SCL_OD_REG PIOC_ODR
00264 #endif
00265 #ifndef TWI_SCL_COD_REG
00266 #define TWI_SCL_COD_REG PIOC_CODR
00267 #endif
00268 #ifndef TWI_SCL_SOD_REG
00269 #define TWI_SCL_SOD_REG PIOC_SODR
00270 #endif
00271 #ifndef TWI_SCL_PDS_REG
00272 #define TWI_SCL_PDS_REG PIOC_PDSR
00273 #endif
00274
00275 #else
00276
00277 #ifndef TWI_SDA_PE_REG
00278 #define TWI_SDA_PE_REG PIO_PER
00279 #endif
00280 #ifndef TWI_SDA_OE_REG
00281 #define TWI_SDA_OE_REG PIO_OER
00282 #endif
00283 #ifndef TWI_SDA_OD_REG
00284 #define TWI_SDA_OD_REG PIO_ODR
00285 #endif
00286 #ifndef TWI_SDA_COD_REG
00287 #define TWI_SDA_COD_REG PIO_CODR
00288 #endif
00289 #ifndef TWI_SDA_SOD_REG
00290 #define TWI_SDA_SOD_REG PIO_SODR
00291 #endif
00292 #ifndef TWI_SDA_PDS_REG
00293 #define TWI_SDA_PDS_REG PIO_PDSR
00294 #endif
00295
00296 #ifndef TWI_SCL_PE_REG
00297 #define TWI_SCL_PE_REG PIO_PER
00298 #endif
00299 #ifndef TWI_SCL_OE_REG
00300 #define TWI_SCL_OE_REG PIO_OER
00301 #endif
00302 #ifndef TWI_SCL_OD_REG
00303 #define TWI_SCL_OD_REG PIO_ODR
00304 #endif
00305 #ifndef TWI_SCL_COD_REG
00306 #define TWI_SCL_COD_REG PIO_CODR
00307 #endif
00308 #ifndef TWI_SCL_SOD_REG
00309 #define TWI_SCL_SOD_REG PIO_SODR
00310 #endif
00311 #ifndef TWI_SCL_PDS_REG
00312 #define TWI_SCL_PDS_REG PIO_PDSR
00313 #endif
00314
00315 #endif
00316
00317 #define TWI_ENABLE() { \
00318 outr(TWI_SDA_COD_REG, _BV(TWI_SDA_BIT)); \
00319 outr(TWI_SCL_COD_REG, _BV(TWI_SCL_BIT)); \
00320 outr(TWI_SDA_PE_REG, _BV(TWI_SDA_BIT)); \
00321 outr(TWI_SCL_PE_REG, _BV(TWI_SCL_BIT)); \
00322 }
00323
00324 #define SDA_LOW() { \
00325 outr(TWI_SDA_COD_REG, _BV(TWI_SDA_BIT)); \
00326 outr(TWI_SDA_OE_REG, _BV(TWI_SDA_BIT)); \
00327 }
00328
00329 #define SDA_HIGH() { \
00330 outr(TWI_SDA_SOD_REG, _BV(TWI_SDA_BIT)); \
00331 outr(TWI_SDA_OD_REG, _BV(TWI_SDA_BIT)); \
00332 }
00333
00334 #define SDA_STAT() (inr(TWI_SDA_PDS_REG) & _BV(TWI_SDA_BIT))
00335
00336 #define SCL_LOW() { \
00337 outr(TWI_SCL_COD_REG, _BV(TWI_SCL_BIT)); \
00338 outr(TWI_SCL_OE_REG, _BV(TWI_SCL_BIT)); \
00339 }
00340
00341 #define SCL_HIGH() { \
00342 outr(TWI_SCL_SOD_REG, _BV(TWI_SCL_BIT)); \
00343 outr(TWI_SCL_OD_REG, _BV(TWI_SCL_BIT)); \
00344 }
00345
00346 #elif defined(__AVR__)
00347
00348
00349
00350
00351 #include <cfg/arch/avr.h>
00352
00353 #ifndef TWI_SDA_BIT
00354 #define TWI_SDA_BIT 0
00355 #endif
00356
00357 #if (TWI_SDA_AVRPORT == AVRPORTD)
00358 #define TWI_SDA_PORT PORTD
00359 #define TWI_SDA_PIN PIND
00360 #define TWI_SDA_DDR DDRD
00361 #elif (TWI_SDA_AVRPORT == AVRPORTE)
00362 #define TWI_SDA_PORT PORTE
00363 #define TWI_SDA_PIN PINE
00364 #define TWI_SDA_DDR DDRE
00365 #elif (TWI_SDA_AVRPORT == AVRPORTF)
00366 #define TWI_SDA_PORT PORTF
00367 #define TWI_SDA_PIN PINF
00368 #define TWI_SDA_DDR DDRF
00369 #else
00370 #define TWI_SDA_PORT PORTB
00371 #define TWI_SDA_PIN PINB
00372 #define TWI_SDA_DDR DDRB
00373 #endif
00374
00375 #ifndef TWI_SCL_BIT
00376 #define TWI_SCL_BIT 1
00377 #endif
00378
00379 #if (TWI_SCL_AVRPORT == AVRPORTD)
00380 #define TWI_SCL_PORT PORTD
00381 #define TWI_SCL_DDR DDRD
00382 #elif (TWI_SCL_AVRPORT == AVRPORTE)
00383 #define TWI_SCL_PORT PORTE
00384 #define TWI_SCL_DDR DDRE
00385 #elif (TWI_SCL_AVRPORT == AVRPORTF)
00386 #define TWI_SCL_PORT PORTF
00387 #define TWI_SCL_DDR DDRF
00388 #else
00389 #define TWI_SCL_PORT PORTB
00390 #define TWI_SCL_DDR DDRB
00391 #endif
00392
00393 #define TWI_ENABLE() { \
00394 cbi(TWI_SDA_PORT, TWI_SDA_BIT); \
00395 cbi(TWI_SCL_PORT, TWI_SCL_BIT); \
00396 }
00397
00398 #define SDA_LOW() sbi(TWI_SDA_DDR, TWI_SDA_BIT)
00399 #define SDA_HIGH() cbi(TWI_SDA_DDR, TWI_SDA_BIT)
00400 #define SDA_STAT() bit_is_set(TWI_SDA_PIN, TWI_SDA_BIT)
00401
00402 #define SCL_LOW() sbi(TWI_SCL_DDR, TWI_SCL_BIT)
00403 #define SCL_HIGH() cbi(TWI_SCL_DDR, TWI_SCL_BIT)
00404
00405 #ifndef TWI_DELAY
00406 #define TWI_DELAY 8
00407 #endif
00408
00409 #endif
00410
00411
00412 static uint8_t tw_mm_error;
00413 static int twibb_initialized;
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 static void TwDelay(int nops)
00424 {
00425 while (nops--) {
00426 _NOP();
00427 }
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437 static void TwStart(void)
00438 {
00439 SDA_HIGH();
00440 TwDelay(TWI_DELAY);
00441 SCL_HIGH();
00442 TwDelay(TWI_DELAY);
00443 SDA_LOW();
00444 TwDelay(TWI_DELAY);
00445 SCL_LOW();
00446 TwDelay(TWI_DELAY);
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456 static void TwStop(void)
00457 {
00458 SDA_LOW();
00459 TwDelay(TWI_DELAY);
00460 SCL_HIGH();
00461 TwDelay(2 * TWI_DELAY);
00462 SDA_HIGH();
00463 TwDelay(8 * TWI_DELAY);
00464 }
00465
00466
00467
00468
00469
00470
00471
00472 static int TwPut(uint8_t octet)
00473 {
00474 int i;
00475
00476 for (i = 0x80; i; i >>= 1) {
00477
00478 if (octet & i) {
00479 SDA_HIGH();
00480 } else {
00481 SDA_LOW();
00482 }
00483
00484 TwDelay(TWI_DELAY);
00485
00486 SCL_HIGH();
00487 TwDelay(2 * TWI_DELAY);
00488 SCL_LOW();
00489 TwDelay(TWI_DELAY);
00490 }
00491
00492
00493 SDA_HIGH();
00494
00495
00496 SCL_HIGH();
00497 TwDelay(2 * TWI_DELAY);
00498 if (SDA_STAT()) {
00499 i = -1;
00500 } else {
00501 i = 0;
00502 }
00503 SCL_LOW();
00504
00505 return i;
00506 }
00507
00508
00509
00510
00511
00512
00513
00514 static uint8_t TwGet(void)
00515 {
00516 uint8_t rc = 0;
00517 int i;
00518
00519
00520 SDA_HIGH();
00521 TwDelay(TWI_DELAY);
00522 for (i = 0x80; i; i >>= 1) {
00523 TwDelay(TWI_DELAY);
00524
00525 SCL_HIGH();
00526 TwDelay(2 * TWI_DELAY);
00527
00528 if (SDA_STAT()) {
00529 rc |= i;
00530 }
00531 SCL_LOW();
00532 }
00533 return rc;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542 static void TwAck(void)
00543 {
00544 SDA_LOW();
00545 TwDelay(TWI_DELAY);
00546 SCL_HIGH();
00547 TwDelay(2 * TWI_DELAY);
00548 SCL_LOW();
00549 TwDelay(TWI_DELAY);
00550 SDA_HIGH();
00551 }
00552
00580 int TwMasterTransact(uint8_t sla, CONST void *txdata, uint16_t txlen, void *rxdata, uint16_t rxsiz, uint32_t tmo)
00581 {
00582 int rc = 0;
00583 uint8_t *cp;
00584
00585 if (!twibb_initialized) {
00586 TwInit(0);
00587 }
00588
00589 if (txlen) {
00590 TwStart();
00591
00592 if ((rc = TwPut(sla << 1)) == 0) {
00593 for (cp = (uint8_t *)txdata; txlen--; cp++) {
00594 if ((rc = TwPut(*cp)) != 0) {
00595 break;
00596 }
00597 }
00598 }
00599 }
00600 if (rc == 0 && rxsiz) {
00601 TwStart();
00602
00603 if ((rc = TwPut((sla << 1) | 1)) == 0) {
00604 for (cp = rxdata;; cp++) {
00605 *cp = TwGet();
00606 if (++rc >= rxsiz) {
00607 break;
00608 }
00609 TwAck();
00610 }
00611 }
00612 }
00613 TwStop();
00614
00615 if (rc == -1) {
00616 tw_mm_error = TWERR_SLA_NACK;
00617 }
00618 return rc;
00619 }
00620
00629 int TwMasterError(void)
00630 {
00631 int rc = (int) tw_mm_error;
00632 tw_mm_error = 0;
00633
00634 return rc;
00635 }
00636
00660 int TwSlaveListen(uint8_t * sla, void *rxdata, uint16_t rxsiz, uint32_t tmo)
00661 {
00662 return -1;
00663 }
00664
00683 int TwSlaveRespond(void *txdata, uint16_t txlen, uint32_t tmo)
00684 {
00685 return -1;
00686 }
00687
00699 int TwSlaveError(void)
00700 {
00701 return TWERR_BUS;
00702 }
00703
00716 int TwIOCtl(int req, void *conf)
00717 {
00718 return 0;
00719 }
00720
00736 int TwInit(uint8_t sla)
00737 {
00738 SDA_HIGH();
00739 SCL_HIGH();
00740 TWI_ENABLE();
00741 twibb_initialized = 1;
00742
00743 return 0;
00744 }