altos/stm32f1: Grab both TX/RX DMA mutexes while doing I2C
[fw/altos] / src / stm32f1 / ao_i2c_stm.c
index e84f594bb19cc7a290de5e866dea00e8a82d653b..a61d3eb5f037c3c20c4324ebbd7321c485b128ca 100644 (file)
@@ -224,11 +224,11 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
 {
        struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
        uint8_t         tx_dma_index = ao_i2c_stm_info[index].tx_dma_index;
+       uint8_t         rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;
 
        /* Clear any pending ADDR bit */
        (void) stm_i2c->sr2;
        ao_i2c_wait_addr(index);
-       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN);
        ao_dma_set_transfer(tx_dma_index,
                            &stm_i2c->dr,
                            block,
@@ -241,13 +241,14 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
                            (0 << STM_DMA_CCR_PINC) |
                            (0 << STM_DMA_CCR_CIRC) |
                            (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
+       ao_dma_mutex_get(rx_dma_index);
+       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN);
 
        ao_dma_start(tx_dma_index);
        ao_arch_block_interrupts();
        while (!ao_dma_done[tx_dma_index])
                if (ao_sleep_for(&ao_dma_done[tx_dma_index], 1 + len))
                        break;
-       ao_dma_done_transfer(tx_dma_index);
        stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
        while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0)
                if (ao_sleep_for(&ao_i2c_state[index], 1 + len))
@@ -258,6 +259,8 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
                stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
                ao_i2c_wait_stop(index);
        }
+       ao_dma_mutex_put(rx_dma_index);
+       ao_dma_done_transfer(tx_dma_index);
        return true;
 }
 
@@ -311,7 +314,9 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
                ao_arch_release_interrupts();
                ret = ao_i2c_recv_len[index] == 0;
        } else {
+               uint8_t         tx_dma_index = ao_i2c_stm_info[index].tx_dma_index;
                uint8_t         rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;
+               ao_dma_mutex_get(tx_dma_index);
                ao_dma_set_transfer(rx_dma_index,
                                    &stm_i2c->dr,
                                    block,
@@ -349,8 +354,9 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
                                break;
                ao_arch_release_interrupts();
                ret = ao_dma_done[rx_dma_index];
-               ao_dma_done_transfer(rx_dma_index);
                stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
+               ao_dma_done_transfer(rx_dma_index);
+               ao_dma_mutex_put(tx_dma_index);
        }
        if (stop)
                ao_i2c_wait_stop(index);