From: asterix Date: Tue, 20 Jul 2010 10:17:00 +0000 (+0000) Subject: Fix read function. Add comment. Use macro for registers devices specific. X-Git-Tag: 2.6.0~288^2~58 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=bc29f088a13db6ebf7296d11fc29c49b53d298cb;p=bertos.git Fix read function. Add comment. Use macro for registers devices specific. git-svn-id: https://src.develer.com/svnoss/bertos/branches/i2c@4035 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/cpu/arm/drv/i2c_lpc2.c b/bertos/cpu/arm/drv/i2c_lpc2.c index 4619e537..270f4c02 100644 --- a/bertos/cpu/arm/drv/i2c_lpc2.c +++ b/bertos/cpu/arm/drv/i2c_lpc2.c @@ -54,15 +54,11 @@ #include - -#define I2C_READBIT BV(0) - /* * */ #if 1 /* I2C 0 */ - #define I2C_PCONP PCONP_PCI2C0 #define I2C_CONSET I20CONSET #define I2C_CONCLR I20CONCLR @@ -70,21 +66,36 @@ #define I2C_SCLL I20SCLL #define I2C_STAT I20STAT #define I2C_DAT I20DAT - #define I2C_SDA_PINSEL_MASK I2C_SDA0_PINSEL_MASK - #define I2C_SCL_PINSEL_MASK I2C_SCL0_PINSEL_MASK - #define I2C_SDA_PINSEL I2C_SDA0_PINSEL - #define I2C_SCL_PINSEL I2C_SCL0_PINSEL + #define I2C_PINSEL_PORT PINSEL1 + #define I2C_PINSEL I2C0_PINSEL + #define I2C_PINSEL_MASK I2C0_PINSEL_MASK + #define I2C_PCLKSEL PCLKSEL0 + #define I2C_PCLK_MASK I2C0_PCLK_MASK + #define I2C_PCLK_DIV8 I2C0_PCLK_DIV8 #else /* I2C 1 */ + #error #endif -#define GET_STATUS() (I2C_STAT) +#define GET_STATUS() ((uint8_t)I2C_STAT) +/* + * Wait that SI bit is set. + * + * Note: this bit is set when the I2C state changes. However, entering + * state F8 does not set SI since there is nothing for an interrupt service + * routine to do in that case. + */ +#define WAIT_SI() while( !(I2C_CONSET & BV(I2CON_SI)) ) static uint8_t i2c_builtin_start(void) { + // Clear all pending flags. + I2C_CONCLR = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC); + + // Set start and ack bit. I2C_CONSET = BV(I2CON_STA) | BV(I2CON_AA); - while( !(I2C_CONSET & BV(I2CON_SI)) ); + WAIT_SI(); return true; } @@ -102,8 +113,9 @@ bool i2c_builtin_start_w(uint8_t id) ticks_t start = timer_clock(); while (i2c_builtin_start()) { - uint32_t status = GET_STATUS(); + uint8_t status = GET_STATUS(); + /* Start status ok, set addres and the R/W bit */ if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND)) I2C_DAT = id & ~I2C_READBIT; @@ -113,7 +125,10 @@ bool i2c_builtin_start_w(uint8_t id) if (status == I2C_STAT_SLAW_ACK) return true; else if (status == I2C_STAT_ARB_LOST) + { + LOG_ERR("Arbitration lost\n"); break; + } else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT)) { LOG_ERR("Timeout on I2C START\n"); @@ -135,22 +150,30 @@ bool i2c_builtin_start_r(uint8_t id) { if (i2c_builtin_start()) { - uint32_t status = GET_STATUS(); + uint8_t status = GET_STATUS(); + /* Start status ok, set addres and the R/W bit */ if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND)) I2C_DAT = id | I2C_READBIT; /* Clear the start bit and clear the SI bit */ I2C_CONCLR = BV(I2CON_SIC) | BV(I2CON_STAC); - while( !(I2C_CONSET & BV(I2CON_SI)) ); + WAIT_SI(); status = GET_STATUS(); if (status == I2C_STAT_SLAR_ACK) return true; + + else if (status == I2C_STAT_SLAR_ACK) + { + LOG_ERR("SLAR NACK:%02x\n", status); + } else if (status == I2C_STAT_ARB_LOST) - return false; + { + LOG_ERR("ARB Lost:%02x\n", status); + } } return false; @@ -159,7 +182,9 @@ bool i2c_builtin_start_r(uint8_t id) void i2c_builtin_stop(void) { + /* Set the stop bit */ I2C_CONSET = BV(I2CON_STO); + /* Clear pending flags */ I2C_CONCLR = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC); } @@ -183,33 +208,33 @@ int i2c_builtin_get(bool ack) bool i2c_send(const void *_buf, size_t count) { const uint8_t *buf = (const uint8_t *)_buf; - uint32_t status = 0; + uint8_t status = 0; while (count) { I2C_DAT = *buf++; - I2C_CONSET = BV(I2CON_AA); I2C_CONCLR = BV(I2CON_SIC); count--; - while( !(I2C_CONSET & BV(I2CON_SI)) ); + WAIT_SI(); status = GET_STATUS(); + if (status == I2C_STAT_DATA_ACK) continue; else if (status == I2C_STAT_DATA_NACK) { - LOG_ERR("send:%02x\n", (uint8_t)status); + LOG_ERR("Data NACK\n"); return false; } - else if (status == 0xf8) + else if (status == I2C_STAT_ERROR) { - LOG_ERR("send:%02x\n", (uint8_t)status); + LOG_ERR("I2C error.\n"); return false; } - else if (status == 0x10) + else if (status == I2C_STAT_UNKNOW) { - LOG_ERR("send:%02x\n", (uint8_t)status); + LOG_ERR("I2C unable to read status.\n"); return false; } @@ -226,11 +251,19 @@ bool i2c_recv(void *_buf, size_t count) uint8_t *buf = (uint8_t *)_buf; uint8_t status = GET_STATUS(); -// LOG_ERR("recv:%02x\n", (uint8_t)status); + /* Ready for read */ + I2C_CONSET = BV(I2CON_AA); + I2C_CONCLR = BV(I2CON_SIC); + + WAIT_SI(); while (count) { *buf++ = I2C_DAT; + /* + * Set ack bit if we want read more byte, otherwise + * we disable it + */ if (count > 1) I2C_CONSET = BV(I2CON_AA); else @@ -239,25 +272,22 @@ bool i2c_recv(void *_buf, size_t count) I2C_CONCLR = BV(I2CON_SIC); count--; - while( !(I2C_CONSET & BV(I2CON_SI)) ); + WAIT_SI(); status = GET_STATUS(); if (status == I2C_STAT_RDATA_ACK) continue; else if (status == I2C_STAT_RDATA_NACK) - { - // LOG_ERR("recv:%02x\n", (uint8_t)status); return true; - } - else if (status == 0xf8) + else if (status == I2C_STAT_ERROR) { - LOG_ERR("recv:%02x\n", (uint8_t)status); + LOG_ERR("I2C error.\n"); return false; } - else if (status == 0x10) + else if (status == I2C_STAT_UNKNOW) { - LOG_ERR("recv:%02x\n", (uint8_t)status); + LOG_ERR("I2C unable to read status.\n"); return false; } } @@ -285,8 +315,8 @@ void i2c_builtin_init(void) * Bit Frequency = Fplk / (I2C_I2SCLH + I2C_I2SCLL) * value of I2SCLH and I2SCLL must be different */ - PCLKSEL0 &= ~I2C0_PCLK_MASK; - PCLKSEL0 |= I2C0_PCLK_DIV8; + I2C_PCLKSEL &= ~I2C_PCLK_MASK; + I2C_PCLKSEL |= I2C_PCLK_DIV8; I2C_SCLH = (((CPU_FREQ / 8) / CONFIG_I2C_FREQ) / 2) + 1; I2C_SCLL = (((CPU_FREQ / 8) / CONFIG_I2C_FREQ) / 2); @@ -294,8 +324,8 @@ void i2c_builtin_init(void) ASSERT(I2C_SCLH > 4 || I2C_SCLL > 4); /* Assign pins to SCL and SDA (P0_27, P0_28) */ - PINSEL1 &= ~I2C_PINSEL_MASK; - PINSEL1 |= I2C_PINSEL; + I2C_PINSEL_PORT &= ~I2C_PINSEL_MASK; + I2C_PINSEL_PORT |= I2C_PINSEL; // Enable I2C I2C_CONSET = BV(I2CON_I2EN);