Eliminate the TD DMA callback; we don't need to know that it's completed.

Fix abort behaviour on timeouts, now we don't wedge after the first one.
This commit is contained in:
px4dev
2013-07-05 17:39:28 -07:00
parent 50cae347b4
commit 6c5a15da9b
+18 -57
View File
@@ -140,7 +140,6 @@ private:
/** saved DMA status */
static const unsigned _dma_status_inactive = 0x80000000; // low bits overlap DMA_STATUS_* values
static const unsigned _dma_status_waiting = 0x00000000;
volatile unsigned _tx_dma_status;
volatile unsigned _rx_dma_status;
/** bus-ownership lock */
@@ -151,16 +150,13 @@ private:
/**
* Start the transaction with IO and wait for it to complete.
*
* @param expect_reply If true, expect a reply from IO.
*/
int _wait_complete(bool expect_reply, unsigned tx_length);
int _wait_complete();
/**
* DMA completion handler.
*/
static void _dma_callback(DMA_HANDLE handle, uint8_t status, void *arg);
void _do_tx_dma_callback(unsigned status);
void _do_rx_dma_callback(unsigned status);
/**
@@ -197,7 +193,6 @@ PX4IO_serial::PX4IO_serial() :
_tx_dma(nullptr),
_rx_dma(nullptr),
_rx_length(0),
_tx_dma_status(_dma_status_inactive),
_rx_dma_status(_dma_status_inactive),
_perf_dmasetup(perf_alloc(PC_ELAPSED, "dmasetup")),
_perf_timeouts(perf_alloc(PC_COUNT, "timeouts")),
@@ -314,8 +309,9 @@ PX4IO_serial::test(unsigned mode)
for (unsigned count = 0;; count++) {
uint16_t value = count & 0xffff;
if (set_reg(PX4IO_PAGE_TEST, PX4IO_P_TEST_LED, &value, 1) != OK)
return -2;
set_reg(PX4IO_PAGE_TEST, PX4IO_P_TEST_LED, &value, 1);
/* ignore errors */
if (count > 100) {
perf_print_counter(_perf_dmasetup);
perf_print_counter(_perf_txns);
@@ -353,7 +349,7 @@ PX4IO_serial::set_reg(uint8_t page, uint8_t offset, const uint16_t *values, unsi
/* XXX implement check byte */
/* start the transaction and wait for it to complete */
int result = _wait_complete(false, PKT_SIZE(_dma_buffer));
int result = _wait_complete();
sem_post(&_bus_semaphore);
return result;
@@ -372,13 +368,14 @@ PX4IO_serial::get_reg(uint8_t page, uint8_t offset, uint16_t *values, unsigned n
_dma_buffer.offset = offset;
/* start the transaction and wait for it to complete */
int result = _wait_complete(true, PKT_SIZE(_dma_buffer));
int result = _wait_complete();
if (result != OK)
goto out;
/* compare the received count with the expected count */
if (PKT_COUNT(_dma_buffer) != num_values) {
return -EIO;
result = -EIO;
goto out;
} else {
/* XXX implement check byte */
/* copy back the result */
@@ -386,13 +383,12 @@ PX4IO_serial::get_reg(uint8_t page, uint8_t offset, uint16_t *values, unsigned n
}
out:
sem_post(&_bus_semaphore);
return OK;
return result;
}
int
PX4IO_serial::_wait_complete(bool expect_reply, unsigned tx_length)
PX4IO_serial::_wait_complete()
{
/* clear any lingering error status */
(void)rSR;
(void)rDR;
@@ -418,12 +414,10 @@ PX4IO_serial::_wait_complete(bool expect_reply, unsigned tx_length)
stm32_dmastart(_rx_dma, _dma_callback, this, false);
rCR3 |= USART_CR3_DMAR;
/* start TX DMA - no callback if we also expect a reply */
/* DMA setup time ~3µs */
_dma_buffer.crc = 0;
_dma_buffer.crc = crc_packet(_dma_buffer);
_tx_dma_status = _dma_status_waiting;
stm32_dmasetup(
_tx_dma,
PX4IO_SERIAL_BASE + STM32_USART_DR_OFFSET,
@@ -435,7 +429,7 @@ PX4IO_serial::_wait_complete(bool expect_reply, unsigned tx_length)
DMA_SCR_MSIZE_8BITS |
DMA_SCR_PBURST_SINGLE |
DMA_SCR_MBURST_SINGLE);
stm32_dmastart(_tx_dma, /*expect_reply ? nullptr :*/ _dma_callback, this, false);
stm32_dmastart(_tx_dma, nullptr, nullptr, false);
rCR3 |= USART_CR3_DMAT;
perf_end(_perf_dmasetup);
@@ -460,11 +454,6 @@ PX4IO_serial::_wait_complete(bool expect_reply, unsigned tx_length)
if (ret == OK) {
/* check for DMA errors */
if (_tx_dma_status & DMA_STATUS_TEIF) {
lowsyslog("DMA transmit error\n");
ret = -1;
break;
}
if (_rx_dma_status & DMA_STATUS_TEIF) {
lowsyslog("DMA receive error\n");
ret = -1;
@@ -490,7 +479,6 @@ PX4IO_serial::_wait_complete(bool expect_reply, unsigned tx_length)
}
/* reset DMA status */
_tx_dma_status = _dma_status_inactive;
_rx_dma_status = _dma_status_inactive;
/* update counters */
@@ -507,37 +495,13 @@ PX4IO_serial::_dma_callback(DMA_HANDLE handle, uint8_t status, void *arg)
if (arg != nullptr) {
PX4IO_serial *ps = reinterpret_cast<PX4IO_serial *>(arg);
if (handle == ps->_tx_dma) {
ps->_do_tx_dma_callback(status);
} else if (handle == ps->_rx_dma) {
ps->_do_rx_dma_callback(status);
}
}
}
void
PX4IO_serial::_do_tx_dma_callback(unsigned status)
{
/* on completion of a no-reply transmit, wake the sender */
if (_tx_dma_status == _dma_status_waiting) {
/* save TX status */
_tx_dma_status = status;
/* disable UART DMA */
rCR3 &= ~USART_CR3_DMAT;
/* if we aren't going on to expect a reply, complete now */
if (_rx_dma_status != _dma_status_waiting)
sem_post(&_completion_semaphore);
ps->_do_rx_dma_callback(status);
}
}
void
PX4IO_serial::_do_rx_dma_callback(unsigned status)
{
ASSERT(_tx_dma_status != _dma_status_waiting);
/* on completion of a reply, wake the waiter */
if (_rx_dma_status == _dma_status_waiting) {
@@ -552,7 +516,7 @@ PX4IO_serial::_do_rx_dma_callback(unsigned status)
_rx_dma_status = status;
/* disable UART DMA */
rCR3 &= ~USART_CR3_DMAR;
rCR3 &= ~(USART_CR3_DMAT | USART_CR3_DMAR);
/* DMA may have stopped short */
_rx_length = sizeof(IOPacket) - stm32_dmaresidual(_rx_dma);
@@ -593,6 +557,10 @@ PX4IO_serial::_do_interrupt()
*/
if (_rx_dma_status == _dma_status_waiting) {
_abort_dma();
/* complete DMA as though in error */
_do_rx_dma_callback(DMA_STATUS_TEIF);
return;
}
@@ -605,7 +573,7 @@ PX4IO_serial::_do_interrupt()
if (sr & USART_SR_IDLE) {
/* if there was DMA transmission still going, this is an error */
if (_tx_dma_status == _dma_status_waiting) {
if (stm32_dmaresidual(_tx_dma) != 0) {
/* babble from IO */
_abort_dma();
@@ -636,13 +604,6 @@ PX4IO_serial::_abort_dma()
/* stop DMA */
stm32_dmastop(_tx_dma);
stm32_dmastop(_rx_dma);
/* complete DMA as though in error */
_do_tx_dma_callback(DMA_STATUS_TEIF);
_do_rx_dma_callback(DMA_STATUS_TEIF);
_tx_dma_status = _dma_status_inactive;
_rx_dma_status = _dma_status_inactive;
}
static const uint8_t crc8_tab[256] =