git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5525 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
0e39ecd8bf
commit
0ebb7959d5
|
@ -56,7 +56,7 @@
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
#define I2C_MASTER_TC \
|
#define I2C_MASTER_TC \
|
||||||
((uint32_t)(I2C_ISR_BUSY|I2C_ISR_TC))
|
((uint32_t)(I2C_ISR_BUSY | I2C_ISR_TC))
|
||||||
|
|
||||||
#define I2C_ERROR_MASK \
|
#define I2C_ERROR_MASK \
|
||||||
((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \
|
((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \
|
||||||
|
@ -155,13 +155,14 @@ static void i2c_lld_safety_timeout(void *p) {
|
||||||
* @brief I2C shared ISR code.
|
* @brief I2C shared ISR code.
|
||||||
*
|
*
|
||||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||||
|
* @param[in] isr content of the ISR register to be decoded
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t status) {
|
static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) {
|
||||||
I2C_TypeDef *dp = i2cp->i2c;
|
I2C_TypeDef *dp = i2cp->i2c;
|
||||||
|
|
||||||
if (status & I2C_MASTER_TC) {
|
if (isr & I2C_ISR_TC) {
|
||||||
uint8_t rxbytes = dmaStreamGetTransactionSize(i2cp->dmarx);
|
uint8_t rxbytes = dmaStreamGetTransactionSize(i2cp->dmarx);
|
||||||
if (rxbytes > 0) {
|
if (rxbytes > 0) {
|
||||||
/* Enable RX DMA */
|
/* Enable RX DMA */
|
||||||
|
@ -179,6 +180,10 @@ static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t status) {
|
||||||
wakeup_isr(i2cp, RDY_OK);
|
wakeup_isr(i2cp, RDY_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (isr & I2C_ISR_NACKF) {
|
||||||
|
i2cp->errors |= I2CD_ACK_FAILURE;
|
||||||
|
wakeup_isr(i2cp, RDY_RESET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -231,48 +236,31 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
|
||||||
* @brief I2C error handler.
|
* @brief I2C error handler.
|
||||||
*
|
*
|
||||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||||
|
* @param[in] isr content of the ISR register to be decoded
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t status) {
|
static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) {
|
||||||
i2cflags_t errors;
|
|
||||||
|
|
||||||
/* Clears interrupt flags just to be safe.*/
|
/* Clears interrupt flags just to be safe.*/
|
||||||
dmaStreamDisable(i2cp->dmatx);
|
dmaStreamDisable(i2cp->dmatx);
|
||||||
dmaStreamDisable(i2cp->dmarx);
|
dmaStreamDisable(i2cp->dmarx);
|
||||||
|
|
||||||
errors = I2CD_NO_ERROR;
|
if (isr & I2C_ISR_BERR)
|
||||||
|
i2cp->errors |= I2CD_BUS_ERROR;
|
||||||
|
|
||||||
if (status & I2C_ISR_BERR) { /* Bus error. */
|
if (isr & I2C_ISR_ARLO)
|
||||||
status &= ~I2C_ISR_BERR;
|
i2cp->errors |= I2CD_ARBITRATION_LOST;
|
||||||
errors |= I2CD_BUS_ERROR;
|
|
||||||
}
|
if (isr & I2C_ISR_OVR)
|
||||||
if (status & I2C_ISR_ARLO) { /* Arbitration lost. */
|
i2cp->errors |= I2CD_OVERRUN;
|
||||||
status &= ~I2C_ISR_ARLO;
|
|
||||||
errors |= I2CD_ARBITRATION_LOST;
|
if (isr & I2C_ISR_TIMEOUT)
|
||||||
}
|
i2cp->errors |= I2CD_TIMEOUT;
|
||||||
if (status & I2C_ISR_OVR) { /* Overrun. */
|
|
||||||
status &= ~I2C_ISR_OVR;
|
|
||||||
errors |= I2CD_OVERRUN;
|
|
||||||
}
|
|
||||||
if (status & I2C_ISR_PECERR) { /* PEC error. */
|
|
||||||
status &= ~I2C_ISR_PECERR;
|
|
||||||
errors |= I2CD_PEC_ERROR;
|
|
||||||
}
|
|
||||||
if (status & I2C_ISR_TIMEOUT) { /* SMBus Timeout. */
|
|
||||||
status &= ~I2C_ISR_TIMEOUT;
|
|
||||||
errors |= I2CD_TIMEOUT;
|
|
||||||
}
|
|
||||||
if (status & I2C_ISR_ALERT) { /* SMBus alert. */
|
|
||||||
status &= ~I2C_ISR_ALERT;
|
|
||||||
errors |= I2CD_SMB_ALERT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If some error has been identified then sends wakes the waiting thread.*/
|
/* If some error has been identified then sends wakes the waiting thread.*/
|
||||||
if (errors != I2CD_NO_ERROR) {
|
if (i2cp->errors != I2CD_NO_ERROR)
|
||||||
i2cp->errors = errors;
|
|
||||||
wakeup_isr(i2cp, RDY_RESET);
|
wakeup_isr(i2cp, RDY_RESET);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -287,35 +275,44 @@ static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t status) {
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
CH_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) {
|
CH_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) {
|
||||||
uint32_t status = I2CD1.i2c->ISR;
|
uint32_t isr = I2CD1.i2c->ISR;
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
if (status & I2C_ERROR_MASK)
|
/* Clearing IRQ bits.*/
|
||||||
i2c_lld_serve_error_interrupt(&I2CD1, status);
|
I2CD1.i2c->ICR = isr;
|
||||||
else if (status & I2C_INT_MASK)
|
|
||||||
i2c_lld_serve_interrupt(&I2CD1, status);
|
if (isr & I2C_ERROR_MASK)
|
||||||
|
i2c_lld_serve_error_interrupt(&I2CD1, isr);
|
||||||
|
else if (isr & I2C_INT_MASK)
|
||||||
|
i2c_lld_serve_interrupt(&I2CD1, isr);
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER)
|
#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER)
|
||||||
CH_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
|
CH_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
|
||||||
uint32_t status = I2CD1.i2c->ISR;
|
uint32_t isr = I2CD1.i2c->ISR;
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
i2c_lld_serve_interrupt(&I2CD1, status);
|
/* Clearing IRQ bits.*/
|
||||||
|
I2CD1.i2c->ICR = isr & I2C_INT_MASK;
|
||||||
|
|
||||||
|
i2c_lld_serve_interrupt(&I2CD1, isr);
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
CH_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
|
CH_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
|
||||||
uint32_t status = I2CD1.i2c->ISR;
|
uint32_t isr = I2CD1.i2c->ISR;
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
i2c_lld_serve_error_interrupt(&I2CD1, status);
|
/* Clearing IRQ bits.*/
|
||||||
|
I2CD1.i2c->ICR = isr & I2C_ERROR_MASK;
|
||||||
|
|
||||||
|
i2c_lld_serve_error_interrupt(&I2CD1, isr);
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
@ -333,35 +330,44 @@ CH_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
CH_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) {
|
CH_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) {
|
||||||
uint32_t status = I2CD2.i2c->ISR;
|
uint32_t isr = I2CD2.i2c->ISR;
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
if (status & I2C_ERROR_MASK)
|
/* Clearing IRQ bits.*/
|
||||||
i2c_lld_serve_error_interrupt(&I2CD2, status);
|
I2CD2.i2c->ICR = isr;
|
||||||
else if (status & I2C_INT_MASK)
|
|
||||||
i2c_lld_serve_interrupt(&I2CD2, status);
|
if (isr & I2C_ERROR_MASK)
|
||||||
|
i2c_lld_serve_error_interrupt(&I2CD2, isr);
|
||||||
|
else if (isr & I2C_INT_MASK)
|
||||||
|
i2c_lld_serve_interrupt(&I2CD2, isr);
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER)
|
#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER)
|
||||||
CH_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
|
CH_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
|
||||||
uint32_t status = I2CD2.i2c->ISR;
|
uint32_t isr = I2CD2.i2c->ISR;
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
i2c_lld_serve_interrupt(&I2CD2, status);
|
/* Clearing IRQ bits.*/
|
||||||
|
I2CD2.i2c->ICR = isr & I2C_INT_MASK;
|
||||||
|
|
||||||
|
i2c_lld_serve_interrupt(&I2CD2, isr);
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
CH_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
|
CH_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
|
||||||
uint32_t status = I2CD2.i2c->ISR;
|
uint32_t isr = I2CD2.i2c->ISR;
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
i2c_lld_serve_error_interrupt(&I2CD2, status);
|
/* Clearing IRQ bits.*/
|
||||||
|
I2CD2.i2c->ICR = isr & I2C_ERROR_MASK;
|
||||||
|
|
||||||
|
i2c_lld_serve_error_interrupt(&I2CD2, isr);
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
@ -497,8 +503,8 @@ void i2c_lld_start(I2CDriver *i2cp) {
|
||||||
dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR);
|
dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR);
|
||||||
|
|
||||||
/* Reset i2c peripheral.*/
|
/* Reset i2c peripheral.*/
|
||||||
dp->CR1 = i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_TCIE |
|
dp->CR1 = i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE |
|
||||||
I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN;
|
I2C_CR1_TCIE | I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN;
|
||||||
|
|
||||||
/* Set slave address field (master mode) */
|
/* Set slave address field (master mode) */
|
||||||
dp->CR2 = (i2cp->config->cr2 & ~I2C_CR2_SADD);
|
dp->CR2 = (i2cp->config->cr2 & ~I2C_CR2_SADD);
|
||||||
|
@ -591,6 +597,9 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||||
|
|
||||||
chDbgCheck((rxbytes > 1), "i2c_lld_master_receive_timeout");
|
chDbgCheck((rxbytes > 1), "i2c_lld_master_receive_timeout");
|
||||||
|
|
||||||
|
/* Resetting error flags for this transfer.*/
|
||||||
|
i2cp->errors = I2CD_NO_ERROR;
|
||||||
|
|
||||||
/* Global timeout for the whole operation.*/
|
/* Global timeout for the whole operation.*/
|
||||||
if (timeout != TIME_INFINITE)
|
if (timeout != TIME_INFINITE)
|
||||||
chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
|
chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
|
||||||
|
@ -682,6 +691,9 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||||
chDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))),
|
chDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))),
|
||||||
"i2c_lld_master_transmit_timeout");
|
"i2c_lld_master_transmit_timeout");
|
||||||
|
|
||||||
|
/* Resetting error flags for this transfer.*/
|
||||||
|
i2cp->errors = I2CD_NO_ERROR;
|
||||||
|
|
||||||
/* Global timeout for the whole operation.*/
|
/* Global timeout for the whole operation.*/
|
||||||
if (timeout != TIME_INFINITE)
|
if (timeout != TIME_INFINITE)
|
||||||
chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
|
chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* The timings are critical, please always refer to the STM32 Reference
|
* The timings are critical, please always refer to the STM32 Reference
|
||||||
* Manual before attempting changes.
|
* Manual before attempting changes.
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
static const I2CConfig i2cconfig = {
|
static const I2CConfig i2cconfig = {
|
||||||
STM32_TIMINGR_PRESC(8U) | /* 72MHz/9 = 8MHz I2CCLK. */
|
STM32_TIMINGR_PRESC(8U) | /* 72MHz/9 = 8MHz I2CCLK. */
|
||||||
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
|
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
|
||||||
|
@ -30,6 +31,14 @@ static const I2CConfig i2cconfig = {
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
static const I2CConfig i2cconfig = {
|
||||||
|
STM32_TIMINGR_PRESC(15U) |
|
||||||
|
STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) |
|
||||||
|
STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U),
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a periodic thread that does absolutely nothing except flashing
|
* This is a periodic thread that does absolutely nothing except flashing
|
||||||
|
@ -78,6 +87,23 @@ int main(void) {
|
||||||
* Normal main() thread activity, in this demo it does nothing.
|
* Normal main() thread activity, in this demo it does nothing.
|
||||||
*/
|
*/
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
unsigned i;
|
||||||
|
msg_t msg;
|
||||||
|
static const uint8_t cmd[] = {0, 0};
|
||||||
|
uint8_t data[16];
|
||||||
|
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
msg = i2cMasterTransmitTimeout(&I2CD2, 0x52, cmd, sizeof(cmd),
|
||||||
|
data, sizeof(data), TIME_INFINITE);
|
||||||
|
if (msg != RDY_OK)
|
||||||
|
chSysHalt();
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
chThdSleepMilliseconds(10);
|
||||||
|
msg = i2cMasterReceiveTimeout(&I2CD2, 0x52,
|
||||||
|
data, sizeof(data), TIME_INFINITE);
|
||||||
|
if (msg != RDY_OK)
|
||||||
|
chSysHalt();
|
||||||
|
}
|
||||||
chThdSleepMilliseconds(500);
|
chThdSleepMilliseconds(500);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue