Compare commits

..

No commits in common. "a1ae9042394f84f3c36c61db49b5556fac241d79" and "fd33003e26f23f6609d20d3371f2b618cddd7aab" have entirely different histories.

4 changed files with 39 additions and 59 deletions

View File

@ -12,13 +12,9 @@
//--local definitions----------------------------------------------------------- //--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_PERIPH \ #define DMA_CONFIG (DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_PERIPH \
| DMA_CONFIG_CIRCULAR | DMA_CONFIG_INC_MEM \ | DMA_CONFIG_CIRCULAR | DMA_CONFIG_INC_MEM \
| DMA_CONFIG_MSIZE_8BITS) | DMA_CONFIG_PSIZE_8BITS | DMA_CONFIG_MSIZE_8BITS)
static void cbuf_callback(enum DmaIRQSource src, volatile void* param); static void cbuf_callback(enum DmaIRQSource src, volatile void* param);

View File

@ -26,8 +26,8 @@ struct DmaCircBuffer {
uint16_t size; //the size of the buffer uint16_t size; //the size of the buffer
uint16_t begin; //pointer to the current begin of the buffer uint16_t begin; //pointer to the current begin of the buffer
enum DmaPeriph dma; //DMA peripheral used for transfers enum DmaPeriph dma;
enum DmaChannel channel; //DMA channel used for transfers enum DmaChannel channel;
bool dma_looped; //whether the DMA looped or not (buffer overflow) bool dma_looped; //whether the DMA looped or not (buffer overflow)
}; };
@ -38,12 +38,8 @@ struct DmaCircBuffer {
/** /**
* Configure a DMA circular buffer for a single DMA channel. A standard buffer * Configure a DMA circular buffer for a single DMA channel. A standard buffer
* is used a base to construct a circular buffer, supplied in data by DMA * is used a base to construct a circular buffer, supplied in data by DMA
* tranfers from a peripheral. * tranfers from a peripheral. The DMA's priority is given as parameters.
* The peripheral's specific configuration must be handled separately. * 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.
* *
* Once this function is called, the system will start running right away and * Once this function is called, the system will start running right away and
* will stay running until manually stopped * will stay running until manually stopped
@ -52,10 +48,6 @@ void dma_cbuf_configure(volatile struct DmaCircBuffer* buffer,
const struct DmaParam* param, enum DmaConfig priority, const struct DmaParam* param, enum DmaConfig priority,
volatile void* raw_buffer, uint16_t buffer_size); volatile void* raw_buffer, uint16_t buffer_size);
/**
* Reads a bytes from the buffer, returning if the read operation was
* successfull, 1 otherwise. This function is non-blocking.
*/
uint32_t dma_cbuf_read_byte(volatile struct DmaCircBuffer* buffer, uint32_t dma_cbuf_read_byte(volatile struct DmaCircBuffer* buffer,
uint8_t* byte); uint8_t* byte);

View File

@ -12,12 +12,9 @@
//--local definitions----------------------------------------------------------- //--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 \ #define DMA_CONFIG (DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_MEM \
| DMA_CONFIG_INC_MEM | DMA_CONFIG_MSIZE_8BITS) | DMA_CONFIG_INC_MEM | DMA_CONFIG_PSIZE_8BITS \
| DMA_CONFIG_MSIZE_8BITS)
static void mbuf_callback(enum DmaIRQSource src, volatile void* param); static void mbuf_callback(enum DmaIRQSource src, volatile void* param);
@ -63,16 +60,12 @@ uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer,
return 0; return 0;
} }
uint32_t dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer) void dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer)
{ {
//no data to send, stop here //if transfer already in progress or no data to send, don't start the
if (buffer->byte_index == 0) { //transfer
return 0; if (buffer->dma_running || buffer->byte_index == 0) {
} return;
//dma already running, give up
if (buffer->dma_running) {
return 1;
} }
//start a new transfer //start a new transfer
@ -87,15 +80,15 @@ uint32_t dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer)
buffer->buffer_index = 0; buffer->buffer_index = 0;
} }
return 0; return;
} }
//--local functions------------------------------------------------------------- //--local functions-------------------------------------------------------------
/** /**
* Callback called on DMA TX tranfert's completion. Stops the DMA and notifies * Callback called on DMA TX tranfert's completion. Checks for any remaining
* the buffer that the transfer is done. * data to send. If any, starts a new transfer, else stop the DMA
*/ */
static void mbuf_callback(enum DmaIRQSource src, volatile void* param) static void mbuf_callback(enum DmaIRQSource src, volatile void* param)
{ {

View File

@ -2,7 +2,7 @@
* Module handling Direct Memory Access controller's multibuffer system * Module handling Direct Memory Access controller's multibuffer system
* *
* The module provides a convenient tool to send data to a peripheral in a * The module provides a convenient tool to send data to a peripheral in a
* buffered, low-latency, low-cpu usage, non-blocking way * buffered, low-altency, low-cpu usage, non-blocking way
*/ */
#ifndef _DMA_MBUF_H_ #ifndef _DMA_MBUF_H_
@ -17,38 +17,36 @@
/** /**
* Struct used by the multibuffer system. This system allows bufferized writes * Struct used by the multibuffer system. This system allows bufferized writes
* to a peripheral with controlled latency, minimal cpu usage and customisable * to a peripheral with no latency, minimal cpu usage and customisable buffer
* buffer size * sizes
*/ */
struct DmaMultiBuffer { struct DmaMultiBuffer {
uint8_t* raw_buffer; //the buffer to use as a multi-buffer uint8_t* raw_buffer;
uint16_t buffer_size; //the size of the buffer uint16_t buffer_size;
uint8_t byte_index; //index of the next byte to be written uint8_t byte_index;
uint8_t buffer_index; //index of the buffer being written to uint8_t buffer_index;
enum DmaPeriph dma; //DMA peripheral used for transfers enum DmaPeriph dma;
enum DmaChannel channel; //DMA channel used for transfers enum DmaChannel channel;
bool dma_running; //whether the dam is currently running or not bool dma_running;
}; };
//--functions------------------------------------------------------------------- //--functions-------------------------------------------------------------------
/** /**
* Configure a DMA multibuffer for a single DMA channel. The given buffer is * Configure a DMA multibuffer for a single DMA channel. A list of buffers is
* divided into 2 to allow one part to be written to while the other is being * used to allow concurent write and DMA tranfers to the specified destination
* transfered by the DMA to a peripheral. * wich must be a peripheral. The DMA's priority is also given as parameters.
* The peripheral's specific configuration must be handled separately. * The peripheral's specific configuration must be handled separately. 2 bytes
* Each peripheral's driver is responsible for providing the DMA configuration * are reserved in each buffer for index storage.
* 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 buffer can be written to at any given time using dma_mbuf_write_byte(), * This system needs to be started manually: dma_mbuf_refresh() should be called
* but its content are only written to the corresponding peripheral when * whenever a DMA transfer can be started. This can be done manually after
* dma_mbuf_switch() is called. * 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
*/ */
void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer, void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer,
const struct DmaParam* param, enum DmaConfig priority, const struct DmaParam* param, enum DmaConfig priority,
@ -59,17 +57,18 @@ void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer,
* was successfull, 1 otherwise. The function is non-blocking. * was successfull, 1 otherwise. The function is non-blocking.
* *
* Note: calling this function will not trigger a DMA transfer, see * Note: calling this function will not trigger a DMA transfer, see
* dma_mbuf_switch() to do that * dma_mbuf_refresh() to do that
*/ */
uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer, uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer,
uint8_t byte); uint8_t byte);
/** /**
* Switch the buffers, triggering a DMA transfer while allowing writes to * Refresh the buffer state, checking for bytes to send and triggering a DMA
* continue. This function may fail if a DMA transfer is already running, * transfer if necessary. Should be called for the first transfer, any remaining
* returning 1 * transfer will be handled automatically until there are no bytes left in the
* buffer
*/ */
uint32_t dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer); void dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer);
#endif //_DMA_MBUF_H_ #endif //_DMA_MBUF_H_