Giovanni wrote:On F1 (GPIOv1) there are no alternate numbers, just alternate or not.
The driver is very old and proved to work, probably the problem is not where you are looking, I would bet on some HW issue (because bus locked).
Giovanni
I modified the following code
Code: Select all
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) {
I2C_TypeDef *dp = i2cp->i2c;
systime_t start, end;
#if defined(STM32F1XX_I2C)
osalDbgCheck((rxbytes == 0) || ((rxbytes > 0) && (rxbuf != NULL)));
#endif
/* Resetting error flags for this transfer.*/
i2cp->errors = I2C_NO_ERROR;
/* Initializes driver fields, LSB = 0 -> transmit.*/
i2cp->addr = (addr << 1);
Code: Select all
msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) {
thread_t *tp = chThdGetSelfX();
chDbgAssert(*trp != NULL, "not NULL");
if (TIME_IMMEDIATE == timeout) {
return MSG_TIMEOUT;
}
*trp = tp;
tp->p_u.wttrp = trp;
return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout);
}
The test found that the thread will block in "osalThreadSuspendTimeoutS".
The following is my relevant code to use I2C.
Code: Select all
I2C.thread = chThdGetSelfX();
i2cMasterTransmitTimeout(&I2C,
HAL_COMPASS_IST8310_I2C_ADDR,
tx_buf.data(),
tx_buf.size(),
rx_buf.data(),
rx_buf.size(),
US2ST(2000)));
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) {
I2C_TypeDef *dp = i2cp->i2c;
systime_t start, end;
#if defined(STM32F1XX_I2C)
osalDbgCheck((rxbytes == 0) || ((rxbytes > 0) && (rxbuf != NULL)));
#endif
/* Resetting error flags for this transfer.*/
i2cp->errors = I2C_NO_ERROR;
/* Initializes driver fields, LSB = 0 -> transmit.*/
i2cp->addr = (addr << 1);
/* Releases the lock from high level driver.*/
osalSysUnlock();
/* TX DMA setup.*/
dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
dmaStreamSetMemory0(i2cp->dmatx, txbuf);
dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
/* RX DMA setup.*/
dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
/* Calculating the time window for the timeout on the busy bus condition.*/
start = osalOsGetSystemTimeX();
end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT);
/* Waits until BUSY flag is reset or, alternatively, for a timeout
condition.*/
while (true) {
osalSysLock();
/* If the bus is not busy then the operation can continue, note, the
loop is exited in the locked state.*/
if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP))
break;
/* If the system time went outside the allowed window then a timeout
condition is returned.*/
//if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end))
if (ST2MS(osalOsGetSystemTimeX()-start) > STM32_I2C_BUSY_TIMEOUT)
return MSG_TIMEOUT;
osalSysUnlock();
}
/* Starts the operation.*/
dp->CR2 |= I2C_CR2_ITEVTEN;
dp->CR1 |= I2C_CR1_START;
/* Waits for the operation completion or a timeout.*/
return osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
//return 0;
}
static inline msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp,
systime_t timeout) {
return chThdSuspendTimeoutS(trp, timeout);
}
msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) {
thread_t *tp = chThdGetSelfX();
chDbgAssert(*trp != NULL, "not NULL");
if (TIME_IMMEDIATE == timeout) {
return MSG_TIMEOUT;
}
*trp = tp;
tp->p_u.wttrp = trp;
return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout);
}
According to the parameter "US2ST(2000)" that I passed in, the program should not block. It feels like "chThdSuspendTimeoutS" hangs the program.