MPC5744P-DMA模块及SPI DMA发送

1、MPC5744P 主从机模块

mpc5744含有z4d_0 core、z4d_0 core Nexus、DMA、SIPI、FlexRay五个主机模块和FLASH CTRL、PRAM CTRL、PBRIDGE #0、PBRIDGE #1、TCM五个从机模块,其中z4d_0 core、z4d_0 core Nexus、FlexRay连接主机端口M0、M1、M6,DMA和SIPI公用主机端口M5;FLASH CTRL、PRAM CTRL、PBRIDGE #0、PBRIDGE #1、TCM分别连接值从机端口S0、S2、S4、S5、S7。MPC5744P通过Crossbar Switch来管理主机对从机的访问,通过AIPS_Lite来管理主机对从机对外设模块的访问权。主机和从机对应的连接端口和Crossbar Switch逻辑关系如下:
在这里插入图片描述
主机的逻辑ID为:
在这里插入图片描述

2、DMA访问优先级和访问权限的配置

1、主机对从机访问优先级的配置
5744通过cossbar switch管理主机对从机的访问优先级,以满足不同主机可以同时访问不同从机,不同主机访问同一从机时进行正确优先级仲裁。5744位每个从机提供对应的优先级寄存器来定义不同主机访问该从机时的优先级,寄存器结构如下:
在这里插入图片描述M6、M5、M1、M0分别对应相应的主机访问该从机时的优先级,0位最高优先级、8为最低优先级,其中若主机数目小于5,则优先级只能为0~3,否则会导致错误,若主机数目大于等于5,则优先级可为0 ~n-1(为主机数目);
2、主机对外设桥访问权限的配置
5744通过AIPS_Lite来管理主机对外设桥的访问权限。5744为外设桥提供了对应的寄存器来进行主机访问权限的配置。寄存器配置结构如下:
在这里插入图片描述MTRx 、MTWx和MPLx对应主机Mx,则寄存器内各区域分别对应主机0(主机z4d_0 core逻辑ID为0)、2(主机DMA逻辑ID为2)、3(主机FlexRay逻辑ID为3)、4(主机SIPI逻辑ID为4)。

  • MTRx 运行主机x对该外设桥读 0:不可读 1:可读
  • MTWx 运行主机x对该外设桥写 0:不可写 1:可写
  • MPLx 设置主机x对该外设桥的特权级别 0:来自主机x的访问强迫至用户模式 1:来自主机x的访问不强迫至用户模式

3、DMA请求源和DAM通道的配置

1、DMA通道配置
5744通过DMAMUX来将外部DMA请求源分配给对应的DAM通道,若使用相应的外设进行DMA数据传输,则需要使用DMAMUX对相应通道进行配置。DMA每个通道对应一个DMAMUX_CHCFG用于通道使能和选择可用DAM请求源,配置寄存器如下图:

在这里插入图片描述

  • ENBL DMA通道使能 1:该寄存器对应的DAM通道使能 0:该寄存器对应的DAM通道失能
  • TRIG DMA通道触发使能 1:触发使能,若ENBL也使能,则为周期触发模式 0:触发失能,若ENBL使能,则为正常单词触发模式。
  • SOURCE DMA通道源
    2、DMA通道与DMA请求源的关系
    DMAMUX含有DMAMUX_0和DAMMUX _1两个模块,分别管理通道0~15和通道16 ~31,这两个模块对应的DAM请求源如下图:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

4、DMA模块

