SPRAA85E November   2005  – December 2017 SM320F2812 , SM320F2812-EP , TMS320F280021 , TMS320F280021-Q1 , TMS320F280023 , TMS320F280023-Q1 , TMS320F280023C , TMS320F280025 , TMS320F280025-Q1 , TMS320F280025C , TMS320F280025C-Q1 , TMS320F280040-Q1 , TMS320F280040C-Q1 , TMS320F280041 , TMS320F280041-Q1 , TMS320F280041C , TMS320F280041C-Q1 , TMS320F280045 , TMS320F280048-Q1 , TMS320F280048C-Q1 , TMS320F280049 , TMS320F280049-Q1 , TMS320F280049C , TMS320F280049C-Q1 , TMS320F2801 , TMS320F2801-Q1 , TMS320F2802 , TMS320F2802-Q1 , TMS320F28044 , TMS320F2806 , TMS320F2806-Q1 , TMS320F28062 , TMS320F28062-Q1 , TMS320F28062F , TMS320F28062F-Q1 , TMS320F28063 , TMS320F28064 , TMS320F28065 , TMS320F28066 , TMS320F28066-Q1 , TMS320F28067 , TMS320F28067-Q1 , TMS320F28068F , TMS320F28068M , TMS320F28069 , TMS320F28069-Q1 , TMS320F28069F , TMS320F28069F-Q1 , TMS320F28069M , TMS320F28069M-Q1 , TMS320F28075 , TMS320F28075-Q1 , TMS320F2808 , TMS320F2808-Q1 , TMS320F2809 , TMS320F2810 , TMS320F2810-Q1 , TMS320F2811 , TMS320F2811-Q1 , TMS320F2812 , TMS320F2812-Q1 , TMS320F28232 , TMS320F28232-Q1 , TMS320F28234 , TMS320F28234-Q1 , TMS320F28235 , TMS320F28235-Q1 , TMS320F28332 , TMS320F28333 , TMS320F28334 , TMS320F28335 , TMS320F28335-Q1 , TMS320F28374D , TMS320F28374S , TMS320F28375D , TMS320F28375S , TMS320F28375S-Q1 , TMS320F28376D , TMS320F28376S , TMS320F28377D , TMS320F28377D-EP , TMS320F28377D-Q1 , TMS320F28377S , TMS320F28377S-Q1 , TMS320F28379D , TMS320F28379D-Q1 , TMS320F28379S , TMS320R2811 , TMS320R2812

 

  1.   Programming TMS320x28xx and TMS320x28xxx Peripherals in C/C++
    1.     Trademarks
    2. Introduction
    3. Traditional #define Approach
      1.      Example 1. Traditional #define Macros
      2.      Example 2. Accessing Registers Using #define Macros
    4. Bit Field and Register-File Structure Approach
      1. 3.1 Defining A Register-File Structure
        1.       Example 3. SCI Register-File Structure Definition
        2.       Example 4. SCI Register-File Structure Variables
      2. 3.2 Using the DATA_SECTION Pragma to Map a Register-File Structure to Memory
        1.       Example 5. Assigning Variables to Data Sections
        2.       Example 6. Mapping Data Sections to Register Memory Locations
        3.       Example 7. Accessing a Member of the SCI Register-File Structure
      3. 3.3 Adding Bit-Field Definitions
        1.       Example 8. SCI Control Registers Defined Using Bit Fields
      4. 3.4 Using Unions
        1.       Example 9. Union Definition to Provide Access to Bit Fields and the Whole Register
        2.       Example 10. SCI Register-File Structure Using Unions
        3.       Example 11. Accessing Bit Fields in C/C++
    5. Bit Field and Register-File Structure Advantages
    6. Code Size and Performance Using Bit Fields
      1.      Example 12. TMS320x280x PCLKCR0 Bit-Field Definition
      2.      Example 13. Assembly Code Generated by Bit Field Accesses
      3.      Example 14. Optimization Using the .all Union Member
      4.      Example 15. Optimization Using a Shadow Register
    7. Read-Modify-Write Considerations When Using Bit Fields
      1.      Example 16. A Few Read-Modify-Write Operations
      2. 6.1 Registers That Hardware Can Modify During Read-Modify-Write Operations
        1. 6.1.1 PIEIFRx Registers
          1.        Example 17. Clearing PIEIFRx (x = 1, 2...12) Registers
        2. 6.1.2 GPxDAT Registers
          1.        Example 18. Read-Modify-Write Effects on GPxDAT Registers
          2.        Example 19. Using GPxSET and GPxCLEAR Registers
      3. 6.2 Registers With Write 1-to-Clear Bits.
        1.       Example 20. Read-Modify-Write Operation Inadvertently Modifies Write 1-to-Clear Bits (TCR[TIF])
        2.       Example 21. Using a Shadow Register to Preserve Write 1-to-Clear Bits
      4. 6.3 Register Bits Requiring a Specific Value
        1.       Example 22. Watchdog Check Bits (WDCR[WDCHK])
      5. 6.4 Read-Modify-Write Sensitive Registers
    8. Special Case Peripherals
      1. 7.1 eCAN Control Registers
        1.       Example 23. Invalid eCAN Control Register 16-Bit Write
        2.       Example 24. Using a Shadow Register to Force a 32-Bit Access
      2. 7.2 Byte Peripheral Registers
        1.       Example 25. Invalid Byte Peripheral Register Access
        2.       Example 26. Byte Peripheral Register Access Using “byte_peripheral” Attribute
    9. C2000 Peripheral Driver Library Approach
      1. 8.1 Using the Peripheral Driver Library
        1.       Example 27. SCI-A Driverlib Function Prototype
          1.        Example 28. SCI-A Configuration Using the Driverlib
      2. 8.2 Construction of a Driver Library Function
        1.       Example 29. SCI Register Description Header File (hw_sci.h)
          1.        Example 30. SCI Function Implementation
      3. 8.3 Peripheral Driver Library Advantages
    10. Code Size and Performance Using Driverlib
      1.      Example 31. Inlined ADC_readResult() Function Calls
      2.      Example 32. ADC Function Implementation to be Optimized
      3.      Example 33. Inlined ADC_setupSOC() Function Call
    11. 10 Comparing and Combining Approaches
      1.      Example 34. CPU Timer Bit-Field (Left) and Driverlib (Right) Disassembly Comparison
      2.      Example 35. ADC Bit-Field (Left) and Driverlib (Right) Disassembly Comparison
    12. 11 References
  2.   Revision History

