From: Keith Packard Date: Sun, 6 Nov 2022 23:31:50 +0000 (-0800) Subject: samd21: Macro-ize the DMA register settings a bit X-Git-Tag: 1.9.13~1^2~26^2~43 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=5d18ef0a25248f0192c3b539cad36d3de60a6f32 samd21: Macro-ize the DMA register settings a bit Signed-off-by: Keith Packard --- diff --git a/src/samd21/ao_spi_samd21.c b/src/samd21/ao_spi_samd21.c index cffec1b4..6e49884b 100644 --- a/src/samd21/ao_spi_samd21.c +++ b/src/samd21/ao_spi_samd21.c @@ -65,6 +65,89 @@ _ao_spi_recv_dma_done(uint8_t dma_id, void *closure) } #endif +static inline uint32_t +dma_chctrlb(uint8_t id, bool tx) +{ + uint32_t chctrlb = 0; + + /* No complicated actions needed */ + chctrlb |= SAMD21_DMAC_CHCTRLB_CMD_NOACT << SAMD21_DMAC_CHCTRLB_CMD; + + /* Trigger after each byte transferred */ + chctrlb |= SAMD21_DMAC_CHCTRLB_TRIGACT_BEAT << SAMD21_DMAC_CHCTRLB_TRIGACT; + + /* Set the trigger source */ + if (tx) + chctrlb |= SAMD21_DMAC_CHCTRLB_TRIGSRC_SERCOM_TX(id) << SAMD21_DMAC_CHCTRLB_TRIGSRC; + else + chctrlb |= SAMD21_DMAC_CHCTRLB_TRIGSRC_SERCOM_RX(id) << SAMD21_DMAC_CHCTRLB_TRIGSRC; + + /* RX has priority over TX so that we don't drop incoming bytes */ + if (tx) + chctrlb |= SAMD21_DMAC_CHCTRLB_LVL_LVL0 << SAMD21_DMAC_CHCTRLB_LVL; + else + chctrlb |= SAMD21_DMAC_CHCTRLB_LVL_LVL3 << SAMD21_DMAC_CHCTRLB_LVL; + + /* No events needed */ + chctrlb |= 0UL << SAMD21_DMAC_CHCTRLB_EVOE; + chctrlb |= 0UL << SAMD21_DMAC_CHCTRLB_EVIE; + + /* And no actions either */ + chctrlb |= SAMD21_DMAC_CHCTRLB_EVACT_NOACT << SAMD21_DMAC_CHCTRLB_EVACT; + + return chctrlb; +} + +static inline uint16_t +dma_btctrl(bool tx, bool step) +{ + uint16_t btctrl = 0; + + /* Always step by 1 */ + btctrl |= SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X1 << SAMD21_DMAC_DESC_BTCTRL_STEPSIZE; + + /* Step the source if transmit, otherwise step the dest */ + if (tx) + btctrl |= SAMD21_DMAC_DESC_BTCTRL_STEPSEL_SRC << SAMD21_DMAC_DESC_BTCTRL_STEPSEL; + else + btctrl |= SAMD21_DMAC_DESC_BTCTRL_STEPSEL_DST << SAMD21_DMAC_DESC_BTCTRL_STEPSEL; + + /* Set the increment if stepping */ + if (tx) { + if (step) + btctrl |= 1UL << SAMD21_DMAC_DESC_BTCTRL_SRCINC; + else + btctrl |= 0UL << SAMD21_DMAC_DESC_BTCTRL_SRCINC; + btctrl |= 0UL << SAMD21_DMAC_DESC_BTCTRL_DSTINC; + } else { + btctrl |= 0UL << SAMD21_DMAC_DESC_BTCTRL_SRCINC; + if (step) + btctrl |= 1UL << SAMD21_DMAC_DESC_BTCTRL_DSTINC; + else + btctrl |= 0UL << SAMD21_DMAC_DESC_BTCTRL_DSTINC; + } + + /* byte at a time please */ + btctrl |= SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_BYTE << SAMD21_DMAC_DESC_BTCTRL_BEATSIZE; + + /* + * Watch for interrupts on RX -- we need to wait for the last byte to get received + * to know the SPI bus is idle + */ + if (tx) + btctrl |= SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_NOACT << SAMD21_DMAC_DESC_BTCTRL_BLOCKACT; + else + btctrl |= SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_INT << SAMD21_DMAC_DESC_BTCTRL_BLOCKACT; + + /* don't need any events */ + btctrl |= SAMD21_DMAC_DESC_BTCTRL_EVOSEL_DISABLE << SAMD21_DMAC_DESC_BTCTRL_EVOSEL; + + /* And make the descriptor valid */ + btctrl |= 1UL << SAMD21_DMAC_DESC_BTCTRL_VALID; + + return btctrl; +} + void ao_spi_send(const void *block, uint16_t len, uint8_t spi_index) { @@ -74,54 +157,24 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index) ao_arch_block_interrupts(); ao_spi_done[id] = 0; + _ao_dma_start_transfer(AO_SAMD21_SPI_MISO_DMA_ID, (void *) &sercom->data, &spi_dev_null, len, - - (SAMD21_DMAC_CHCTRLB_CMD_NOACT << SAMD21_DMAC_CHCTRLB_CMD) | - (SAMD21_DMAC_CHCTRLB_TRIGACT_BEAT << SAMD21_DMAC_CHCTRLB_TRIGACT) | - (SAMD21_DMAC_CHCTRLB_TRIGSRC_SERCOM_RX(id) << SAMD21_DMAC_CHCTRLB_TRIGSRC) | - (SAMD21_DMAC_CHCTRLB_LVL_LVL3 << SAMD21_DMAC_CHCTRLB_LVL) | - (0UL << SAMD21_DMAC_CHCTRLB_EVOE) | - (0UL << SAMD21_DMAC_CHCTRLB_EVIE) | - (SAMD21_DMAC_CHCTRLB_EVACT_NOACT << SAMD21_DMAC_CHCTRLB_EVACT), - - (SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X1 << SAMD21_DMAC_DESC_BTCTRL_STEPSIZE) | - (SAMD21_DMAC_DESC_BTCTRL_STEPSEL_DST << SAMD21_DMAC_DESC_BTCTRL_STEPSEL) | - (0UL << SAMD21_DMAC_DESC_BTCTRL_DSTINC) | - (0UL << SAMD21_DMAC_DESC_BTCTRL_SRCINC) | - (SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_BYTE << SAMD21_DMAC_DESC_BTCTRL_BEATSIZE) | - (SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_INT << SAMD21_DMAC_DESC_BTCTRL_BLOCKACT) | - (SAMD21_DMAC_DESC_BTCTRL_EVOSEL_DISABLE << SAMD21_DMAC_DESC_BTCTRL_EVOSEL) | - (1UL << SAMD21_DMAC_DESC_BTCTRL_VALID), + dma_chctrlb(id, false), + dma_btctrl(false, false), _ao_spi_recv_dma_done, (void *) (uintptr_t) id ); _ao_dma_start_transfer(AO_SAMD21_SPI_MOSI_DMA_ID, - (uint8_t *) block + len, + (uint8_t *) block + len, /* must point past the end of the block */ (void *) &sercom->data, len, - - (SAMD21_DMAC_CHCTRLB_CMD_NOACT << SAMD21_DMAC_CHCTRLB_CMD) | - (SAMD21_DMAC_CHCTRLB_TRIGACT_BEAT << SAMD21_DMAC_CHCTRLB_TRIGACT) | - (SAMD21_DMAC_CHCTRLB_TRIGSRC_SERCOM_TX(id) << SAMD21_DMAC_CHCTRLB_TRIGSRC) | - (SAMD21_DMAC_CHCTRLB_LVL_LVL2 << SAMD21_DMAC_CHCTRLB_LVL) | - (0UL << SAMD21_DMAC_CHCTRLB_EVOE) | - (0UL << SAMD21_DMAC_CHCTRLB_EVIE) | - (SAMD21_DMAC_CHCTRLB_EVACT_NOACT << SAMD21_DMAC_CHCTRLB_EVACT), - - (SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X1 << SAMD21_DMAC_DESC_BTCTRL_STEPSIZE) | - (SAMD21_DMAC_DESC_BTCTRL_STEPSEL_SRC << SAMD21_DMAC_DESC_BTCTRL_STEPSEL) | - (0UL << SAMD21_DMAC_DESC_BTCTRL_DSTINC) | - (1UL << SAMD21_DMAC_DESC_BTCTRL_SRCINC) | - (SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_BYTE << SAMD21_DMAC_DESC_BTCTRL_BEATSIZE) | - (SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_NOACT << SAMD21_DMAC_DESC_BTCTRL_BLOCKACT) | - (SAMD21_DMAC_DESC_BTCTRL_EVOSEL_DISABLE << SAMD21_DMAC_DESC_BTCTRL_EVOSEL) | - (1 << SAMD21_DMAC_DESC_BTCTRL_VALID), - + dma_chctrlb(id, true), + dma_btctrl(true, true), NULL, NULL );