先贴上TQ2440测试程序中的一个函数:
void Clk0_Enable(int clock_sel)
{ // 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
rMISCCR = rMISCCR&~(7<<4) | (clock_sel<<4);
rGPHCON = rGPHCON&~(3<<18) | (2<<18);
}
代码详解:
首先,查看rMISCCR变量的定义:
#define rMISCCR (*(volatile unsigned *)0x56000080) //Miscellaneous control
表示的是一个整型值,该值存放在0x56000080地址处。该地址为s3c2440的寄存器MISCCR(Miscellaneous control Register),查看s3c2440的datasheet,可知该寄存器的[6:4]位表示对clkout0的设置,如下图:
由此可以看出,上面的函数clk0_enable的作用就是为clkout0选择时钟源。具体选那个时钟源由传递给该函数的参数clock_sel指定。
以上就是该函数的功能。
提炼一下,该函数的作用就是将一个32位的整型数的4-6位设置成函数参数指定的值。那么它是怎么实现的呢?再仔细分析一下。要将该32位数的其他位保持不变,只将4-6这3位设置成指定的值,只需两个步骤:1.将其他位保持不变,4-6位清零。这可通过按位与操作实现。2.将4-6位设置成函数参数指定的值,这可通过按位或操作实现。其中步骤1的对4-6位清零可通过 rMISCCR &......(31到7位为1)000...(3到0位为1)实现。但是直接写成那种确定数相与的办法使得程序可移植性不好。
函数中rMISCCR&~(7<<4) 操作实现的就是把rMISCCR的4,5,6三位置0,其他位不变,而且程序具有可通用性。例如如果要将rMISCCR的9,10,11位清零,其他位不变,只需改成rMISCCR&~(111<<9)即可。也就是说rMISCCR&~(A<<B)中A指定的是要被置1的连续的位的个数,B指定的是该段连续位的最低位在这个整型数中所处的位置。这种先置1再移位再反转相与的思路值得借鉴。
同理rMISCCR&~(7<<4) | (clock_sel<<4);的后半段实现的就是对被清零的4-6位按函数参数进行设置。
文章评论(0条评论)
登录后参与讨论