概述
本文通过分析NXP S32K1的官方S32SDK,剖析其DMA代码,以便后续更好的使用DMA。
虚拟通道
在MCU中,可能由1-多个DMA实例,每个实例又有若干不同数目的DMA通道,为此,在S32SDK的DRV中引入virtualChannel的概念,隔绝底层的差异,用户只需要关心一个(虚拟)通道完成什么样的事情。
/* Get DMA instance from virtual channel */
uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);
/* Get DMA channel from virtual channel*/
uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);
在DRV接口中,操作的便是不同的virtualChannel。
运行时状态
由于是使用C语言实现,没有类似C++中类这样的封装技术,但NXP也巧妙的使用了这样的概念,在初始化时引入一个edma_state_t *edmaState。
typedef struct {
edma_chn_state_t * volatile virtChnState[(uint32_t)FEATURE_DMA_VIRTUAL_CHANNELS]; /*!< Pointer array storing channel state. */
} edma_state_t;
typedef struct {
uint8_t virtChn; /*!< Virtual channel number. */
edma_callback_t callback; /*!< Callback function pointer for the eDMA channel. It will
be called at the eDMA channel complete and eDMA channel
error. */
void *parameter; /*!< Parameter for the callback function pointer. */
volatile edma_chn_status_t status; /*!< eDMA channel status. */
} edma_chn_state_t;
edmaState通过数组指针的方式保存有所有通道的运行时信息,供外设驱动使用。
而edma_chn_state_t便是每个通道的信息,有通道号,供用户使用的回调函数,以及通道状态(正常or错误)。
配置信息
同S32SDK中其他模块一样,使用xxx_config_t的方式,提供模块的配置信息,在初始化时,将config赋给state,这样的好处就是可以使用图形化的配置工具生成特定模块的c语言结构体的config。
typedef struct {
edma_channel_priority_t channelPriority; /*!< eDMA channel priority - only used when channel arbitration mode is 'Fixed priority'. */
uint8_t virtChnConfig; /*!< eDMA virtual channel number */
dma_request_source_t source; /*!< Selects the source of the DMA request for this channel */
edma_callback_t callback; /*!< Callback that will be registered for this channel */
void * callbackParam; /*!< Parameter passed to the channel callback */
bool enableTrigger; /*!< Enables the periodic trigger capability for the DMA channel. */
} edma_channel_config_t;
对于一个通道的配置,有通道号、优先级、触发源、回调函数、是否周期触发等。
初始化
status_t EDMA_DRV_Init(edma_state_t *edmaState,
const edma_user_config_t *userConfig,
edma_chn_state_t * const chnStateArray[]