This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C1290NCPDT: Tiva Problem with 'legacy SPI' migrating working code from TM4c123g to TM4c1290, FatFS throws FR_NOT_READY, likely a SSI/SPI config problem

Part Number: TM4C1290NCPDT
Other Parts Discussed in Thread: TM4C123GH6PM, , EK-TM4C1294XL, SYSCONFIG, TM4C1294NCPDT

Tool/software:

In an existing mature code base that runs on TM4C123GH6PM and TM4C123GHPGE, all 4 SSI are used.  

We are adding support for TM4C1290NCPDT.  UART0, I2C0 are working but SSI0 which is used for microSD card / FatFS is not.

Looking at the Tiva Migration doc: https://www.ti.com/lit/an/spma065/spma065.pdf, nothing stands out with respect to SSI0 other than PA4/PA5 TX/RX roles are swapped between 123g and 1290N.

Single stepping the call stack:

-  fresult = f_opendir(&g_sDirObject, g_cCwdBuf);      calls disk_initialize (SPI)  (in microsd.c)

 - res = find_volume(&fs, &path, 0);  ultimately returns FR_NOT_READY.   find_volume calls disk_initialize

 -  stat = disk_initialize(fs->drv); /* Initialize the physical drive */     disk_initialize calls power_on which sets up the SSI.  See below.

Legacy SPI mapping:

123G     MISO=RX=PA4=SSI0_MISO         MOSI=TX=PA5=SSI0_MOSI           CLK=PA2=SSI0_CLK       CS=PA3

1290:     MISO=RX=PA5=SSI0_DAT1         MOSI=TX=PA4=SSI0_DAT0           CLK=PA2=SSI0_CLK        CS=PA3

I'd like to know if I'm missing something with respect to SSI0 migrating code from TM4c123g to TM4c1290n?

Thanks

In diskio.c, the platform bindings and SSI setup:

#ifdef PART_TM4C1290NCPDT
/* Peripheral definitions for TM4c1290N base serlog_msc3 board */
// SSI port
#define SDC_SSI_BASE SSI0_BASE
#define SDC_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI0

// GPIO for SSI pins
#define SDC_GPIO_PORT_BASE GPIO_PORTA_BASE
#define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOA
#define SDC_SSI_CLK GPIO_PIN_2
#define SDC_SSI_TX GPIO_PIN_4 //NOTE: RX/TX swapped vs TM4c123g per www.ti.com/.../spma065.pdf
#define SDC_SSI_RX GPIO_PIN_5
#define SDC_SSI_FSS GPIO_PIN_3
#define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK | SDC_SSI_FSS)

#else
/* Peripheral definitions for TM4C123G board */
// SSI port
#define SDC_SSI_BASE SSI0_BASE
#define SDC_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI0

// GPIO for SSI pins
#define SDC_GPIO_PORT_BASE GPIO_PORTA_BASE
#define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOA
#define SDC_SSI_CLK GPIO_PIN_2
#define SDC_SSI_TX GPIO_PIN_5
#define SDC_SSI_RX GPIO_PIN_4
#define SDC_SSI_FSS GPIO_PIN_3
#define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK | SDC_SSI_FSS)

#endif

