openmv/lib/alif/drivers/source/dma_ctrl.c
iabdalkader daf2bb30da misc: Restructure repo.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-13 08:28:34 +02:00

169 lines
6.2 KiB
C

/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
* Use, distribution and modification of this code is permitted under the
* terms stated in the Alif Semiconductor Software License Agreement
*
* You should have received a copy of the Alif Semiconductor Software
* License Agreement with this file. If not, please write to:
* contact@alifsemi.com, or visit: https://alifsemi.com/license
*
*/
/**************************************************************************//**
* @file dma_ctrl.c
* @author Sudhir Sreedharan
* @email sudhir@alifsemi.com
* @version V1.0.0
* @date 28-Sep-2023
* @brief DMA control driver
* @bug None
* @Note None
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <dma_ctrl.h>
/**
\fn int8_t dma_allocate_channel(dma_config_info_t *dma_cfg)
\brief Allocate a channel if available
\param[in] dma_cfg Pointer to DMA Configuration resources
\return int8_t channel number or -1 if not available
*/
int8_t dma_allocate_channel(dma_config_info_t *dma_cfg)
{
dma_thread_info_t *channel_thread = &dma_cfg->channel_thread[0];
dma_channel_info_t *channel_info;
uint8_t channel_num;
for(channel_num = 0; channel_num < DMA_MAX_CHANNELS; channel_num++)
{
if(channel_thread[channel_num].in_use == false)
{
channel_thread[channel_num].in_use = true;
channel_thread[channel_num].user_mcode = (void *)0;
channel_info = &channel_thread[channel_num].channel_info;
channel_info->flags = 0;
return (int8_t)channel_num;
}
}
return -1;
}
/**
\fn int8_t dma_allocate_event(dma_config_info_t *dma_cfg,
uint8_t channel_num)
\brief Allocate a event if available
\param[in] dma_cfg Pointer to DMA Configuration resources
\param[in] channel_num Channel Number
\return int8_t Event index number or -1 if not available
*/
int8_t dma_allocate_event(dma_config_info_t *dma_cfg, uint8_t channel_num)
{
dma_thread_info_t *thread_info = &dma_cfg->channel_thread[channel_num];
dma_channel_info_t *channel_info = &thread_info->channel_info;
uint8_t event_index;
for(event_index = 0; event_index < DMA_MAX_EVENTS; event_index++)
{
if(dma_cfg->event_map[event_index] == 0xFF)
{
dma_cfg->event_map[event_index] = channel_num;
channel_info->event_index = event_index;
return (int8_t)event_index;
}
}
return -1;
}
/**
\fn void dma_copy_desc_info(dma_config_info_t *dma_cfg,
uint8_t channel_num,
dma_desc_info_t *desc_info)
\brief Update the channel descriptor Structure
\param[in] dma_cfg Pointer to DMA Configuration resources
\param[in] channel_num Channel Number
\param[in] desc_info Descriptor Information
\return None
*/
void dma_copy_desc_info(dma_config_info_t *dma_cfg,
uint8_t channel_num,
dma_desc_info_t *desc_info)
{
dma_thread_info_t *thread_info = &dma_cfg->channel_thread[channel_num];
dma_channel_info_t *channel_info = &thread_info->channel_info;
dma_desc_info_t *channel_desc_info = &channel_info->desc_info;
channel_desc_info->direction = desc_info->direction;
channel_desc_info->total_len = desc_info->total_len;
channel_desc_info->src_addr = desc_info->src_addr;
channel_desc_info->dst_addr0 = desc_info->dst_addr0;
channel_desc_info->src_bsize = desc_info->src_bsize;
channel_desc_info->dst_bsize = desc_info->dst_bsize;
channel_desc_info->src_blen = desc_info->src_blen;
channel_desc_info->dst_blen = desc_info->dst_blen;
channel_desc_info->periph_num = desc_info->periph_num;
if(channel_desc_info->direction == DMA_TRANSFER_MEM_TO_DEV)
{
channel_desc_info->dst_cache_ctrl = 0x0;
}
else if(channel_desc_info->direction == DMA_TRANSFER_DEV_TO_MEM)
{
channel_desc_info->src_cache_ctrl = 0x0;
}
}
/**
\fn dma_ccr_t dma_get_channel_ctrl_info(dma_config_info_t *dma_cfg,
uint8_t channel_num)
\brief Return the Channel Control Info from Descriptor info
\param[in] dma_cfg Pointer to DMA Configuration resources
\param[in] channel_num Channel Number
\return dma_ccr_t channel Control Info (CCR)
*/
dma_ccr_t dma_get_channel_ctrl_info(dma_config_info_t *dma_cfg,
uint8_t channel_num)
{
dma_thread_info_t *thread_info = &dma_cfg->channel_thread[channel_num];
dma_channel_info_t *channel_info = &thread_info->channel_info;
dma_desc_info_t *channel_desc_info = &channel_info->desc_info;
dma_ccr_t dma_ccr;
dma_ccr.value = 0;
dma_ccr.value_b.dst_burst_len = channel_desc_info->dst_blen - 1;
dma_ccr.value_b.src_burst_len = channel_desc_info->src_blen - 1;
dma_ccr.value_b.dst_burst_size = channel_desc_info->dst_bsize;
dma_ccr.value_b.src_burst_size = channel_desc_info->src_bsize;
dma_ccr.value_b.dst_cache_ctrl = channel_desc_info->dst_cache_ctrl;
dma_ccr.value_b.src_cache_ctrl = channel_desc_info->src_cache_ctrl;
dma_ccr.value_b.dst_prot_ctrl = channel_desc_info->dst_prot_ctrl;
dma_ccr.value_b.src_prot_ctrl = channel_desc_info->src_prot_ctrl;
dma_ccr.value_b.endian_swap_size = channel_desc_info->endian_swap_size;
if(channel_desc_info->direction == DMA_TRANSFER_MEM_TO_DEV)
{
dma_ccr.value_b.dst_inc = DMA_BURST_FIXED;
dma_ccr.value_b.src_inc = DMA_BURST_INCREMENTING;
}
else if(channel_desc_info->direction == DMA_TRANSFER_DEV_TO_MEM)
{
dma_ccr.value_b.dst_inc = DMA_BURST_INCREMENTING;
dma_ccr.value_b.src_inc = DMA_BURST_FIXED;
}
else
{
dma_ccr.value_b.dst_inc = DMA_BURST_INCREMENTING;
dma_ccr.value_b.src_inc = DMA_BURST_INCREMENTING;
}
return dma_ccr;
}