转载自:http://blog.sina.com.cn/s/blog_735f291001016ke4.html
看到EMIF_FMKS(GBLCTL,NOHOLD,DISABLE)甚是不解,以前没有碰到过这种写法所以查阅资料理解如下。
DSP开发板自带程序中有如下语句:
EMIF_Config MyEMIFcfg0={
0x30 |
EMIF_FMKS(GBLCTL,NOHOLD,DISABLE) |
EMIF_FMKS(GBLCTL,CLK1EN,DISABLE) |
EMIF_FMKS(GBLCTL,CLK2EN,ENABLE),……}
EMIF_FMKS(GBLCTL,NOHOLD,DISABLE)是在CSL_emifahal.h里预定义的一个宏,如下:
#define EMIF_FMKS(REG,FIELD,SYM)
_PER_FMKS(EMIF,##REG,##FIELD,##SYM)
这里有##和两个符号需要大家理解一下,举个例子:
1、“##”是宏定义中使用的连字符。
#define a(w, h) a_##w##x##h
那么a(720, 576) 就等价于 a_720x576
2、‘’ 是程序换行符。用法就顾名思义了,需要注意的是‘’的后面不能有空格,那样它会失效,编译会出问题的。
所以上面的语句可以等同于#define EMIF_FMKS(REG,FIELD,SYM) _PER_FMKS(EMIF,##REG,##FIELD,##SYM)
看到这里 貌似有点思路了吧……嘿嘿,下面继续:
根据《TMS320C6000 Chip Support Library API ReferenceGuide》查找上语句操作如下:
Field Make Symbolically _FMKS
Macro _FMKS(,,)
Arguments Register name
Field name
Symbolic field value
Return Value Uint32 In-place and masked-field value
Description This macro takes the symbolic field value then shiftsit over and masks it to
form the in-place field value. It can be bit-wise OR’ed with otherFMK or FMKS
macros to form a register value as an alternative to the RMKmacro.
Example Uint32 x;
x = DMA_FMKS(AUXCTL, CHPRI, HIGHEST)
| DMA_FMKS(AUXCTL, AUXPRI,CPU);
以上中文我们可以理解为:根据define用法,上面的语句是操作_PER_FMKS(,,,)即:
_PER_FMKS(EMIF,REG,FIELD,SYM)//EMIFA是要操作的寄存器,REG=GBLCTL,FIELD=NOHOLD,SYM=DISABLE即:
_PER_FMKS(EMIF,GBLCTL,NOHOLD,DISABLE)
到此步步推入,可能写的有点繁琐如下:EMIF_FMKS(GBLCTL,NOHOLD,DISABLE)
等价于:_PER_FMKS(EMIF,GBLCTL,NOHOLD,DISABLE)
又根据宏定义:
#define_PER_FMKS(PER,REG,FIELD,SYM) (
(_PER_FSYM(##PER,##REG,##FIELD,##SYM)<<_PER_FSHIFT(##PER,##REG,##FIELD))
&_PER_FMASK(##PER,##REG,##FIELD)
)
接着等价于:((_PER_FSYM(EMIF,GBLCTL,NOHOLD,DISABLE)<<_PER_FSHIFT(EMIF,GBLCTL,NOHOLD))&_PER_FMASK(EMIF,GBLCTL,NOHOLD))
根据宏定义:
#define_PER_FSHIFT(PER,REG,FIELD)
_##PER##_##REG##_##FIELD##_SHIFT
#define _PER_FMASK(PER,REG,FIELD)
_##PER##_##REG##_##FIELD##_MASK
#define _PER_FSYM(PER,REG,FIELD,SYM)
PER##_##REG##_##FIELD##_##SYM
继续等价于:((_EMIF_GBLCTL_NOHOLD_DISABLE)<<_EMIF_GBLCTL_NOHOLD_SHIFT)&_EMIF_GBLCTL_NOHOLD_MASK)
好了:到此最后碰到问题了……这到底是什么意思呢?
原来
#define _PER_FSHIFT(PER,REG,FIELD)
_##PER##_##REG##_##FIELD##_SHIFT
假如:
你设置:_EMIF_FSHIFT(EMIF,GBLCTL,BUSREQ)
那么就是:_EMIF_GBLCTL_BUSREQ_SHIFT
然后再一个CSL头文件中会有一个定义:
#define _EMIF_GBLCTL_BUSREQ_SHIFT 0x0000000Bu
然后说EMIF、GBLCTL、BUSREQ是怎么来的,那就需要看一些TI的文档了---CSL支持库的那个文档
我们查csl_emifhal.h头文件中可以看到
#define EMIF_GBLCTL_NOHOLD_DISABLE 0x00000000u
#define_EMIF_GBLCTL_NOHOLD_SHIFT 0x00000007u
#define_EMIF_GBLCTL_NOHOLD_MASK 0x00000080u
最终等价:((_EMIF_GBLCTL_NOHOLD_DISABLE)<<_EMIF_GBLCTL_NOHOLD_SHIFT)&_EMIF_GBLCTL_NOHOLD_MASK)
即变成了0x00000000u
至此我们就完全理解了 这只是一种TI的写法而已 最终还是和我们平时接触的是一样的……