X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fi2c_stm32.c;h=9fd53f0128e1ea249ad28101842a9ff4517267aa;hb=745d9627b4c8b8db6a17511cf1b1ca380c4193d7;hp=9807de1194fef81a0c39d16eb3d3381994ecdbca;hpb=98eb98b118f4274745b41ad99833c3f08938e60c;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/i2c_stm32.c b/bertos/cpu/cortex-m3/drv/i2c_stm32.c index 9807de11..9fd53f01 100644 --- a/bertos/cpu/cortex-m3/drv/i2c_stm32.c +++ b/bertos/cpu/cortex-m3/drv/i2c_stm32.c @@ -81,7 +81,11 @@ INLINE uint32_t get_status(struct stm32_i2c *base) return ((base->SR1 | (base->SR2 << 16)) & 0x00FFFFFF); } - +/* + * This fuction read the status registers of the i2c device + * and waint until the selec event happen. If occur one error + * the funtions return false. + */ INLINE bool wait_event(I2c *i2c, uint32_t event) { while (true) @@ -101,129 +105,139 @@ INLINE bool wait_event(I2c *i2c, uint32_t event) return true; } -static void i2c_stm32_start(struct I2c *i2c, uint16_t slave_addr) -{ - i2c->hw->cached = false; - - if (I2C_TEST_START(i2c->flags) == I2C_START_W) - { - /* - * Loop on the select write sequence: when the eeprom is busy - * writing previously sent data it will reply to the SLA_W - * control byte with a NACK. In this case, we must - * keep trying until the eeprom responds with an ACK. - */ - ticks_t start = timer_clock(); - while (true) - { - i2c->hw->base->CR1 |= CR1_ACK_SET | CR1_START_SET; - - if(!wait_event(i2c, I2C_EVENT_MASTER_MODE_SELECT)) - { - LOG_ERR("ARBIT lost\n"); - i2c->errors |= I2C_ARB_LOST; - break; - } - - i2c->hw->base->DR = slave_addr & OAR1_ADD0_RESET; - - if(wait_event(i2c, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) - break; - - if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT)) - { - LOG_ERR("Timeout on I2C START\n"); - i2c->errors |= I2C_START_TIMEOUT; - i2c->hw->base->CR1 |= CR1_STOP_SET; - break; - } - } - } - else /* (I2C_TEST_START(i2c->flags) == I2C_START_R) */ +INLINE void start_w(struct I2c *i2c, uint16_t slave_addr) +{ + /* + * Loop on the select write sequence: when the eeprom is busy + * writing previously sent data it will reply to the SLA_W + * control byte with a NACK. In this case, we must + * keep trying until the eeprom responds with an ACK. + */ + ticks_t start = timer_clock(); + while (true) { - i2c->hw->base->CR1 |= CR1_START_SET; + i2c->hw->base->CR1 |= CR1_ACK_SET | CR1_START_SET; if(!wait_event(i2c, I2C_EVENT_MASTER_MODE_SELECT)) { LOG_ERR("ARBIT lost\n"); i2c->errors |= I2C_ARB_LOST; - i2c->hw->base->CR1 |= CR1_STOP_SET; - return; + break; } - i2c->hw->base->DR = (slave_addr | OAR1_ADD0_SET); + i2c->hw->base->DR = slave_addr & OAR1_ADD0_RESET; - if (i2c->xfer_size == 2) - i2c->hw->base->CR1 |= CR1_ACK_SET | CR1_POS_SET; + if(wait_event(i2c, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) + break; - if(!wait_event(i2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) + if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT)) { - LOG_ERR("SLAR NACK:%08lx\n", get_status(i2c->hw->base)); - i2c->errors |= I2C_NO_ACK; + LOG_ERR("Timeout on I2C START\n"); + i2c->errors |= I2C_START_TIMEOUT; i2c->hw->base->CR1 |= CR1_STOP_SET; - return; + break; } + } +} - if (i2c->xfer_size == 1) - { - i2c->hw->base->CR1 &= CR1_ACK_RESET; - - cpu_flags_t irq; - IRQ_SAVE_DISABLE(irq); +INLINE bool start_and_addr(struct I2c *i2c, uint16_t slave_addr) +{ + i2c->hw->base->CR1 |= CR1_START_SET; + if(!wait_event(i2c, I2C_EVENT_MASTER_MODE_SELECT)) + { + LOG_ERR("ARBIT lost\n"); + i2c->errors |= I2C_ARB_LOST; + i2c->hw->base->CR1 |= CR1_STOP_SET; + return false; + } - (void)i2c->hw->base->SR2; + i2c->hw->base->DR = (slave_addr | OAR1_ADD0_SET); - if (I2C_TEST_STOP(i2c->flags) == I2C_STOP) - i2c->hw->base->CR1 |= CR1_STOP_SET; + if (i2c->xfer_size == 2) + i2c->hw->base->CR1 |= CR1_ACK_SET | CR1_POS_SET; - IRQ_RESTORE(irq); + if(!wait_event(i2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) + { + LOG_ERR("SLAR NACK:%08lx\n", get_status(i2c->hw->base)); + i2c->errors |= I2C_NO_ACK; + i2c->hw->base->CR1 |= CR1_STOP_SET; + return false; + } - WAIT_RXNE(i2c->hw->base); + return true; +} - i2c->hw->cache[0] = i2c->hw->base->DR; - i2c->hw->cached = true; +INLINE void start_r(struct I2c *i2c, uint16_t slave_addr) +{ + if (!start_and_addr(i2c, slave_addr)) + return; + /* + * Due to the hardware receive bytes from slave in automatically mode + * we should manage contextually all cases that we want to read one, two or more + * than two bytes. To comply this behaviour to our api we shoul bufferd some byte + * to hide all special case that needs to use this device. + */ + if (i2c->xfer_size == 1) + { + i2c->hw->base->CR1 &= CR1_ACK_RESET; - if (I2C_TEST_STOP(i2c->flags) == I2C_STOP) - while (i2c->hw->base->CR1 & CR1_STOP_SET); + cpu_flags_t irq; - i2c->hw->base->CR1 |= CR1_ACK_SET; + IRQ_SAVE_DISABLE(irq); + (void)i2c->hw->base->SR2; + if (I2C_TEST_STOP(i2c->flags) == I2C_STOP) + i2c->hw->base->CR1 |= CR1_STOP_SET; + IRQ_RESTORE(irq); - } - else if (i2c->xfer_size == 2) - { - cpu_flags_t irq; - IRQ_SAVE_DISABLE(irq); + WAIT_RXNE(i2c->hw->base); - (void)i2c->hw->base->SR2; + i2c->hw->cache[0] = i2c->hw->base->DR; + i2c->hw->cached = true; - i2c->hw->base->CR1 &= CR1_ACK_RESET; + if (I2C_TEST_STOP(i2c->flags) == I2C_STOP) + while (i2c->hw->base->CR1 & CR1_STOP_SET); - IRQ_RESTORE(irq); + i2c->hw->base->CR1 |= CR1_ACK_SET; + } + else if (i2c->xfer_size == 2) + { + cpu_flags_t irq; - WAIT_BTF(i2c->hw->base); + IRQ_SAVE_DISABLE(irq); + (void)i2c->hw->base->SR2; + i2c->hw->base->CR1 &= CR1_ACK_RESET; + IRQ_RESTORE(irq); - IRQ_SAVE_DISABLE(irq); + WAIT_BTF(i2c->hw->base); - if (I2C_TEST_STOP(i2c->flags) == I2C_STOP) - i2c->hw->base->CR1 |= CR1_STOP_SET; + IRQ_SAVE_DISABLE(irq); + if (I2C_TEST_STOP(i2c->flags) == I2C_STOP) + i2c->hw->base->CR1 |= CR1_STOP_SET; + /* + * We store read bytes like a fifo.. + */ + i2c->hw->cache[1] = i2c->hw->base->DR; + i2c->hw->cache[0] = i2c->hw->base->DR; + i2c->hw->cached = true; + IRQ_RESTORE(irq); - /* - * We store read bytes like a fifo.. - */ - i2c->hw->cache[1] = i2c->hw->base->DR; - i2c->hw->cache[0] = i2c->hw->base->DR; - i2c->hw->cached = true; + i2c->hw->base->CR1 &= CR1_POS_RESET; + i2c->hw->base->CR1 |= CR1_ACK_SET; + } +} - IRQ_RESTORE(irq); +static void i2c_stm32_start(struct I2c *i2c, uint16_t slave_addr) +{ + i2c->hw->cached = false; - i2c->hw->base->CR1 &= CR1_POS_RESET; - i2c->hw->base->CR1 |= CR1_ACK_SET; - } - } + if (I2C_TEST_START(i2c->flags) == I2C_START_W) + start_w(i2c, slave_addr); + else /* (I2C_TEST_START(i2c->flags) == I2C_START_R) */ + start_r(i2c, slave_addr); } -static void i2c_stm32_put(I2c *i2c, const uint8_t data) +static void i2c_stm32_putc(I2c *i2c, const uint8_t data) { i2c->hw->base->DR = data; @@ -237,7 +251,7 @@ static void i2c_stm32_put(I2c *i2c, const uint8_t data) } } -static uint8_t i2c_stm32_get(I2c *i2c) +static uint8_t i2c_stm32_getc(I2c *i2c) { if (i2c->hw->cached) { @@ -283,13 +297,13 @@ static uint8_t i2c_stm32_get(I2c *i2c) static const I2cVT i2c_stm32_vt = { .start = i2c_stm32_start, - .get = i2c_stm32_get, - .put = i2c_stm32_put, - .send = i2c_swSend, - .recv = i2c_swRecv, + .getc = i2c_stm32_getc, + .putc = i2c_stm32_putc, + .write = i2c_genericWrite, + .read = i2c_genericRead, }; -struct I2cHardware i2c_stm32_hw[] = +static struct I2cHardware i2c_stm32_hw[] = { { /* I2C1 */ .base = (struct stm32_i2c *)I2C1_BASE, @@ -303,8 +317,6 @@ struct I2cHardware i2c_stm32_hw[] = }, }; -MOD_DEFINE(i2c); - /** * Initialize I2C module. */ @@ -338,6 +350,4 @@ void i2c_hw_init(I2c *i2c, int dev, uint32_t clock) i2c->hw->base->TRISE |= (CR2_FREQ_36MHZ + 1); i2c->hw->base->CR1 |= CR1_PE_SET; - - MOD_INIT(i2c); }