I2C. In functions added local pointer to I2C_TypeDef structure.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3770 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
barthess 2012-01-08 20:41:27 +00:00
parent 16d354e687
commit 4284d0ee15
1 changed files with 66 additions and 55 deletions

View File

@ -142,12 +142,13 @@ static volatile uint16_t dbgCR2;
* @notapi * @notapi
*/ */
static void i2c_lld_abort_operation(I2CDriver *i2cp) { static void i2c_lld_abort_operation(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
/* Stops the I2C peripheral.*/ /* Stops the I2C peripheral.*/
i2cp->i2c->CR1 = I2C_CR1_SWRST; dp->CR1 = I2C_CR1_SWRST;
i2cp->i2c->CR1 = 0; dp->CR1 = 0;
i2cp->i2c->CR2 = 0; dp->CR2 = 0;
i2cp->i2c->SR1 = 0; dp->SR1 = 0;
/* Stops the associated DMA streams.*/ /* Stops the associated DMA streams.*/
dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmatx);
@ -181,6 +182,7 @@ static void i2c_lld_safety_timeout(void *p) {
* @notapi * @notapi
*/ */
static void i2c_lld_set_clock(I2CDriver *i2cp) { static void i2c_lld_set_clock(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
uint16_t regCCR, clock_div; uint16_t regCCR, clock_div;
int32_t clock_speed = i2cp->config->clock_speed; int32_t clock_speed = i2cp->config->clock_speed;
i2cdutycycle_t duty = i2cp->config->duty_cycle; i2cdutycycle_t duty = i2cp->config->duty_cycle;
@ -189,8 +191,8 @@ static void i2c_lld_set_clock(I2CDriver *i2cp) {
"i2c_lld_set_clock"); "i2c_lld_set_clock");
/* CR2 Configuration.*/ /* CR2 Configuration.*/
i2cp->i2c->CR2 &= (uint16_t)~I2C_CR2_FREQ; dp->CR2 &= (uint16_t)~I2C_CR2_FREQ;
i2cp->i2c->CR2 |= (uint16_t)I2C_CLK_FREQ; dp->CR2 |= (uint16_t)I2C_CLK_FREQ;
/* CCR Configuration.*/ /* CCR Configuration.*/
regCCR = 0; regCCR = 0;
@ -211,7 +213,7 @@ static void i2c_lld_set_clock(I2CDriver *i2cp) {
regCCR |= (clock_div & I2C_CCR_CCR); regCCR |= (clock_div & I2C_CCR_CCR);
/* Sets the Maximum Rise Time for standard mode.*/ /* Sets the Maximum Rise Time for standard mode.*/
i2cp->i2c->TRISE = I2C_CLK_FREQ + 1; dp->TRISE = I2C_CLK_FREQ + 1;
} }
else if (clock_speed <= 400000) { else if (clock_speed <= 400000) {
/* Configure clock_div in fast mode.*/ /* Configure clock_div in fast mode.*/
@ -234,13 +236,13 @@ static void i2c_lld_set_clock(I2CDriver *i2cp) {
regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR));
/* Sets the Maximum Rise Time for fast mode.*/ /* Sets the Maximum Rise Time for fast mode.*/
i2cp->i2c->TRISE = (I2C_CLK_FREQ * 300 / 1000) + 1; dp->TRISE = (I2C_CLK_FREQ * 300 / 1000) + 1;
} }
chDbgAssert((clock_div <= I2C_CCR_CCR), chDbgAssert((clock_div <= I2C_CCR_CCR),
"i2c_lld_set_clock(), #3", "the selected clock is too low"); "i2c_lld_set_clock(), #3", "the selected clock is too low");
i2cp->i2c->CCR = regCCR; dp->CCR = regCCR;
} }
/** /**
@ -251,10 +253,11 @@ static void i2c_lld_set_clock(I2CDriver *i2cp) {
* @notapi * @notapi
*/ */
static void i2c_lld_set_opmode(I2CDriver *i2cp) { static void i2c_lld_set_opmode(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
i2copmode_t opmode = i2cp->config->op_mode; i2copmode_t opmode = i2cp->config->op_mode;
uint16_t regCR1; uint16_t regCR1;
regCR1 = i2cp->i2c->CR1; regCR1 = dp->CR1;
switch (opmode) { switch (opmode) {
case OPMODE_I2C: case OPMODE_I2C:
regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE);
@ -267,7 +270,7 @@ static void i2c_lld_set_opmode(I2CDriver *i2cp) {
regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE);
break; break;
} }
i2cp->i2c->CR1 = regCR1; dp->CR1 = regCR1;
} }
/** /**
@ -281,14 +284,15 @@ static void i2c_lld_set_opmode(I2CDriver *i2cp) {
* @notapi * @notapi
*/ */
static uint32_t i2c_get_event(I2CDriver *i2cp) { static uint32_t i2c_get_event(I2CDriver *i2cp) {
uint16_t regSR1 = i2cp->i2c->SR1; I2C_TypeDef *dp = i2cp->i2c;
uint16_t regSR2 = i2cp->i2c->SR2; uint16_t regSR1 = dp->SR1;
uint16_t regSR2 = dp->SR2;
#if CH_DBG_ENABLE_ASSERTS #if CH_DBG_ENABLE_ASSERTS
dbgSR1 = regSR1; dbgSR1 = regSR1;
dbgSR2 = regSR2; dbgSR2 = regSR2;
dbgCR1 = i2cp->i2c->CR1; dbgCR1 = dp->CR1;
dbgCR2 = i2cp->i2c->CR2; dbgCR2 = dp->CR2;
#endif /* CH_DBG_ENABLE_ASSERTS */ #endif /* CH_DBG_ENABLE_ASSERTS */
return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); return (I2C_EV_MASK & (regSR1 | (regSR2 << 16)));
@ -302,21 +306,22 @@ static uint32_t i2c_get_event(I2CDriver *i2cp) {
* @notapi * @notapi
*/ */
static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
/* Interrupts are disabled just before dmaStreamEnable() because there /* Interrupts are disabled just before dmaStreamEnable() because there
is no need of interrupts until next transaction begin. All the work is is no need of interrupts until next transaction begin. All the work is
done by the DMA.*/ done by the DMA.*/
switch (i2c_get_event(i2cp)) { switch (i2c_get_event(i2cp)) {
case I2C_EV5_MASTER_MODE_SELECT: case I2C_EV5_MASTER_MODE_SELECT:
i2cp->i2c->DR = i2cp->addr; dp->DR = i2cp->addr;
break; break;
case I2C_EV6_MASTER_REC_MODE_SELECTED: case I2C_EV6_MASTER_REC_MODE_SELECTED:
i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; dp->CR2 &= ~I2C_CR2_ITEVTEN;
dmaStreamEnable(i2cp->dmarx); dmaStreamEnable(i2cp->dmarx);
i2cp->i2c->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */
break; break;
case I2C_EV6_MASTER_TRA_MODE_SELECTED: case I2C_EV6_MASTER_TRA_MODE_SELECTED:
i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; dp->CR2 &= ~I2C_CR2_ITEVTEN;
dmaStreamEnable(i2cp->dmatx); dmaStreamEnable(i2cp->dmatx);
break; break;
case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
@ -324,11 +329,11 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) { if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) {
/* Starts "read after write" operation, LSB = 1 -> receive.*/ /* Starts "read after write" operation, LSB = 1 -> receive.*/
i2cp->addr |= 0x01; i2cp->addr |= 0x01;
i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
return; return;
} }
i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; dp->CR2 &= ~I2C_CR2_ITEVTEN;
i2cp->i2c->CR1 |= I2C_CR1_STOP; dp->CR1 |= I2C_CR1_STOP;
wakeup_isr(i2cp, RDY_OK); wakeup_isr(i2cp, RDY_OK);
break; break;
default: default:
@ -345,6 +350,7 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
* @notapi * @notapi
*/ */
static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) {
I2C_TypeDef *dp = i2cp->i2c;
/* DMA errors handling.*/ /* DMA errors handling.*/
#if defined(STM32_I2C_DMA_ERROR_HOOK) #if defined(STM32_I2C_DMA_ERROR_HOOK)
@ -358,9 +364,9 @@ static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) {
dmaStreamDisable(i2cp->dmarx); dmaStreamDisable(i2cp->dmarx);
dmaStreamClearInterrupt(i2cp->dmarx); dmaStreamClearInterrupt(i2cp->dmarx);
i2cp->i2c->CR2 &= ~I2C_CR2_LAST; dp->CR2 &= ~I2C_CR2_LAST;
i2cp->i2c->CR1 &= ~I2C_CR1_ACK; dp->CR1 &= ~I2C_CR1_ACK;
i2cp->i2c->CR1 |= I2C_CR1_STOP; dp->CR1 |= I2C_CR1_STOP;
wakeup_isr(i2cp, RDY_OK); wakeup_isr(i2cp, RDY_OK);
} }
@ -372,6 +378,7 @@ static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) {
* @notapi * @notapi
*/ */
static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
I2C_TypeDef *dp = i2cp->i2c;
/* DMA errors handling.*/ /* DMA errors handling.*/
#if defined(STM32_I2C_DMA_ERROR_HOOK) #if defined(STM32_I2C_DMA_ERROR_HOOK)
@ -387,7 +394,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
/* Enables interrupts to catch BTF event meaning transmission part complete. /* Enables interrupts to catch BTF event meaning transmission part complete.
Interrupt handler will decide to generate STOP or to begin receiving part Interrupt handler will decide to generate STOP or to begin receiving part
of R/W transaction itself.*/ of R/W transaction itself.*/
i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN; dp->CR2 |= I2C_CR2_ITEVTEN;
} }
/** /**
@ -398,10 +405,11 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
* @notapi * @notapi
*/ */
static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp) { static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
i2cflags_t errors; i2cflags_t errors;
chSysLockFromIsr();
/* Clears interrupt flags just to be safe.*/ /* Clears interrupt flags just to be safe.*/
chSysLockFromIsr();
dmaStreamDisable(i2cp->dmatx); dmaStreamDisable(i2cp->dmatx);
dmaStreamDisable(i2cp->dmarx); dmaStreamDisable(i2cp->dmarx);
dmaStreamClearInterrupt(i2cp->dmatx); dmaStreamClearInterrupt(i2cp->dmatx);
@ -410,34 +418,34 @@ static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp) {
errors = I2CD_NO_ERROR; errors = I2CD_NO_ERROR;
if (i2cp->i2c->SR1 & I2C_SR1_BERR) { /* Bus error. */ if (dp->SR1 & I2C_SR1_BERR) { /* Bus error. */
i2cp->i2c->SR1 &= ~I2C_SR1_BERR; dp->SR1 &= ~I2C_SR1_BERR;
errors |= I2CD_BUS_ERROR; errors |= I2CD_BUS_ERROR;
} }
if (i2cp->i2c->SR1 & I2C_SR1_ARLO) { /* Arbitration lost. */ if (dp->SR1 & I2C_SR1_ARLO) { /* Arbitration lost. */
i2cp->i2c->SR1 &= ~I2C_SR1_ARLO; dp->SR1 &= ~I2C_SR1_ARLO;
errors |= I2CD_ARBITRATION_LOST; errors |= I2CD_ARBITRATION_LOST;
} }
if (i2cp->i2c->SR1 & I2C_SR1_AF) { /* Acknowledge fail. */ if (dp->SR1 & I2C_SR1_AF) { /* Acknowledge fail. */
i2cp->i2c->SR1 &= ~I2C_SR1_AF; dp->SR1 &= ~I2C_SR1_AF;
i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN; dp->CR2 &= ~I2C_CR2_ITEVTEN;
i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */ dp->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */
errors |= I2CD_ACK_FAILURE; errors |= I2CD_ACK_FAILURE;
} }
if (i2cp->i2c->SR1 & I2C_SR1_OVR) { /* Overrun. */ if (dp->SR1 & I2C_SR1_OVR) { /* Overrun. */
i2cp->i2c->SR1 &= ~I2C_SR1_OVR; dp->SR1 &= ~I2C_SR1_OVR;
errors |= I2CD_OVERRUN; errors |= I2CD_OVERRUN;
} }
if (i2cp->i2c->SR1 & I2C_SR1_PECERR) { /* PEC error. */ if (dp->SR1 & I2C_SR1_PECERR) { /* PEC error. */
i2cp->i2c->SR1 &= ~I2C_SR1_PECERR; dp->SR1 &= ~I2C_SR1_PECERR;
errors |= I2CD_PEC_ERROR; errors |= I2CD_PEC_ERROR;
} }
if (i2cp->i2c->SR1 & I2C_SR1_TIMEOUT) { /* SMBus Timeout. */ if (dp->SR1 & I2C_SR1_TIMEOUT) { /* SMBus Timeout. */
i2cp->i2c->SR1 &= ~I2C_SR1_TIMEOUT; dp->SR1 &= ~I2C_SR1_TIMEOUT;
errors |= I2CD_TIMEOUT; errors |= I2CD_TIMEOUT;
} }
if (i2cp->i2c->SR1 & I2C_SR1_SMBALERT) { /* SMBus alert. */ if (dp->SR1 & I2C_SR1_SMBALERT) { /* SMBus alert. */
i2cp->i2c->SR1 &= ~I2C_SR1_SMBALERT; dp->SR1 &= ~I2C_SR1_SMBALERT;
errors |= I2CD_SMB_ALERT; errors |= I2CD_SMB_ALERT;
} }
@ -584,6 +592,7 @@ void i2c_lld_init(void) {
* @notapi * @notapi
*/ */
void i2c_lld_start(I2CDriver *i2cp) { void i2c_lld_start(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
i2cp->dmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | i2cp->dmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
@ -676,20 +685,20 @@ void i2c_lld_start(I2CDriver *i2cp) {
dmaStreamSetMode(i2cp->dmarx, i2cp->dmamode | STM32_DMA_CR_DIR_P2M); dmaStreamSetMode(i2cp->dmarx, i2cp->dmamode | STM32_DMA_CR_DIR_P2M);
/* I2C registers pointed by the DMA.*/ /* I2C registers pointed by the DMA.*/
dmaStreamSetPeripheral(i2cp->dmarx, &i2cp->i2c->DR); dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
dmaStreamSetPeripheral(i2cp->dmatx, &i2cp->i2c->DR); dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
/* Reset i2c peripheral.*/ /* Reset i2c peripheral.*/
i2cp->i2c->CR1 = I2C_CR1_SWRST; dp->CR1 = I2C_CR1_SWRST;
i2cp->i2c->CR1 = 0; dp->CR1 = 0;
i2cp->i2c->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
/* Setup I2C parameters.*/ /* Setup I2C parameters.*/
i2c_lld_set_clock(i2cp); i2c_lld_set_clock(i2cp);
i2c_lld_set_opmode(i2cp); i2c_lld_set_opmode(i2cp);
/* Ready to go.*/ /* Ready to go.*/
i2cp->i2c->CR1 |= I2C_CR1_PE; dp->CR1 |= I2C_CR1_PE;
} }
/** /**
@ -761,6 +770,7 @@ void i2c_lld_stop(I2CDriver *i2cp) {
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
uint8_t *rxbuf, size_t rxbytes, uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) { systime_t timeout) {
I2C_TypeDef *dp = i2cp->i2c;
VirtualTimer vt; VirtualTimer vt;
msg_t rdymsg; msg_t rdymsg;
@ -782,7 +792,7 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
/* Waits until BUSY flag is reset and the STOP from the previous operation /* Waits until BUSY flag is reset and the STOP from the previous operation
is completed, alternatively for a timeout condition.*/ is completed, alternatively for a timeout condition.*/
while ((i2cp->i2c->SR2 & I2C_SR2_BUSY) || (i2cp->i2c->CR1 & I2C_CR1_STOP)) { while ((dp->SR2 & I2C_SR2_BUSY) || (dp->CR1 & I2C_CR1_STOP)) {
if (!chVTIsArmedI(&vt)) { if (!chVTIsArmedI(&vt)) {
chSysLock(); chSysLock();
return RDY_TIMEOUT; return RDY_TIMEOUT;
@ -798,8 +808,8 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
return RDY_TIMEOUT; return RDY_TIMEOUT;
/* Starts the operation.*/ /* Starts the operation.*/
i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN; dp->CR2 |= I2C_CR2_ITEVTEN;
i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
/* Waits for the operation completion or a timeout.*/ /* Waits for the operation completion or a timeout.*/
i2cp->thread = chThdSelf(); i2cp->thread = chThdSelf();
@ -840,6 +850,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
const uint8_t *txbuf, size_t txbytes, const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes, uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) { systime_t timeout) {
I2C_TypeDef *dp = i2cp->i2c;
VirtualTimer vt; VirtualTimer vt;
msg_t rdymsg; msg_t rdymsg;
@ -866,7 +877,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
/* Waits until BUSY flag is reset and the STOP from the previous operation /* Waits until BUSY flag is reset and the STOP from the previous operation
is completed, alternatively for a timeout condition.*/ is completed, alternatively for a timeout condition.*/
while ((i2cp->i2c->SR2 & I2C_SR2_BUSY) || (i2cp->i2c->CR1 & I2C_CR1_STOP)) { while ((dp->SR2 & I2C_SR2_BUSY) || (dp->CR1 & I2C_CR1_STOP)) {
if (!chVTIsArmedI(&vt)) { if (!chVTIsArmedI(&vt)) {
chSysLock(); chSysLock();
return RDY_TIMEOUT; return RDY_TIMEOUT;
@ -882,8 +893,8 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
return RDY_TIMEOUT; return RDY_TIMEOUT;
/* Starts the operation.*/ /* Starts the operation.*/
i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN; dp->CR2 |= I2C_CR2_ITEVTEN;
i2cp->i2c->CR1 |= I2C_CR1_START; dp->CR1 |= I2C_CR1_START;
/* Waits for the operation completion or a timeout.*/ /* Waits for the operation completion or a timeout.*/
i2cp->thread = chThdSelf(); i2cp->thread = chThdSelf();