FCCdsp 发表于 2017-10-23 10:28

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

[*]};

[*]

复制代码

51xlf 发表于 2017-10-23 22:03

这些文件都定义在哪里?

i1mcu 发表于 2017-10-23 22:03

直接操作寄存器就行吧

pmp 发表于 2017-10-23 22:04

当每个寄存器的位域结构体类型和共用体的定义都建立起来了,就可以定义这个寄存器类型了

mmbs 发表于 2017-10-23 22:04

寄存器文件结构体看着真是复杂。

51xlf 发表于 2017-10-23 22:13

C2000的开发都使用哪些资料?

i1mcu 发表于 2017-10-23 22:13

定义的这些地址岂不是更复杂了?

pmp 发表于 2017-10-23 22:13

位域中的内容也是存在顺序的

mmbs 发表于 2017-10-23 22:13

DSP对类型有什么要求?
页: [1]
查看完整版本: F28335的位域和寄存器结构的学习