TM4C123GH6PM: N/A

Part Number: TM4C123GH6PM

Tool/software:

I'm trying to implement SSI0 (TM4C123 as a master) to communicate between the MCU and two Si834x isolated smart switches (as slaves) on CCS. 

Before implementing the actual SPI protocol between them, I tried to observe the SSI0 timing diagram to verify that the data bytes are transmitting correctly. Basically, I'm sending 10 bytes and using logic analyzer (logic pro 8) to verify the data being transmitted.  

However, it seems like there's an error every three bytes (1st, 4th, 7th, 10th byte). What is causing the issue and how should I fix it?

Also, I should mention that if I change the system clock frequency or bitrate, the error location changes but it still occurs once every three bytes (EX: errors happen at 2nd, 5th, 8th byte or 3rd, 6th, 9th byte...etc.)

Here is the code

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

#include "Si834x.h"

#define NUM_SSI_DATA 10 //10 data bytes

void InitSPI(void) {
    // Enable peripherals for SSI0 and GPIO Port A
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);                 //Enable SSI0 peripherals
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);                //Enable GPIO Port A for SSI0

    // Configure SSI0 pins
    //      PA2 - SSI0CLK
    //      PA3 - SSI0Fss (Manual control)
    //      PA4 - SSI0Rx (MISO)
    //      PA5 - SSI0Tx (MOSI)
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5);

    // Set drive strength and pin type for SSI pins (8mA drive strength)
    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_5, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD);


    // Configure and enable the SSI port for SPI master mode
    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 1000000, 8);   //SSI_FRF_MOTO_MODE_3 -> Data captured on the second clock edge & Steady state High for SSI0Clk, 1 Mbps, 8 bits
    SSIEnable(SSI0_BASE);                                                                                //Enable the SSI0 module

    // Configure PA3 for manual CS control
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); // Set CS High initially
    SysCtlDelay(500);
}

void SPIWrite(uint8_t data) {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0);          // Pull CS Low to start communication
    SSIDataPut(SSI0_BASE, data);                           // Transmit data
    while (SSIBusy(SSI0_BASE)) {}                          // Wait until the transmission is complete
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); // Pull CS High to end communication
   // SysCtlDelay(10);
}

int main(void) {
    uint32_t pui32DataTx[NUM_SSI_DATA];
//    uint32_t pui32DataRx[NUM_SSI_DATA];
    uint32_t ui32Index;

//    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // System clock: 80MHz
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // System clock: 16MHz

    //Configure PE2 for OE and set it High
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)) {}
    GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_2);
    GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_2, GPIO_PIN_2);

    InitSPI();

    // Clear any residual data from the SSI port
    //while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx[0])) {}

    pui32DataTx[0] = 0x01;
    pui32DataTx[1] = 0x12;
    pui32DataTx[2] = 0x23;
    pui32DataTx[3] = 0x34;
    pui32DataTx[4] = 0x45;
    pui32DataTx[5] = 0x56;
    pui32DataTx[6] = 0x78;
    pui32DataTx[7] = 0x89;
    pui32DataTx[8] = 0x9A;
    pui32DataTx[9] = 0xAB;

    for (ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++) {
        SPIWrite(pui32DataTx[ui32Index]);
    }

    return 0;
}

Here is the timing diagram (Channel 4 is CS)

  • I forgot to mention this, but this error only happens when I connect the logic analyzer to the slave (Si834x). If I connect the logic analyzer to the microcontroller, the transmitted data are correct.

  • Hi,

    I forgot to mention this, but this error only happens when I connect the logic analyzer to the slave (Si834x). If I connect the logic analyzer to the microcontroller, the transmitted data are correct.

      You are saying the waveform is correct when you connect the LA to the MCU. In this case, the MCU is correctly transmitting the data. 

      How are you connecting between the master and the slave? Are they far from each other with long wires? 

      Looking at your waveform, you are not skipping a data every 3 bytes, but rather the LA is capturing a wrong data instead. For example, you are shifting out 0x12, 0x23 and then 0x34. However, the LA is capturing 0x12, 0x23 and then 0x38. It is 0x34 vs 0x38 with one bit difference. Next you shift 0x45, 0x56, then 0x78. But this time, the LA captures 0x45, 0x56 and 0x70. Again, it is 0x78 vs 0x70 with one bit difference. This suggests to me some timing issue such as that the data from the MCU is not meeting the setup time of the capturing edge on the LA. If you are in MODE 3 then you need to make sure LA is setup to sample at the correct edge and phase. I will suggest you use MODE 0 which should be the default by most LA. You can use the scope to better view if the timing is met or not. Again, if you have a long wire or if perhaps the MCU, the slave and the LA are not on common ground, it is possible the reason for not sampling correct data. 

  • Hello,

    Thank you for your suggestions. The issue was that I was reading the output from MOSI_THRU of the slave, not from the MOSI pin directly from the TM4C. Si834x datasheet says that the MOSI_THRU and MOSI are two different pins and output different signals.