Freerunning mode

Freerunning mode provides the ability to move data from one memory location to another. The FDMA hardware allows the source and destination addresses to be handled in one of three ways:

  • As a single memory location, accessed repeatedly
  • As a linear block of memory, read from the lower (smaller) address to the higher (larger) address
  • As a 2 dimensional array, specifying a span (the width of each line) and a stride (the difference between the start of each line)
These are the dimensions of the transfer: 0, 1 or 2D respectively. As both source and destination address can be treated differently, there are 3x3 = 9 possible combinations, however 2D to 2D transfers are not supported, so there are only eight possible combinations.

The functions to set the transfer dimensions are listed below, one of these functions must be called for each transfer descriptor:

void dma_params_DIM_0_x_0(struct stm_dma_params *p);
 
void dma_params_DIM_0_x_1(struct stm_dma_params *p);
 
void dma_params_DIM_0_x_2(struct stm_dma_params *p,
                          unsigned long line_len,
                          unsigned long dstride);
 
void dma_params_DIM_1_x_0(struct stm_dma_params *p);
 
void dma_params_DIM_1_x_1(struct stm_dma_params *p);
 
void dma_params_DIM_1_x_2(struct stm_dma_params *p,
                          unsigned long line_len,
                          unsigned long dstride);
 
void dma_params_DIM_2_x_0(struct stm_dma_params *p,
                          unsigned long line_len,
                          unsigned long sstride);
 
void dma_params_DIM_2_x_1(struct stm_dma_params *p,
                          unsigned long line_len,
                          unsigned long sstride);

The parameters are described in the table below:

Parameters Description
p This is a pointer to the stm_dma_params structure for the transfer.
line-len In a two-dimensional transfer, this is the length of a single line of data.
dstride In a two-dimensional transfer, this is the stride length (the distance between lines) of the destination buffer.
sstride In a two-dimensional transfer, this is the stride length (the distance between lines) of the source buffer.

Use the function dma_params_addrs() to set the source and destination addresses for the transfer and the length in bytes. This function must be called for all transfers:

void dma_params_addrs(struct stm_dma_params *p,
                      unsigned long src,
                      unsigned long dst,
                      unsigned long bytes);
Parameters Description
p This is a pointer to the stm_dma_params structure for the transfer.
src The is the physical source address.
dst The is the physical destination address.
bytes This is the length of the transfer in bytes.

Use the function dma_parms_addrs() to specify the source (src) and destination (dst) addresses for the transfer of bytes length which is specified by the structure p. This function is mandatory for all transfers.

	static inline void dma_parms_addrs(
					struct stm_dma_params *p,
					unsigned long src,
					unsigned long dst,
					unsigned long bytes)

The API provides a set of functions for specifying the transfer mode for multi-dimensional array transfers. These are listed below.

static inline void dma_parms_DIM_0_x_0(	struct stm_dma_params *p,
					unsigned long srcsize)
 
static inline void dma_parms_paced(	struct stm_dma_params *p,
					unsigned long xfer_size,
					int req_line)
 
static inline void dma_parms_DIM_0_x_1(	struct stm_dma_params *p,
					unsigned long srcsize)
 
static inline void dma_parms_DIM_0_x_2(	struct stm_dma_params *p,
					unsigned long srcsize,
					unsigned long dstride)
 
static inline void dma_parms_DIM_1_x_0(	struct stm_dma_params *p,
					unsigned long srcsize)
 
static inline void dma_parms_DIM_1_x_1(	struct stm_dma_params *p,
					unsigned long srcsize)
 
static inline void dma_parms_DIM_1_x_2(	struct stm_dma_params *p,
					unsigned long dstsize,
					unsigned long dstride)
 
static inline void dma_parms_DIM_2_x_0(	struct stm_dma_params *p,
					unsigned long srcsize,
					unsigned long sstride)
 
static inline void dma_parms_DIM_2_x_1(	struct stm_dma_params *p,
					unsigned long srcsize,
					unsigned long sstride)

The parameters are described in the table below:

Parameters Description
p This is a pointer to the stm_dma_params structure for the transfer.
srcsize The size in bytes of the source location.
dstsize The size in bytes of the destination location.
line-len In a one- or two-dimensional transfer, this is the length of a single line of data.
dstride In a two-dimensional transfer, this is the stride length (the distance between lines) of the destination buffer.
sstride In a two-dimensional transfer, this is the stride length (the distance between lines) of the source buffer.

Example:

static int foo(void)
{
	const char * dmac_id =STM_DMAC_ID;
	const char * hb_cap_channel = STM_DMA_CAP_HIGH_BW;
	unsigned long xfer_bytes =4096;
	void * src_buff = (void*)kmalloc(xfer_bytes,GFP_KERNEL);
	void * dst_buff = (void*)kmalloc(xfer_bytes,GFP_KERNEL);
	struct stm_dma_params dmap0;
	int ch_num = request_dma_bycap(&dmac_id,&hb_cap_channel,__FUNCTION__);	
	if(ch_num == -ENODEV){
		printk(" No DMA channel or DMAC available\n");
		return -ENODEV;
	}
	printk("%s IN ch %d\n",__FUNCTION__,ch_num);
 
 
 
	declare_dma_parms(
				&dmap0,
				MODE_FREERUNNING,
				STM_DMA_LIST_OPEN,
				STM_DMA_SETUP_CONTEXT_TASK,
				STM_DMA_NOBLOCK_MODE,
				STM_DMAC_ID);
 
	if(src_buff && dst_buff){	
		memset(src_buff,0x4,xfer_bytes);
		flush_cache_all();
	}
 
	dma_parms_addrs(&dmap0,
		virt_to_phys(src_buff),
		virt_to_phys(dst_buff),
		(unsigned long)xfer_bytes);
 
	dma_parms_comp_cb(&dmap0,report_on_node_complete,NULL,0);
 
	dma_parms_DIM_1_x_1(&dmap0,xfer_bytes);
	dma_compile_list(&dmap0);
	dma_xfer_list(ch_num,&dmap0);
	dma_wait_for_completion(ch_num);
	printk(" RECIEVED WAKE UP FROM DMA_API modifying for next transfer\n");		
 
 
	kfree(src_buff);
 
	src_buff = (void*)kmalloc(xfer_bytes,GFP_KERNEL);
 
	memset(src_buff,0x1,xfer_bytes);
 
	dma_parms_addrs(&dmap0,
			virt_to_phys(src_buff),
			virt_to_phys(dst_buff),
			xfer_bytes);
 
	dma_parms_DIM_1_x_1(&dmap0,xfer_bytes);
 
	dma_parms_comp_cb(&dmap0,report_on_node_complete_alt,NULL,0);
 
	dma_compile_list(&dmap0);
 
	dma_xfer_list(ch_num,&dmap0);
 
	dma_wait_for_completion(ch_num);
 
	printk(" RECIEVED WAKE UP FROM DMA_API modified  transfer\n");		
	free_dma(ch_num);
 
	dma_free_descriptor(&dmap0);
 
	kfree(src_buff);
 
	kfree(dst_buff);
 
	return 0;
 
}