介绍:本文主要讲解CC3200寄存器操作中的 (*((volatile uint32_t *)(x))) 语句,内容牵涉到位带操作,volatile 关键字。
在CC3200开发过程当中,使用的SDK开发都是库函数操作,即只需要调用相关的函数,确定相应的入口参数就可以实现特定功能。但是库函数归根结底的功能是操作寄存器中的相关位,通过一层一层的调用关系,你会发现,凡是对硬件的操作最终都会调用到下面几条语句:
#define HWREG(x) (*((volatile uint32_t *)(x)))
#define HWREGH(x) (*((volatile uint16_t *)(x)))
#define HWREGB(x) (*((volatile uint8_t *)(x)))
#define HWREGBITW(x, b) /
HWREG(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITH(x, b) /
HWREGH(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITB(x, b) /
HWREGB(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
前面3句是直接的寄存器操作,后面三句是通过“位带操作”操作寄存器,关于位带操作,可以参考cortex M3权威指南之位带(Bit Band)操作
位带操作最主要是理解位带区和未带别名区的对应关系。对HWREG(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)) 进行如下解析:
下面主要分析下直接操作寄存器位的C语言语句:(*((volatile uint32_t *)(x)))
1、绿色部分(volatile uint32_t *)(x)表示将X强制转化为uint32-t型指针;
2、*((volatile uint32_t *)(x)),设(volatile uint32_t *)(x)=P,则表达式为*P,我们可以对*P进行取值和赋值。
3、volatile是告诉编译器这段代码不要优化,也就是每次取值,都是从内存里面取,而不是从寄存器里面直接取。更多了解,参考嵌入式中的 *(volatile unsigned int *)0x500 解释。
***************************************************************************************************************************************************************************************************
实例
在CC3200 I2C开发过着中,调用I2CMasterDataPut(uint32_t ui32Base, uint8_t ui8Data);其中uint32_t ui32Base为I2C外设的基地址,uint8_t ui8Data为要发送的数据,该函数的具体实现为:
void
I2CMasterDataPut(uint32_t ui32Base, uint8_t ui8Data)
{
//
// Check the arguments.
//
ASSERT(_I2CBaseValid(ui32Base));
//
// Write the byte.
//
HWREG(ui32Base + I2C_O_MDR) = ui8Data;//将ui8Data写到ui32Base + I2C_O_MDR地址里面去
}
ui32Base 和 I2C_O_MDR参数可以查看datasheet,如图1
总结:通过HWREG(x) 可以完成最底层硬件的操作。