diff --git a/srv/dma_mbuf.c b/srv/dma_mbuf.c index 1ceaad0..4f2255c 100644 --- a/srv/dma_mbuf.c +++ b/srv/dma_mbuf.c @@ -12,9 +12,12 @@ //--local definitions----------------------------------------------------------- +/** + * DMA configuration to be used for the buffer. Additionnal configuration may be + * added by the peripherals used + */ #define DMA_CONFIG (DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_MEM \ - | DMA_CONFIG_INC_MEM | DMA_CONFIG_PSIZE_8BITS \ - | DMA_CONFIG_MSIZE_8BITS) + | DMA_CONFIG_INC_MEM | DMA_CONFIG_MSIZE_8BITS) static void mbuf_callback(enum DmaIRQSource src, volatile void* param); @@ -60,12 +63,16 @@ uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer, return 0; } -void dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer) +uint32_t dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer) { - //if transfer already in progress or no data to send, don't start the - //transfer - if (buffer->dma_running || buffer->byte_index == 0) { - return; + //no data to send, stop here + if (buffer->byte_index == 0) { + return 0; + } + + //dma already running, give up + if (buffer->dma_running) { + return 1; } //start a new transfer @@ -80,15 +87,15 @@ void dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer) buffer->buffer_index = 0; } - return; + return 0; } //--local functions------------------------------------------------------------- /** - * Callback called on DMA TX tranfert's completion. Checks for any remaining - * data to send. If any, starts a new transfer, else stop the DMA + * Callback called on DMA TX tranfert's completion. Stops the DMA and notifies + * the buffer that the transfer is done. */ static void mbuf_callback(enum DmaIRQSource src, volatile void* param) { diff --git a/srv/dma_mbuf.h b/srv/dma_mbuf.h index cf44d0d..b5f930c 100644 --- a/srv/dma_mbuf.h +++ b/srv/dma_mbuf.h @@ -2,7 +2,7 @@ * Module handling Direct Memory Access controller's multibuffer system * * The module provides a convenient tool to send data to a peripheral in a - * buffered, low-altency, low-cpu usage, non-blocking way + * buffered, low-latency, low-cpu usage, non-blocking way */ #ifndef _DMA_MBUF_H_ @@ -17,36 +17,38 @@ /** * Struct used by the multibuffer system. This system allows bufferized writes - * to a peripheral with no latency, minimal cpu usage and customisable buffer - * sizes + * to a peripheral with controlled latency, minimal cpu usage and customisable + * buffer size */ struct DmaMultiBuffer { - uint8_t* raw_buffer; + uint8_t* raw_buffer; //the buffer to use as a multi-buffer - uint16_t buffer_size; + uint16_t buffer_size; //the size of the buffer - uint8_t byte_index; - uint8_t buffer_index; - enum DmaPeriph dma; - enum DmaChannel channel; + uint8_t byte_index; //index of the next byte to be written + uint8_t buffer_index; //index of the buffer being written to + enum DmaPeriph dma; //DMA peripheral used for transfers + enum DmaChannel channel; //DMA channel used for transfers - bool dma_running; + bool dma_running; //whether the dam is currently running or not }; //--functions------------------------------------------------------------------- /** - * Configure a DMA multibuffer for a single DMA channel. A list of buffers is - * used to allow concurent write and DMA tranfers to the specified destination - * wich must be a peripheral. The DMA's priority is also given as parameters. - * The peripheral's specific configuration must be handled separately. 2 bytes - * are reserved in each buffer for index storage. + * Configure a DMA multibuffer for a single DMA channel. The given buffer is + * divided into 2 to allow one part to be written to while the other is being + * transfered by the DMA to a peripheral. + * The peripheral's specific configuration must be handled separately. + * Each peripheral's driver is responsible for providing the DMA configuration + * for said peripheral, though it can be manually given too. Please note that + * multiple peripherals may share the same DMA channel, which will cause issue + * when used with this buffer. * - * This system needs to be started manually: dma_mbuf_refresh() should be called - * whenever a DMA transfer can be started. This can be done manually after - * filling up the buffer. Transfers will then automatically be started as long - * as there are bytes in the buffer. See the usart module for an usage exemple + * This buffer can be written to at any given time using dma_mbuf_write_byte(), + * but its content are only written to the corresponding peripheral when + * dma_mbuf_switch() is called. */ void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer, const struct DmaParam* param, enum DmaConfig priority, @@ -57,18 +59,17 @@ void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer, * was successfull, 1 otherwise. The function is non-blocking. * * Note: calling this function will not trigger a DMA transfer, see - * dma_mbuf_refresh() to do that + * dma_mbuf_switch() to do that */ uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer, uint8_t byte); /** - * Refresh the buffer state, checking for bytes to send and triggering a DMA - * transfer if necessary. Should be called for the first transfer, any remaining - * transfer will be handled automatically until there are no bytes left in the - * buffer + * Switch the buffers, triggering a DMA transfer while allowing writes to + * continue. This function may fail if a DMA transfer is already running, + * returning 1 */ -void dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer); +uint32_t dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer); #endif //_DMA_MBUF_H_