mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-03-13 10:03:57 -03:00
HAL_ChibiOS: added checking of bus owner
this ensures all bus transfers are only done by the thread that owns the semaphore
This commit is contained in:
parent
2ffb8d1583
commit
f1ce321a2f
@ -126,6 +126,11 @@ void I2CBus::dma_deallocate(void)
|
||||
bool I2CDevice::transfer(const uint8_t *send, uint32_t send_len,
|
||||
uint8_t *recv, uint32_t recv_len)
|
||||
{
|
||||
if (!bus.semaphore.check_owner()) {
|
||||
hal.console->printf("ERR: I2C transfer by non-owner\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bus.dma_handle->lock();
|
||||
|
||||
if (_use_smbus) {
|
||||
@ -172,41 +177,39 @@ bool I2CDevice::_transfer(const uint8_t *send, uint32_t send_len,
|
||||
|
||||
bus.bouncebuffer_setup(send_buf, send_len, recv_buf, recv_len);
|
||||
|
||||
i2cAcquireBus(I2CD[bus.busnum].i2c);
|
||||
|
||||
for(uint8_t i=0 ; i <= _retries; i++) {
|
||||
int ret;
|
||||
i2cAcquireBus(I2CD[bus.busnum].i2c);
|
||||
// calculate a timeout as twice the expected transfer time, and set as min of 4ms
|
||||
uint32_t timeout_ms = 1+2*(((8*1000000UL/bus.i2ccfg.clock_speed)*MAX(send_len, recv_len))/1000);
|
||||
timeout_ms = MAX(timeout_ms, _timeout_ms);
|
||||
bus.i2c_active = true;
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_READY, "i2cStart state");
|
||||
if(send_len == 0) {
|
||||
ret = i2cMasterReceiveTimeout(I2CD[bus.busnum].i2c, _address, recv_buf, recv_len, MS2ST(timeout_ms));
|
||||
} else {
|
||||
ret = i2cMasterTransmitTimeout(I2CD[bus.busnum].i2c, _address, send_buf, send_len,
|
||||
recv_buf, recv_len, MS2ST(timeout_ms));
|
||||
}
|
||||
i2cReleaseBus(I2CD[bus.busnum].i2c);
|
||||
bus.i2c_active = false;
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_READY, "i2cStart state");
|
||||
if (ret != MSG_OK){
|
||||
if (ret != MSG_OK) {
|
||||
//restart the bus
|
||||
if (bus.i2c_started) {
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_READY, "i2cStart state");
|
||||
i2cStop(I2CD[bus.busnum].i2c);
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_STOP, "i2cStart state");
|
||||
bus.i2c_started = false;
|
||||
}
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_READY || I2CD[bus.busnum].i2c->state == I2C_LOCKED, "i2cStart state");
|
||||
i2cStop(I2CD[bus.busnum].i2c);
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_STOP, "i2cStart state");
|
||||
i2cStart(I2CD[bus.busnum].i2c, &bus.i2ccfg);
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_READY, "i2cStart state");
|
||||
bus.i2c_started = true;
|
||||
} else {
|
||||
osalDbgAssert(I2CD[bus.busnum].i2c->state == I2C_READY, "i2cStart state");
|
||||
if (recv_buf != recv) {
|
||||
memcpy(recv, recv_buf, recv_len);
|
||||
}
|
||||
i2cReleaseBus(I2CD[bus.busnum].i2c);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i2cReleaseBus(I2CD[bus.busnum].i2c);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -196,6 +196,7 @@ uint16_t SPIDevice::derive_freq_flag(uint32_t _frequency)
|
||||
bool SPIDevice::transfer(const uint8_t *send, uint32_t send_len,
|
||||
uint8_t *recv, uint32_t recv_len)
|
||||
{
|
||||
bus.semaphore.assert_owner();
|
||||
if (send_len == recv_len && send == recv) {
|
||||
// simplest cases, needed for DMA
|
||||
do_transfer(send, recv, recv_len);
|
||||
@ -217,6 +218,7 @@ bool SPIDevice::transfer(const uint8_t *send, uint32_t send_len,
|
||||
|
||||
bool SPIDevice::transfer_fullduplex(const uint8_t *send, uint8_t *recv, uint32_t len)
|
||||
{
|
||||
bus.semaphore.assert_owner();
|
||||
uint8_t buf[len];
|
||||
memcpy(buf, send, len);
|
||||
do_transfer(buf, buf, len);
|
||||
@ -245,6 +247,7 @@ bool SPIDevice::adjust_periodic_callback(AP_HAL::Device::PeriodicHandle h, uint3
|
||||
*/
|
||||
bool SPIDevice::set_chip_select(bool set)
|
||||
{
|
||||
bus.semaphore.assert_owner();
|
||||
if (set && cs_forced) {
|
||||
return true;
|
||||
}
|
||||
|
@ -29,6 +29,12 @@ public:
|
||||
bool give();
|
||||
bool take(uint32_t timeout_ms);
|
||||
bool take_nonblocking();
|
||||
bool check_owner(void) {
|
||||
return _lock.owner == chThdGetSelfX();
|
||||
}
|
||||
void assert_owner(void) {
|
||||
osalDbgAssert(check_owner(), "owner");
|
||||
}
|
||||
private:
|
||||
mutex_t _lock;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user