1、DMA模块
DAM模块含有eDMA Engine和TCD两个部分,模块图如下:
在这里插入图片描述2、DMA基本数据流向
DMA将数据分为1个或多个minor loop进行传输,每完成一次minor loop传输将当前状态写回TCD并进行一次通道仲裁,如果有优先级更高的DAM请求,则让出控制权。示意图如下:
在这里插入图片描述
基本流程如下:
1)DMA请求内部注册后进入DMA Engine,在通过通道仲裁后将激活的通道转化成访问对应TCD的所需地址,然后访问TCD内存区将所需TCD加载到DMA Engine内的Address Path对应的寄存器内,流程如下:
在这里插入图片描述2)将TCD加载入Address Path内对应的寄存器后在DMA Engine控制下进行数据传送。
在这里插入图片描述3)在mior loop指定长度的数据传送完毕之后,address path将当前源地址、目的地址写入对应的TCD进行更新,若有新的DAM请求进入,则进行通道仲裁,可根据当前DAM通道的优先级和是否允许抢占来决定是否让出使用权给更高优先级的DMA通道。若major iteration(也就是数据传输完毕所需要的minor的数据)完成,则进行最终地址调整和major iteration的更新,若允许DMA中断请求,此时也会请求DMA中断。
3、DMA TCD
5744位每个DAM 通道一个TCD来进行DMA数据传输控制,其结构如下:
在这里插入图片描述主要用到的模块意义分别是:
1)SADDR :源地址
2)SSIZE :原数据字节长度
3)DSIZE :目的数据字节长度
4)SOFF :每进行一个源数据传输,目的地址增加数目
5)SMODE DMODE :源地址和目的地址是否采用取模方式
6)NBYTES :每次DAM请求传输的字节数
7)SLAST :完成数据传输后对源地址的修正值,即当前值加上修正值为最终源地址。
8)DADDR :目的地址
9)CITER:当前minor loop的数目
10)DOFF :每进行一次目的数据传输,目的地址增加数目
11)DLAST_SGA :完成数据传输后对目的地址的修正值,即当前值加上修正值为最终目的地址
12)BITER:开始minor的数目
13)BITER.E_LINK ,CITER.E_LINK :minor loop完成后是否允许通道之间连接,即当一个minor loop完成后是否自动启动另一个DMA通道的minor loop传输。
14)CITER.LINKCH、BITER.LINKCH:所要链接的通道号
15)MAJOR.E_LINK:major iteratio完成后是否允许通道直接连接,即当数据传输完成后是否自动启动另一个通道的数据传输。
16)MAJOR LINKCH:所要链接的通道号。

5、DMA配置

1、配置流程
1)配置Crossbar switch设置DMA访问外设桥的优先级;
2)配置AIPS_Lite 设置DMA对外设的访问权限;
3)配置DMAMUX 设置DMA通道的DMA请求源;
4)配置DMA通道组和通道优先级类型和优先级(DMA分为两组,每组含有16个通道,组与组之间有固定优先级和回环优先级,每组内的通道之间有固定优先级和回环优先级,回环优先级类型忽略为通道制定的优先级,不进行通道抢占;固定优先级要求为每个组好组内通道设置的优先级不同,高优先级可抢占低优先级,但可以设置DMA_DCHPRI寄存器来设置该通道是否能抢占其它通道或是否能被其他通道抢占);
5)配置对应通道的TCD并允许该通道响应DMA请求;
6)配置对应外设运行发起DMA传输请求(本例以SPI为例);
2、示例代码
1)DMA 总体配置

/***************************************************************
 * 名称         DMA_Config
 * 功能         进行DMA模块的配置
 * 输出参数     无
 * 返回值       无
 * 示例         DMA_Config();//对DAM模块进行配置
 ***************************************************************
 */
void DMA_Config()
{

	XBAR_0.PORT[4].PRS.R = 0x03000021; //配置DMA对外设桥0访问具有最高优先级
	XBAR_0.PORT[5].PRS.R = 0x03000021; //配置DMA对外设桥1访问具有最高优先级
	XBAR_0.PORT[0].PRS.R = 0x03000021; //配置DMA对Flash访问具有最高优先级

	AIPS_0.MPRA.R |= 0x77777770;       //配置所有主机对外设桥0具有读、写权限
	AIPS_1.MPRA.R |= 0x77777770;       //配置所有主机对外设桥1具有读、写权限

	DMAMUX_Init();
	DMA_Init();
}

2)DMAMUX配置

/*****************************************
 * 名称          DMAMUX_Init
 * 功能          进行DMUXMUX的初始化 为相应的DMA通道设置请求源
 * 输入参数      无
 * 返回值        无
 * 示例          DMAMUX_Init();//对DMAMUX进行初始化
 */
static void DMAMUX_Init()
{
	MC_ME.PCTL36.B.RUN_CFG=0;     //设置DMAMUX_0运行模式
	MC_ME.PCTL146.B.RUN_CFG=0;  //设置DMAMUX_1运行模式
	DMAMUX_1.CHCFG[0].R=0x83;     //使能通道16并选择SPI1发送为DMA请求源
}

