void dma_stream_reset(u32 dma, u8 stream) { /* Disable stream (must be done before register is otherwise changed). */ DMA_SCR(dma, stream) &= ~DMA_SxCR_EN; /* Reset all config bits. */ DMA_SCR(dma, stream) = 0; /* Reset data transfer number. */ DMA_SNDTR(dma, stream) = 0; /* Reset peripheral and memory addresses. */ DMA_SPAR(dma, stream) = 0; DMA_SM0AR(dma, stream) = 0; DMA_SM1AR(dma, stream) = 0; /* This is the default setting */ DMA_SFCR(dma, stream) = 0x21; /* Reset all stream interrupt flags using the interrupt flag clear register. */ u32 mask = DMA_ISR_MASK(stream); if (stream < 4) { DMA_LIFCR(dma) |= mask; } else { DMA_HIFCR(dma) |= mask; } }
/** Setup the USART for transmission with DMA. * This function sets up the DMA controller and additional USART parameters for * DMA transmit. The USART must already be configured for normal operation. * * \param s The USART DMA state structure. * \oaram usart The USART base address. * \param dma The DMA controller base address. * \param stream The DMA stream number to use. * \param channel The DMA channel to use. The stream and channel must * correspond to a USART RX channel. */ void usart_tx_dma_setup(usart_tx_dma_state* s, u32 usart, u32 dma, u8 stream, u8 channel) { s->dma = dma; s->usart = usart; s->stream = stream; s->channel = channel; s->byte_counter = 0; s->last_byte_ticks = chTimeNow(); /* Enable clock to DMA peripheral. */ if (dma == DMA1) RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN; else if (dma == DMA2) RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN; /* Enable TX DMA on the USART. */ usart_enable_tx_dma(usart); /* Make sure stream is disabled to start. */ DMA_SCR(dma, stream) &= ~DMA_SxCR_EN; /* Configure the DMA controller. */ DMA_SCR(dma, stream) = 0; DMA_SCR(dma, stream) = /* Error interrupts. */ DMA_SxCR_DMEIE | DMA_SxCR_TEIE | /* Transfer complete interrupt. */ DMA_SxCR_TCIE | DMA_SxCR_DIR_MEM_TO_PERIPHERAL | /* Increment the memory address after each transfer. */ DMA_SxCR_MINC | /* 4 bytes written to the FIFO from memory at a time */ DMA_SxCR_MBURST_INCR4 | /* 8 bit transfers from USART peripheral. */ DMA_SxCR_PSIZE_8BIT | /* and to memory. */ DMA_SxCR_MSIZE_8BIT | /* TODO: what priority level is necessary? */ /* Very high priority. */ DMA_SxCR_PL_VERY_HIGH | /* The channel selects which request line will trigger a transfer. * (see CD00225773.pdf Table 23). */ DMA_SxCR_CHSEL(channel); /* For now, don't transfer any number of datas * (will be set in the initiating function). */ DMA_SNDTR(dma, stream) = 0; /* DMA into the USART data register... */ DMA_SPAR(dma, stream) = &USART_DR(usart); /* ...from the TX buffer. */ DMA_SM0AR(dma, stream) = s->buff; /* TODO: Investigate more about the best FIFO settings. */ DMA_SFCR(dma, stream) = DMA_SxFCR_DMDIS | /* Enable DMA stream FIFO. */ DMA_SxFCR_FTH_2_4_FULL | /* Trigger level 2/4 full. */ DMA_SxFCR_FEIE; /* Enable FIFO error interrupt. */ s->wr = s->rd = 0; /* Buffer is empty to begin with. */ /* Enable DMA interrupts for this stream with the NVIC. */ if (dma == DMA1) nvicEnableVector(dma_irq_lookup[0][stream], CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY)); else if (dma == DMA2) nvicEnableVector(dma_irq_lookup[1][stream], CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY)); }
void dma_set_fifo_threshold(u32 dma, u8 stream, u32 threshold) { u32 reg32 = (DMA_SFCR(dma, stream) & ~DMA_SxFCR_FTH_MASK); DMA_SFCR(dma, stream) = (reg32 | threshold); }
void dma_enable_fifo_mode(u32 dma, u8 stream) { DMA_SFCR(dma, stream) |= DMA_SxFCR_DMDIS; }
void dma_enable_direct_mode(u32 dma, u8 stream) { DMA_SFCR(dma, stream) &= ~DMA_SxFCR_DMDIS; }
u32 dma_fifo_status(u32 dma, u8 stream) { return (DMA_SFCR(dma, stream) & DMA_SxFCR_FS_MASK); }
void dma_disable_fifo_error_interrupt(u32 dma, u8 stream) { DMA_SFCR(dma, stream) &= ~DMA_SxFCR_FEIE; }
void dma_enable_fifo_error_interrupt(u32 dma, u8 stream) { dma_clear_interrupt_flags(dma, stream, DMA_ISR_FEIF); DMA_SFCR(dma, stream) |= DMA_SxFCR_FEIE; }