` CSLr库编写说明:
(1)这里我们以EDMA3CC通道控制寄存器为例,首先写一个包含EDMA3CC所有寄存器的结构体。
typedef struct {
volatile Uint32 CCCFG;
volatile Uint8 RSVD0[504];
volatile Uint32 QCHMAP[8];
volatile Uint8 RSVD1[32];
volatile Uint32 DMAQNUM[8];
volatile Uint32 QDMAQNUM;
volatile Uint8 RSVD2[32];
volatile Uint32 QUEPRI;
volatile Uint8 RSVD3[120];
volatile Uint32 EMR;
volatile Uint8 RSVD4[4];
volatile Uint32 EMCR;
volatile Uint8 RSVD5[4];
volatile Uint32 QEMR;
volatile Uint32 QEMCR;
volatile Uint32 CCERR;
volatile Uint32 CCERRCLR;
volatile Uint32 EEVAL;
volatile Uint8 RSVD7[28];
CSL_Edma3ccDraRegs DRA[4];
volatile Uint8 RSVD8[32];
CSL_Edma3ccQraeRegs QRA[4];
volatile Uint8 RSVD9[112];
CSL_Edma3ccQueueRegs QUEUE[2];
volatile Uint8 RSVD10[384];
volatile Uint32 QSTAT[3];
volatile Uint8 RSVD11[20];
volatile Uint32 QWMTHRA;
volatile Uint8 RSVD12[28];
volatile Uint32 CCSTAT;
volatile Uint8 RSVD13[2492];
volatile Uint32 ER;
volatile Uint8 RSVD14[4];
volatile Uint32 ECR;
volatile Uint8 RSVD15[4];
volatile Uint32 ESR;
volatile Uint8 RSVD16[4];
volatile Uint32 CER;
volatile Uint8 RSVD17[4];
volatile Uint32 EER;
volatile Uint8 RSVD18[4];
volatile Uint32 EECR;
volatile Uint8 RSVD19[4];
volatile Uint32 EESR;
volatile Uint8 RSVD20[4];
volatile Uint32 SER;
volatile Uint8 RSVD21[4];
volatile Uint32 SECR;
volatile Uint8 RSVD22[12];
volatile Uint32 IER;
volatile Uint8 RSVD23[4];
volatile Uint32 IECR;
volatile Uint8 RSVD24[4];
volatile Uint32 IESR;
volatile Uint8 RSVD25[4];
volatile Uint32 IPR;
volatile Uint8 RSVD26[4];
volatile Uint32 ICR;
volatile Uint8 RSVD27[4];
volatile Uint32 IEVAL;
volatile Uint8 RSVD28[4];
volatile Uint32 QER;
volatile Uint32 QEER;
volatile Uint32 QEECR;
volatile Uint32 QEESR;
volatile Uint32 QSER;
volatile Uint32 QSECR;
volatile Uint8 RSVD30[3944];
CSL_Edma3ccShadowRegs SHADOW[4];
volatile Uint8 RSVD31[6144];
CSL_Edma3ccParamSetRegs PARAMSET[128];
} CSL_Edma3ccRegs;
typedef struct {
volatile Uint32 DRAE;
volatile Uint8 RSVD6[4];
} CSL_Edma3ccDraRegs;
typedef struct {
volatile Uint8 RSVD6[3];
volatile Uint8 QRAE;
} CSL_Edma3ccQraeRegs;
typedef struct {
volatile Uint32 EVENT[16];
} CSL_Edma3ccQueueRegs;
typedef struct {
volatile Uint32 ER;
volatile Uint8 RSVD0[4];
volatile Uint32 ECR;
volatile Uint8 RSVD1[4];
volatile Uint32 ESR;
volatile Uint8 RSVD2[4];
volatile Uint32 CER;
volatile Uint8 RSVD3[4];
volatile Uint32 EER;
volatile Uint8 RSVD4[4];
volatile Uint32 EECR;
volatile Uint8 RSVD5[4];
volatile Uint32 EESR;
volatile Uint8 RSVD6[4];
volatile Uint32 SER;
volatile Uint8 RSVD7[4];
volatile Uint32 SECR;
volatile Uint8 RSVD8[12];
volatile Uint32 IER;
volatile Uint8 RSVD9[4];
volatile Uint32 IECR;
volatile Uint8 RSVD10[4];
volatile Uint32 IESR;
volatile Uint8 RSVD11[4];
volatile Uint32 IPR;
volatile Uint8 RSVD12[4];
volatile Uint32 ICR;
volatile Uint8 RSVD13[4];
volatile Uint32 IEVAL;
volatile Uint8 RSVD14[4];
volatile Uint32 QER;
volatile Uint32 QEER;
volatile Uint32 QEECR;
volatile Uint32 QEESR;
volatile Uint32 QSER;
volatile Uint32 QSECR;
volatile Uint8 RSVD15[360];
} CSL_Edma3ccShadowRegs;
typedef struct {
volatile Uint32 OPT;
volatile Uint32 SRC;
volatile Uint32 A_B_CNT;
volatile Uint32 DST;
volatile Uint32 SRC_DST_BIDX;
volatile Uint32 LINK_BCNTRLD;
volatile Uint32 SRC_DST_CIDX;
volatile Uint32 CCNT;
} CSL_Edma3ccParamSetRegs;
关于寄存器的位置及在内存中的地址见下图所示:
volatile Uint32QCHMAP[8];为8个数组形式的寄存器定义。
volatile Uint8 RSVD1[32];
注意啊,这里非常重要,每个寄存器都是32位的,可以看到QCHMAP[7]的偏移地址为021C,DMAQNUM[0]的偏移地址为0240,中间缺少0240h-0220h=20h(32d),因而在内存中需要移动32个地址(内存中单个地址为8位)【这里为什么是减去0220h呢,因为QCHMAP[7]寄存器要占4个内存地址,因而最后指向021Ch+4h】
volatile Uint32 DMAQNUM[8];
我们还可以在本结构体中再套用结构体 CSL_Edma3ccDraRegs DRA[4];
:记得创龙电子给的例程里,MMCSD中使用结构体套用定义了传输配置参数,临时数据存储单元,这样编写程序调用十分方便。
(2)由于在TMS320C6748中,有的模块不止一个,例如UART一共有3个,他们使用的寄存器相同,偏移地址相同,只有基地址不同,因而我们可以在主程序中可以使用这样的方法定义。
/** @brief Base address of Channel controller memory mapped registers */
#define SOC_EDMA30CC_0_REGS (0x01C00000u)
/** @brief Base address of Channel controller memory mapped registers */
#define SOC_EDMA31CC_0_REGS (0x01E30000u)
CSL_Edma3ccRegsOvly edma3ccRegs0=(CSL_Edma3ccRegsOvly)SOC_EDMA30CC_0_REG;
CSL_Edma3ccRegsOvly edma3ccRegs1=(CSL_Edma3ccRegsOvly)SOC_EDMA31CC_0_REG;
这样的好处就是一套结构体可以定义两个EDMA模块。
(3)宏定义。注##表示粘接的意思,例如:CSL_##PER_REG_FIELD##_SHIFT= CSL_PER_REG_FIELD_SHIFT
/* the "expression" macros */
/* the Field MaKe macro */
#define CSL_FMK(PER_REG_FIELD, val)
(((val) << CSL_##PER_REG_FIELD##_SHIFT) & CSL_##PER_REG_FIELD##_MASK)
/* the Field EXTract macro */
#define CSL_FEXT(reg, PER_REG_FIELD)
(((reg) & CSL_##PER_REG_FIELD##_MASK) >> CSL_##PER_REG_FIELD##_SHIFT)
/* the Field INSert macro */
#define CSL_FINS(reg, PER_REG_FIELD, val)
((reg) = ((reg) & ~CSL_##PER_REG_FIELD##_MASK)
|CSL_FMK(PER_REG_FIELD, val))
/* the "token" macros */
/* the Field MaKe (Token) macro */
#define CSL_FMKT(PER_REG_FIELD, TOKEN)
CSL_FMK(PER_REG_FIELD, CSL_##PER_REG_FIELD##_##TOKEN)
/* the Field INSert (Token) macro */
#define CSL_FINST(reg, PER_REG_FIELD, TOKEN)
CSL_FINS((reg), PER_REG_FIELD, CSL_##PER_REG_FIELD##_##TOKEN)
/* the "raw" macros */
/* the Field MaKe (Raw) macro */
#define CSL_FMKR(m***, l***, val)
(((val) & ((1 << ((m***) - (l***) + 1)) - 1)) << (l***))
/* the Field EXTract (Raw) macro */
#define CSL_FEXTR(reg, m***, l***)
(((reg) >> (l***)) & ((1 << ((m***) - (l***) + 1)) - 1))
/* the Field INSert (Raw) macro */
#define CSL_FINSR(reg, m***, l***, val)
((reg) = ((reg) &~ (((1 << ((m***) - (l***) + 1)) - 1) <<(l***)))
|CSL_FMKR(m***, l***, val))
另外还需要定义:
/* ECR */
#define CSL_EDMA3CC_ECR_REG_MASK (0xFFFFFFFFu)
#define CSL_EDMA3CC_ECR_REG_SHIFT (0x00000000u)
#define CSL_EDMA3CC_ECR_REG_RESETVAL (0x00000000u)
在主函数中可以这样使用:这样写的好处在于比较规范,程序意思易懂。
CSL_FINST(edma3ccRegs->ECR,EDMA3CC_ECR_REG, MASK);//清空中断事件
(4)常用定义方法:
a、ifdef与ifndef的使用
有时我们为了方便,可以移植别人写的头文件,但是可能出现两个不同的重复定义,如typedefunsigned int uint32_t;这是为了避免随意删除导致某些调用该文件的程序出错,我们可以这样定义
#ifndef uint32_t
#define unsigned int uint32_t;
#endif
这样对于原来的文件来说,如果没有定义这个变量名,那么在此定义,如果在别的头文件中定义了uint32_t,那么程序就跳过不执行,有效避免了重复定义,又做到了对原来的文件影响最小。
b、#pragma的使用
利用这个函数可以指定某数据、数组、程序在内存中的位置,一般来说比较实用的是在DDR中定义一个大数组。
//指定某数组到用户自定义在数据空间的段
#pragma DATA_SECTION(全局变量名,"用户自定义在数据空间的段名");
//指定某函数到用户自定义在数据空间的段
#pragma CODE_SECTION(函数名,"用户自定义在程序空间的段名");