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:
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; }