SPRADK7 March   2026 TMS320F280039C

 

  1.   1
  2.   Abstract
  3.   Trademarks
  4. 1Introduction
  5. 2System Description
    1. 2.1 SPI Implementation
    2. 2.2 CLB Implementation
    3. 2.3 Software Changes
  6. 3Validation
  7. 4Summary
  8. 5References

Software Changes

Most of the software in the T-Format solution can be reused in the A-Format interface. Based on the above SPI and CLB implementation, there are changes in the software.

The first is the tformat_configureCLBLen() API. This function is used to configure the CLB counters with the proper number of transfer and receive clocks which may vary among different commands. In the A-Format CLB implementation (For CRC calculation), the CRC mask depends on the number of clocks of the encoder response, and hence two extra configurations are added to this API. The two lines configured COUNTER_1_MATCH_1 and COUNTER_1_MATCH_2 to trigger FSM_2 correctly and mark the CRC in the encoder response. Refer to Figure 2-5 for the effect of the configuration.

static inline void
tformat_configureCLBLen(uint16_t transmitClocks, uint16_t receiveClocks)
{
    CLB_writeInterface(PM_TFORMAT_CLB_BASE,
                        CLB_ADDR_COUNTER_1_MATCH1, transmitClocks);
    CLB_writeInterface(PM_TFORMAT_CLB_BASE,
                        CLB_ADDR_COUNTER_1_MATCH2, transmitClocks);
    CLB_writeInterface(PM_TFORMAT_CLB_BASE,
                        CLB_ADDR_HLC_R0, receiveClocks);


    // Below are the changes
    CLB_writeInterface(PM_TFORMAT_RX_CRC_BASE,
                       CLB_ADDR_COUNTER_1_MATCH1, receiveClocks - 9);
    CLB_writeInterface(PM_TFORMAT_RX_CRC_BASE,
                       CLB_ADDR_COUNTER_1_MATCH2, receiveClocks - 1);

    return;
}

The second change in the parameters that passed into the PM_tformat_setupCommand() function.

PM_tformat_setupCommandReadoutOrReset(uint16_t commandID0_1_2_3_7_8_C,
                              uint16_t tformatRXClocks,
                              uint16_t tformatRXFields,
                              uint16_t tformatTXClocks,
                              uint16_t tformatFIFOLevel)

The parameters include the frame data, the number of fields/clocks of transfer and receive data, and the FIFO LEVEL. These parameters are related to the interface protocol itself and affected by the FIFO splitting mentioned in the SPI implementation section. The below shows an example of how to calculate these parameters correctly. The example is based on the A-Format CDF0.

    #define AFORMAT_FRAME_LEN 9
    #define AFORMAT_TX_FRAMES 1
    #define AFORMAT_CFID0RES_RX_FIELDS 4

    uint16_t aformatTXClocks = (AFORMAT_TX_FRAMES*AFORMAT_FRAME_LEN);
    uint16_t aformatRXClocks = (2u*AFORMAT_CFID0RES_FIELDS*AFORMAT_FRAME_LEN);
    uint16_t aformatRXFields = (2u*AFORMAT_CFID0RES_FIELDS);
    uint16_t aformatFIFOLevel = (2u+2u*AFORMAT_CFID0RES_FIELDS);

Since the 18-bit field in A-Format is split into two 9-bit half-fields, when filling the FIFO, the most significant half is filled first, followed by the least significant half. Same to the T-Format solution, the rest of the TX FIFO are filled with 0xFFFF to keep the TX line high during receive. Below is an example of FIFO filling.

    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = cdf_msh;  // Change
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = cdf_lsh;  // Change

    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;

    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;

Finally, the decoding function PM_tformat_receiveDataID0_1_7_8_C() must be changed. This function reads the SPI buffer and decodes the raw data into a comprehensive data structure according to the interface protocol. An example of decoding response of CDF0 in the A-Format is given below. Note that the RX FIFO is also split.

void aformat_decode(){
    // for now, limited to the response of CF0
    uint16_t fullData[4] = {0};

    // full data: get rid of start bit 0 and end bit 1
    fullData[0] = (tformatRxData[3]<<7)|(tformatRxData[4]>>2);
    fullData[1] = (tformatRxData[5]<<7)|(tformatRxData[6]>>2);
    fullData[2] = (tformatRxData[7]<<7)|(tformatRxData[8]>>2);
    fullData[3] = (tformatRxData[9]<<7)|(tformatRxData[10]>>2);
    aformatData.fullData = ((uint64_t)fullData[0]<<48)|
                           ((uint64_t)fullData[1]<<32)|
                           ((uint64_t)fullData[2]<<16)|
                           ((uint64_t)fullData[3]);

    // crc data
    aformatData.crcIncludedData = aformatData.fullData>>8; //for cmd ID 0 only!!

    // crc recived from encoder
    aformatData.crcRecv = (aformatData.fullData & 0x00000000000000ff);

    // crc by CLB
    aformatData.crcByCLB = aformat_getRxCRCbyCLB();
    aformatData.crcBothRecvAndCLB = ((aformatData.crcRecv&0xff)<<8) | (aformatData.crcRecv&0xff);

    // single turn data fullData[16:34] = ST[0:18] (19bit)
    aformatData.stData = (aformatData.fullData & 0x0000ffffd0000000)>>29;
    aformatData.stData = (__flip32(aformatData.stData)>>13)&0x7FFFF;

    // multi turn data fullData[35:51] (17bit)
    aformatData.mtData = (aformatData.fullData & 0x000000001ffff000)>>12;
    aformatData.mtData = (__flip32(aformatData.mtData)>>15)&0x1FFFF;

    // err code
    aformatData.errCode = (aformatData.fullData & 0x000f000000000000)>>48;

    // command ID
    aformatData.cmdID =  (aformatData.fullData & 0x03e0000000000000)>>53;

    // encoder address
    aformatData.encoderAddress = (aformatData.fullData & 0x1c00000000000000)>>58;

    encoderStatus.position = (float)aformatData.stData/524288.0*360;
    encoderStatus.turns = aformatData.mtData;
}