I'm trying to implement USART transfer over DMA (XMDAC) on the SamV71 Xplained board, the simplest way possible (no need for ring buffer or anything fancy, only one transfer at once).
I'm using XDMAC and USART ASF drivers, and while I follow all the steps specified in the datasheet for a single block/single microblock transfer, it seems the XDMAC transfer is not initiated. I know the USART is initialised successfully because it works if I'm not using DMA.
Here's the code that inits the DMA and initiates the transfer by enabling the TX channel. Any doc on XDMAC except for the chapter in the SAMx70 datasheet? It seems it's missing quite a bit of details that I had to find in the various examples.
For info, buffer length is 32 bytes and the buffer is aligned on a 32 bit boundary.
Code: Select all
#define MY_USART USART1 #define MY_USART_ID ID_USART1 #define MY_USART_RX_XDMAC_HWID XDAMC_CHANNEL_HWID_UART1_TX #define MY_USART_TX_XDMAC_HWID XDAMC_CHANNEL_HWID_UART1_TX #define MY_DMA_TX_CHANNEL 0 #define MY_DMA_RX_CHANNEL 1 ///// the init part static xdmac_channel_config_t xdmac_tx_channel_cfg; xdmac_tx_channel_cfg.mbr_sa = 0; xdmac_tx_channel_cfg.mbr_da = (uint32_t)&MY_USART->US_THR; xdmac_tx_channel_cfg.mbr_ubc = 0; xdmac_tx_channel_cfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | XDMAC_CC_MBSIZE_SINGLE | XDMAC_CC_DSYNC_MEM2PER | XDMAC_CC_PROT_SEC | XDMAC_CC_SWREQ_HWR_CONNECTED | XDMAC_CC_MEMSET_NORMAL_MODE | XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_BYTE | XDMAC_CC_SIF_AHB_IF0 | XDMAC_CC_DIF_AHB_IF1 | XDMAC_CC_SAM_INCREMENTED_AM | XDMAC_CC_DAM_FIXED_AM | XDMAC_CC_PERID(MY_USART_TX_XDMAC_HWID); xdmac_tx_channel_cfg.mbr_bc = 0; xdmac_tx_channel_cfg.mbr_ds = 0; xdmac_tx_channel_cfg.mbr_sus = 0; xdmac_tx_channel_cfg.mbr_dus = 0; xdmac_configure_transfer(XDMAC, MY_DMA_TX_CHANNEL, &xdmac_tx_channel_cfg); // NDC xdmac_channel_set_descriptor_control(XDMAC, MY_DMA_TX_CHANNEL, 0); // Enable End Of Block interrupt for channel xdmac_channel_enable_interrupt(XDMAC, MY_DMA_TX_CHANNEL, XDMAC_CIE_BIE); // Enable Global Interrupts for channel xdmac_enable_interrupt(XDMAC, MY_DMA_TX_CHANNEL); ///// the sending part xdmac_channel_set_source_addr(XDMAC, MY_DMA_TX_CHANNEL, (uint32_t)buffer); // set length xdmac_channel_set_microblock_control(XDMAC, MY_DMA_TX_CHANNEL, length); // enable channel barrier(); xdmac_channel_enable(XDMAC,MY_DMA_TX_CHANNEL);
Thanks a lot for your help!