3)DMA配置

/*****************************************
 * 名称          DMA_Init
 * 功能          进行DMA模块的初始化
 * 输入参数      无
 * 返回值        无
 * 示例          DMA_Init();//对DMA模块进行初始化
 */
static void DMA_Init()
{
	DMA_0.CR.B.HALT=1;    //停止DMA传输
	DMA_0.CR.B.ERGA=1;    //选择组优先级类型为回环类型
	DMA_0.CR.B.ERCA=1;    //选择组内通道优先级类型为回环型
	DMA_0.CR.B.HALT=0;    //开始DMA传输
}

4)DMA通道配置

/*********************************************************
 * 名称         DMA_Channel_Config
  *功能         进行DMA通道配置
 * 输入参数
 *              dam_channle
 *                选择的DMA通道
 *              src
 *                DMA传输的源地址
 *              dst
 *                DMA传输的目的地址
 *              data_num
 *                DMA要传输的数据数目
 * 返回值        无
 * 示例          DMA_Channel_Config(DMA_CHANNEL0,src,dst,10);//选择DMA通道0从地址src传输10个数据到目的地址dst
 *********************************************************
 */
void DMA_Channel_Config(uint8_t dam_channel,uint32_t *src,uint32_t *dst,uint32_t data_num)
{
	//源地址相关的配置
	DMA_0.TCD[dam_channel].SADDR.R=(vuint32_t)src;  //设置源地址
	DMA_0.TCD[dam_channel].SOFF.R=4;                //设置minor loop步长,即每进行一次数据传输源地址增长数,以字节为
	                                                //1 :1字节  2:2字节  4:4字节...
	DMA_0.TCD[dam_channel].SLAST.R=-4*data_num;     //数据传输完后对源地址进行调整,完成后的地址加上该寄存器的值为最终源地址
	                                                //1 :1字节  2:2字节  4:4字节...
	DMA_0.TCD[dam_channel].ATTR.B.SMOD=0;           //不选择源地址取模
	DMA_0.TCD[dam_channel].ATTR.B.SSIZE=2;          //源数据字节长,2为32位

	DMA_0.TCD[dam_channel].DADDR.R=(vuint32_t)dst;  //设置目的地址
	DMA_0.TCD[dam_channel].DOFF.R=0;                //设置minor loop步长,即每进行一次数据传输目的地址增长数,以字节为单位
	DMA_0.TCD[dam_channel].DLASTSGA.R=0;            //数据传输完后对目的地址进行调整,完成后的地址加上该寄存器的值为最终目的地址,以字节为单位

	DMA_0.TCD[dam_channel].ATTR.B.DMOD=0;           //不选择目的地址取模
	DMA_0.TCD[dam_channel].ATTR.B.DSIZE=2;          //目标数据字长,2为32位

	DMA_0.TCD[dam_channel].CSR.B.DREQ = 1;
	DMA_0.TCD[dam_channel].NBYTES.MLNO.B.NBYTES=4;         //选择minor loop传输的字节数目

	DMA_0.TCD[dam_channel].BITER.ELINKNO.B.ELINK=0;        //minor loop完成后不选择通道链接
	DMA_0.TCD[dam_channel].BITER.ELINKNO.B.BITER=data_num; //设置开始minor loop数目
	DMA_0.TCD[dam_channel].CITER.ELINKNO.B.ELINK=0;        //minor loop完成后不选择通道链接
	DMA_0.TCD[dam_channel].CITER.ELINKNO.B.CITER=data_num; //设置当前minor loop数目,初始化时应保证CITER与BITER中minor loop数目相等

	DMA_0.SERQ.R=dam_channel;                              //允许对通道dma_channel进行dma请求
}

5)设置允许SPI1发送模块发起DMA请求

******************************SPI1**********************************/
void SPI_SPI1_Init()
{
    .......
	SPI_1.RSER.R = 0x03000000; //设置SPI1使能TFFF中断或DMA请求,选择TFFF 发起DMA请求
   ........
}

猜你喜欢

转载自blog.csdn.net/sinat_31773903/article/details/88844666
DMA
今日推荐