F28335的位域和寄存器结构的学习
实现位域和寄存器文件结构体的具体步骤(以SCI外设为例)1)、定义一个寄存器文件结构体,SCI外设的寄存器在结构体中按实际的地址由低向高依次列出。
[*]/********************************************************************
[*]* SCI header file
[*]* Defines a register file structure for the SCI peripheral
[*]********************************************************************/
[*]#define Uint16 unsigned int
[*]#define Uint32 unsigned long
[*]struct SCI_REGS {
[*]Uint16 SCICCR_REG SCICCR; // Communications control register
[*]Uint16 SCICTL1_REG SCICTL1; // Control register 1
[*]Uint16 SCIHBAUD; // Baud rate (high) register
[*]Uint16 SCILBAUD; // Baud rate (low) register
[*]Uint16 SCICTL2_REG SCICTL2; // Control register 2
[*]Uint16SCIRXST_REG SCIRXST; // Receive status register
[*]Uint16 SCIRXEMU; // Receive emulation buffer register
[*]Uint16SCIRXBUF_REG SCIRXBUF; // Receive data buffer
[*]Uint16 rsvd1; // reserved
[*]Uint16 SCITXBUF; // Transmit data buffer
[*]Uint16SCIFFTX_REG SCIFFTX; // FIFO transmit register
[*]Uint16SCIFFRX_REG SCIFFRX; // FIFO receive register
[*]Uint16SCIFFCT_REG SCIFFCT; // FIFO control register
[*]Uint16 rsvd2; // reserved
[*]Uint16 rsvd3; // reserved
[*]Uint16SCIPRI_REG SCIPRI; // FIFO Priority control
[*]};
复制代码
2)、上面的定义本身并没有建立任何的变量,只是定义了一个结构体,而并没有实例化。下面即定义了具体的变量。注意在这里使用了volatile关键字,它在这里的作用很重要,这使得编译器不会做一些错误的优化。
[*]/********************************************************************
[*]* Source file using register-file structures
[*]* Create a variable for each of the SCI register files
[*]********************************************************************/
[*]volatile struct SCI_REGS SciaRegs;
[*]volatile struct SCI_REGS ScibRegs;
复制代码
3)、利用DATA_SECTION Pragma,将寄存器文件结构体变量分配到特殊的数据段中。如果不使用这条指令,那么定义的寄存器文件结构体变量默认是被分配在.ebss或者.bss段的,但通过使用DATA_SECTION Pragma指令,编译器会将其放在了一个特殊的数据段中。具体实现如下:
[*]/********************************************************************
[*]* Assign variables to data sections using the #pragma compiler statement
[*]* C and C++ use different forms of the #pragma statement
[*]* When compiling a C++ program, the compiler will define __cplusplus automatically
[*]********************************************************************/
[*]//----------------------------------------
[*]#ifdef __cplusplus
[*]#pragmaDATA_SECTION("SciaRegsFile")
[*]#else
[*]#pragmaDATA_SECTION(SciaRegs,"SciaRegsFile");
[*]#endif
[*]volatile struct SCI_REGS SciaRegs;
[*]//----------------------------------------
[*]#ifdef __cplusplus
[*]#pragma DATA_SECTION("ScibRegsFile")
[*]#else
[*]#pragma DATA_SECTION(ScibRegs,"ScibRegsFile");
[*]#endif
[*]volatile struct SCI_REGS ScibRegs;
复制代码
通过上面的代码可以看到,定义的SciaRegs被分配到了SciaRegsFile段中,ScibRegs被分配到了ScibRegsFile段中。
4)、上面只是将定义的寄存器结构体变量分配到了一个特殊的数据段中,通过cmd文件,可将其映射到实际的存储单元,进而和外设实际的存储器映射地址统一起来。实现如下:
[*]/********************************************************************
[*]* Memory linker .cmd file
[*]* Assign the SCI register-file structures to the corresponding memory
[*]********************************************************************/
[*]MEMORY
[*]{
[*]...
[*]PAGE 1:
[*]SCIA : origin = 0x007050, length = 0x000010 /* SCI-A registers */
[*]SCIB : origin = 0x007750, length = 0x000010 /* SCI-B registers */
[*]...
[*]}
[*]SECTIONS
[*]{
[*]...
[*]SciaRegsFile : > SCIA, PAGE = 1
[*]ScibRegsFile : > SCIB, PAGE = 1
[*]...
[*]}
复制代码
5)、添加位域定义。
获取寄存器中特定的位经常是很有用的,位域的定义就提供了这种方便性;但是与此同时位域也缺乏硬件平台之间的可移植性。在位域的定义中,最低位,也就是0位,是寄存器中的第一个位域;位域不能超过寄存器的位数,最多为16位。
[*]/********************************************************************
[*]* SCI header file
[*]********************************************************************/
[*]//----------------------------------------------------------
[*]// SCICCR communication control register bit definitions:
[*]//
[*]struct SCICCR_BITS { // bit deion
[*]Uint16 SCICHAR:3; // 2:0 Character length control
[*]Uint16 ADDRIDLE_MODE:1; // 3 ADDR/IDLE Mode control
[*]Uint16 LOOPBKENA:1; // 4 Loop Back enable
[*]Uint16 PARITYENA:1; // 5 Parity enable
[*]Uint16 PARITY:1; // 6 Even or Odd Parity
[*]Uint16 STOPBITS:1; // 7 Number of Stop Bits
[*]Uint16 rsvd1:8; // 15:8 reserved
[*]};
[*]//-------------------------------------------
[*]// SCICTL1 control register 1 bit definitions:
[*]//
[*]struct SCICTL1_BITS { // bit deion
[*]Uint16 RXENA:1; // 0 SCI receiver enable
[*]Uint16 TXENA:1; // 1 SCI transmitter enable
[*]Uint16 SLEEP:1; // 2 SCI sleep
[*]Uint16 TXWAKE:1; // 3 Transmitter wakeup method
[*]Uint16 rsvd:1; // 4 reserved
[*]Uint16 SWRESET:1; // 5 Software reset
[*]Uint16 RXERRINTENA:1; // 6 Receive interrupt enable
[*]Uint16 rsvd1:9; // 15:7 reserved
[*]};
[*]
复制代码
在上面的定义中,使用了操作符“:”,用来说明位域的长度,即当前位域占几位。
6)、使用联合体。除了能够方便的访问位域外,有时候也希望能够对寄存器整体访问,使用联合体能够实现这种操作。
[*]/********************************************************************
[*]* SCI header file
[*]***** **************************************************************/
[*]union SCICCR_REG {
[*]Uint16 all;
[*]struct SCICCR_BITS bit;
[*]};
[*]union SCICTL1_REG {
[*]Uint16 all;
[*]struct SCICTL1_BITS bit;
[*]};
复制代码
7)、将添加位域后的寄存器结构体重新实现。
[*]/********************************************************************
[*]* SCI header file
[*]* Defines a register file structure for the SCI peripheral
[*]********************************************************************/
[*]#define Uint16 unsigned int
[*]#define Uint32 unsigned long
[*]struct SCI_REGS {
[*]Uint16 SCICCR_REG SCICCR; // Communications control register
[*]Uint16 SCICTL1_REG SCICTL1; // Control register 1
[*]Uint16 SCIHBAUD; // Baud rate (high) register
[*]Uint16 SCILBAUD; // Baud rate (low) register
[*]Uint16 SCICTL2_REG SCICTL2; // Control register 2
[*]Uint16SCIRXST_REG SCIRXST; // Receive status register
[*]Uint16 SCIRXEMU; // Receive emulation buffer register
[*]Uint16SCIRXBUF_REG SCIRXBUF; // Receive data buffer
[*]Uint16 rsvd1; // reserved
[*]Uint16 SCITXBUF; // Transmit data buffer
[*]Uint16SCIFFTX_REG SCIFFTX; // FIFO transmit register
[*]Uint16SCIFFRX_REG SCIFFRX; // FIFO receive register
[*]Uint16SCIFFCT_REG SCIFFCT; // FIFO control register
[*]Uint16 rsvd2; // reserved
[*]Uint16 rsvd3; // reserved
[*]Uint16SCIPRI_REG SCIPRI; // FIFO Priority control
[*]};
[*]
复制代码
这些文件都定义在哪里? 直接操作寄存器就行吧 当每个寄存器的位域结构体类型和共用体的定义都建立起来了,就可以定义这个寄存器类型了 寄存器文件结构体看着真是复杂。 C2000的开发都使用哪些资料? 定义的这些地址岂不是更复杂了? 位域中的内容也是存在顺序的 DSP对类型有什么要求?
页:
[1]