static
void power_on (void)
{
/*
* This doesn't really turn the power on unless the hardware supports it, but initializes the
* SSI port and pins needed to talk to the card.
*/


/* Enable the peripherals used to drive the SDC on SSI */
ROM_SysCtlPeripheralEnable(SDC_SSI_SYSCTL_PERIPH);
ROM_SysCtlPeripheralEnable(SDC_GPIO_SYSCTL_PERIPH);

/*
* Configure the appropriate pins to be SSI instead of GPIO. The FSS (CS)
* signal is directly driven to ensure that we can hold it low through a
* complete transaction with the SD card.
*/
ROM_GPIOPinTypeSSI(SDC_GPIO_PORT_BASE, SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK);
ROM_GPIOPinTypeGPIOOutput(SDC_GPIO_PORT_BASE, SDC_SSI_FSS);

/*
* Set the SSI output pins to 4MA drive strength and engage the
* pull-up on the receive line.
*/
ROM_GPIOPadConfigSet(SDC_GPIO_PORT_BASE, SDC_SSI_RX, GPIO_STRENGTH_4MA,
GPIO_PIN_TYPE_STD_WPU);
ROM_GPIOPadConfigSet(SDC_GPIO_PORT_BASE, SDC_SSI_CLK | SDC_SSI_TX | SDC_SSI_FSS,
GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);

/* Configure the SSI0 port */
// ROM_SSIConfigSetExpClk(SDC_SSI_BASE, ROM_SysCtlClockGet(),
// SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 400000, 8);
ROM_SSIConfigSetExpClk(SDC_SSI_BASE, g_ui32SysClock, //ROM_SysCtlClockGet() is not available on TM4C1290
SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 400000, 8);
ROM_SSIEnable(SDC_SSI_BASE);

/* Set DI and CS high and apply more than 74 pulses to SCLK for the card */
/* to be able to accept a native command. */
send_initial_clock_train();

/*-----------------------------------------------------------------------*/
/* Send 80 or so clock transitions with CS and DI held high. This is */
/* required after card power up to get it into SPI mode */
/*-----------------------------------------------------------------------*/
static
void send_initial_clock_train(void)
{
unsigned int i;
uint32_t ui32Dat;

/* Ensure CS is held high. */
DESELECT();

/* Switch the SSI TX line to a GPIO and drive it high too. */
ROM_GPIOPinTypeGPIOOutput(SDC_GPIO_PORT_BASE, SDC_SSI_TX);
ROM_GPIOPinWrite(SDC_GPIO_PORT_BASE, SDC_SSI_TX, SDC_SSI_TX);

/* Send 10 bytes over the SSI. This causes the clock to wiggle the */
/* required number of times. */
for(i = 0 ; i < 10 ; i++)
{
/* Write DUMMY data. SSIDataPut() waits until there is room in the */
/* FIFO. */
ROM_SSIDataPut(SDC_SSI_BASE, 0xFF);

/* Flush data read during data write. */
ROM_SSIDataGet(SDC_SSI_BASE, &ui32Dat);
}

/* Revert to hardware control of the SSI TX line. */
ROM_GPIOPinTypeSSI(SDC_GPIO_PORT_BASE, SDC_SSI_TX);
}

  • Hi,

      At a high level, I don't see you configure the pinmux. I would expect to see GPIOPinConfigure() that is used to configure pins for SSI. See below example code which I don't see in your code unless they are written somewhere else in your code that is not shown here. 

    MAP_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    MAP_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    MAP_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
    MAP_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);

    I strongly suggest you run the example in C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\ssi_master_slave_xfer. This example uses SSI0 as master and SSI1 as a slave. Run the example and it should work out of box. This way you can compare the register settings on GPIO and SSI0 modules between the example and your code. Later you can customize the drive strength setting as I see you use 4mA rather than 2mA as the default by TivaWare library. 

    If you have a scope or a logic analyzer, it will be a handy tool to know if the signals wiggling on the SSI0 pins. 

  • Thanks for the reply.   I've use the SysConfig tool to generate the pinmux (forgot to add that to the post) and populated those settings into init_SDcard (microsd.c)

    I'm using CCS v12 and I have a custom 1290 board.    I just ordered the 1294 launchpad and I'll try the example you suggested.   Here's the code for both 1290 and 123g.   I didn't put testpoints for easy spi access, but it's on my list to get my saleae logic attached and look at the signals.

    #ifdef PART_TM4C1290NCPDT
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); //(already done in init_TM4C1290NCPDT_128pin.c
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //

    // Configure the pin muxing (PA4/PA5 are swapped from TM4c123g, confusing!)
    ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK); // Configure the GPIO Pin Mux for PA2 for SSI0CLK
    ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS); // Configure the GPIO Pin Mux for PA3 for SSI0FSS
    ROM_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); // Configure the GPIO Pin Mux for PA5 for SSI0XDAT1 - MISO, was GPIO_PA4_SSI0RX
    ROM_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); // Configure the GPIO Pin Mux for PA4 for SSI0XDAT0 - MOSI, was GPIO_PA5_SSI0TX

    // Configure the GPIO settings for the SSI pins. (already done in init_)
    ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);

    // Configure and enable the SSI port for SPI master mode.
    //MOTO_MODE_0 is best for SDCards.
    ROM_SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
    SSI_MODE_MASTER, 1000000, 8);
    ROM_SSIEnable(SSI0_BASE);

    // Flush receive FIFO before starting to talk to uSDCard.
    while(ROM_SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx[0]))
    {
    ;
    }
    #endif

    #ifdef PART_TM4C123GH6PM
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    // Configure the pin muxing
    ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);
    ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);

    // Configure the GPIO settings for the SSI pins.
    ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);

    // Configure and enable the SSI port for SPI master mode.
    //MOTO_MODE_0 is best for SDCards.
    ROM_SSIConfigSetExpClk(SSI0_BASE, ROM_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
    SSI_MODE_MASTER, 1000000, 8);
    ROM_SSIEnable(SSI0_BASE);

    // Flush receive FIFO before starting to talk to SDCard.
    while(ROM_SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx[0]))
    {
    ;
    }
    #endif

  • Hi Pentleman,

      SSI0 pinmuxing is the same between TM4C1290NCPDT and TM4C1294NCPDT. You should be able to run the example on your custom board. 

      Another simpler SSI0 example can be found at C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\ssi\spi_master.c. This example is common for both TM4C123 and TM4C129. This example looks somewhat similar to what you pasted above. I guess you have seen this example already. If not, take a look. 

  • Problem found!   In reviewing the schematic with another engineer, it was found the SSI0 Chip Select was not connected to the microSD card.   All is working now.   Thanks for the support.