Example 13. Assembly Code Generated by Bit Field Accesses

C-Source Code Generated Assembly Memory Instruction // Enable only 2801 Peripheral Clocks EALLOW; 3F82A7 EALLOW 3F82A8 MOVW DP,#0x01C0 SysCtrlRegs.PCLKCR0.bit.rsvd1 = 0; 3F82AA AND @28,#0xFFFC SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; 3F82AC AND @28,#0xFFFB SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; 3F82AE OR @28,#0x0008 SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 1; 3F82B0 OR @28,#0x0010 SysCtrlRegs.PCLKCR0.bit.rsvd2 = 0; 3F82B2 AND @28,#0xFFDF SysCtrlRegs.PCLKCR0.bit.SPICENCLK = 1; 3F82B4 OR @28,#0x0040 SysCtrlRegs.PCLKCR0.bit.SPIDENCLK = 1; 3F82B6 OR @28,#0x0080 SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1; 3F82B8 OR @28,#0x0100 SysCtrlRegs.PCLKCR0.bit.SPIBENCLK = 1; 3F82BA OR @28,#0x0200 SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1; 3F82BC OR @28,#0x0400 SysCtrlRegs.PCLKCR0.bit.SCIBENCLK = 0; 3F82BE AND @28,#0xF7FF SysCtrlRegs.PCLKCR0.bit.rsvd3 = 0; 3F82C0 AND @28,#0xCFFF SysCtrlRegs.PCLKCR0.bit.ECANAENCLK= 1; 3F82C2 OR @28,#0x4000 SysCtrlRegs.PCLKCR0.bit.ECANBENCLK= 0; 3F82C4 AND @28,#0x7FFF EDIS; 3F82C6 EDIS

NOTE

EALLOW and EDIS are macros defined in the C/C++ Header Files and Peripheral Examples. These macros expand to the EALLOW and EDIS assembly instructions.

The EALLOW protection mechanism prevents spurious CPU writes to several registers. Executing EALLOW permits the CPU to write freely to protected registers and executing EDIS protects them once more. For information on EALLOW protection and a list of protected registers, see the device-specific System Control and Interrupts Reference Guide or Technical Reference Manual (TRM).

To calculate how many cycles the code in Example 13 will take, you need to know how many wait states are required to access the PCLKCR0 register. Wait state information for all memory blocks and peripheral frames is listed in the device specific data manual. The PCLKCR0 register is in peripheral frame 2; this frame requires two wait states for a read access and no wait states for a write access. This means a read from PCLKCR0 takes three cycles total and a write takes one cycle. In addition, a new access to PCLKCR0 cannot begin until the previous write is complete. This built-in protection mechanism removes pipeline effects and makes sure operations proceed in the correct order; all of the peripheral registers have this protection. In Example 13, each access to the PCLKCR0 register will take six cycles; the pipeline phases are shown in Table 3.

Table 3. CPU-Pipeline Activity For Read-Modify-Write Instructions in Example 13

CPU-Pipeline Phase (1)
Read 1 - Read Begins Read 2 - Data Latched Execute - Value Modified Write - Value written Cycle
AND @28,#0xFFFC 1
AND @28,#0xFFFC 2
AND @28,#0xFFFC 3
AND @28,#0xFFFC 4
AND @28,#0xFFFC 5
AND @28,#0xFFFC 6
AND @28,#0xFFFB 7
AND @28,#0xFFFB 8
AND @28,#0xFFFB 9
AND @28,#0xFFFB 10
AND @28,#0xFFFB 11
AND @28,#0xFFFB 12
OR @28,#0x0008 13
OR @28,#0x0008 14
OR @28,#0x0008 15
OR @28,#0x0008 16
OR @28,#0x0008 17
OR @28,#0x0008 18
OR @28,#0x0010
etc...
For detailed CPU pipeline information, see theTMS320C28x CPU and Instruction Set Reference Guide (SPRU430).

When code size and cycle counts must be kept to a minimum, it is beneficial to reduce the number of instructions required to initialize a register to as few as possible. Here are some options for reducing code size:

  • Enable the compiler's optimizer:
  • As mentioned in Section 3.1, register-file variables are declared as volatile. For this reason, enabling the optimizer alone will not reduce the number of instructions. The keyword volatile alerts the compiler that the variable's value can change outside of the currently executing code. While removing the volatile keyword would reduce code size, it is not recommended. Removing volatile must be done with great care and only where the developer is certain doing so will not yield incorrect results.

  • Write to the complete register (.all union member):
  • The union definitions discussed in Section 3.4 allow access to either specific bit fields or to the entire register. When a write is performed to the entire register using the .all member of the union, code size is reduced. This method creates very efficient code as shown in Example 14. Using .all, however, makes the code both harder to write and harder to read. It is not immediately evident how different bit fields in the register are configured.