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.

SD Card on TM4C1294XL Launchpad

Other Parts Discussed in Thread: EK-TM4C1294XL, TM4C1294NCPDT

I am attemping to port the sd_card code from the DK-TM4C123G example to the EK-TM4C1294XL board to read/write from a microSD card. I have used this post as a reference. I have been semi-successful in communicating with the microSD card. I have been able to display a list of the files in the root directory as well as write a file to the card and read the file back. So I know that my hardware connections and pin assignments are correct or nearly so.

The issues is that the connection is very unreliable. I will be able to successfully run my program, go off to lunch, then come back and it no longer works. There is no rhyme or reason when it will work.

My main method is given below. The below example reads the files/folders in the top level directory of the SD card, writes a file, then reads that file back.

int main(void) {
    FRESULT iFResult;

    // Enable lazy stacking for interrupt handlers.     This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    ROM_FPULazyStackingEnable();

    // Run from the PLL at 120 MHz.
    systemClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    	SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

    // Configure SysTick for a 100Hz interrupt.
    ROM_SysTickPeriodSet(systemClock / 100);
    ROM_SysTickEnable();
    ROM_SysTickIntEnable();

    // Enable interrupts
    ROM_IntMasterEnable();

    // Enable the GPIO Peripheral used by the UART.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    // Enable UART0
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    // Configure GPIO Pins for UART mode.
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    // Initialize the UART for console I/O.
    UARTStdioConfig(0, 115200, systemClock);

    UARTprintf("\n\nSD Card Example Program\n");

    // Mount the file system, using logical disk 0.
    iFResult = f_mount(0, &fatFS);
    if(iFResult != FR_OK) {
        UARTprintf("f_mount error: %s\n", StringFromFResult(iFResult));
        return(1);
    }
    else {
    	UARTprintf("SD card mounted.\n");
    }

    iFResult = f_opendir(&dir, path);

    // Check for error and return if there is a problem.
    if(iFResult != FR_OK) {
        // Ensure that the error is reported.
        UARTprintf("Error from SD Card: %s\n",StringFromFResult(iFResult));
        return(iFResult);
    }
    else {
    	UARTprintf("Root dir opened.\n");
    }

    // Enter loop to enumerate through all directory entries.
    for(;;) {
        // Read an entry from the directory.
        iFResult = f_readdir(&dir, &fileInfo);

        // Check for error and return if there is a problem.
        if(iFResult != FR_OK) {
        	UARTprintf("Error from SD Card: %s\n",StringFromFResult(iFResult));
            return(iFResult);
        }

        // If the file name is blank, then this is the end of the listing.
        if(!fileInfo.fname[0]) {
            break;
        }

        // Print file names
        UARTprintf("(%c) %s\n", (fileInfo.fattrib & AM_DIR) ? 'D' : 'F',fileInfo.fname);
    }

    UARTprintf("Done");

    FIL fil;
	uint32_t count = 8*512;
	iFResult = f_open(&dir, "testfile.txt", FA_CREATE_NEW|FA_WRITE);
	SysCtlDelay(SysCtlClockGet()/3);
	if(iFResult != FR_OK) {
		UARTprintf("fresult: %s\n", StringFromFResult(iFResult));
	}
	else {
		UARTprintf("\n Opened SD card\n");
	}

	iFResult = f_write(&fil, "Hello world", 11, &count);
	if(iFResult != FR_OK) {
		UARTprintf("Error writing to file: %s\n", StringFromFResult(iFResult));
	}
	iFResult = f_close(&fil);
	f_mount(0, NULL);
}

My pin assignments in mmc-ek-tm4c1294xl.c. I am using SSI2 which is pins D0-D3 on the TM4C1294NCPDT

/* Peripheral definitions for EK-TM4C129EXL board */
/* SSI port */
#define SDC_SSI_BASE            	SSI2_BASE
#define SDC_SSI_SYSCTL_PERIPH   	SYSCTL_PERIPH_SSI2
/* GPIO for SSI pins */
/* CLK pin */
#define SDC_SSI_CLK_GPIO_PORT_BASE  GPIO_PORTD_BASE
#define SDC_SSI_CLK             	GPIO_PIN_3
/* TX pin */
#define SDC_SSI_TX_GPIO_PORT_BASE   GPIO_PORTD_BASE
#define SDC_SSI_TX              	GPIO_PIN_1
/* RX pin */
#define SDC_SSI_RX_GPIO_PORT_BASE   GPIO_PORTD_BASE
#define SDC_SSI_RX              	GPIO_PIN_0
/* CS pin */
#define SDC_SSI_FSS_GPIO_PORT_BASE  GPIO_PORTD_BASE
#define SDC_SSI_FSS             	GPIO_PIN_2

My power_on method in mmc-ek-tm4c1294xl.c

static
void power_on (void)
{
    /*
     * This doesn't really turn the power on, 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(SYSCTL_PERIPH_GPIOD);

    // Configure GPIO Pins for SSI mode.
    ROM_GPIOPinConfigure(GPIO_PD0_SSI2XDAT1);
    ROM_GPIOPinConfigure(GPIO_PD1_SSI2XDAT0);
    ROM_GPIOPinConfigure(GPIO_PD2_SSI2FSS);
    ROM_GPIOPinConfigure(GPIO_PD3_SSI2CLK);

    /*
     * 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_SSI_TX_GPIO_PORT_BASE, SDC_SSI_TX);
    ROM_GPIOPinTypeSSI(SDC_SSI_RX_GPIO_PORT_BASE, SDC_SSI_RX);
    ROM_GPIOPinTypeSSI(SDC_SSI_CLK_GPIO_PORT_BASE, SDC_SSI_CLK);
    ROM_GPIOPinTypeGPIOOutput(SDC_SSI_FSS_GPIO_PORT_BASE, SDC_SSI_FSS);

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

    /* Configure the SSI2 port */
    ROM_SSIConfigSetExpClk(SDC_SSI_BASE, systemClock,
                           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();

    PowerFlag = 1;
}
  • Hello Daniel

    Flaky communication indicates to

    1. Poor VCC and GND connection between the two boards
    2. Long wires if used between off board devices.

    Regards
    Amit
  • Amit,

    I have shortened the wires and made sure all the connections are solid. I have even tried using a separate power supply for the SD card in case the 3.3V from the launchpad wasn't sufficient.

    Do you have any other suggestions?

    Thank you,
    Daniel
  • Hi Daniel,

    Check if the value of systemClock is 120000000.

    systemClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

    How do you pass the value of systemClock from int main(void) to static void power_on (void) to this function below.

    ROM_SSIConfigSetExpClk(SDC_SSI_BASE, systemClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 400000, 8);

    - kel

  • How could the frequency be "set wrong" when the poster reports his success at:

    • reading a list of files
    • writing a file to the card
    • reading that file from the card

    Is your sense that the MCU's system clock is changing?   Have you ever heard of that, here?   (i.e. it may be set improperly - but I cannot recall drift or frequency shift!)

    It would be interesting to learn "how" you came to your "System Clock setting as villain" conclusion...

    I suggest (instead):

    • replacement of that SD card w/another
    • replacement of your board w/a second
    • close inspection of the SD socket and its soldering
    • reducing system clock by a factor of 2 - and seeing if this cures  (it may be that you're at a "ragged edge" timing wise - slowing may solve)

  • cb1,

    Pardon me. This is one of those I just woke up replies. Disregard my reply.

    - kel
  • A not too "guruian" pair of postings - some would say...
  • Markel,

    The top of the file contains

    /* must be supplied by the application */
    extern uint32_t systemClock;

    so the value of the clock is correct.

    Dan
  • cb1,

    I tried a second SD card, rechecked all the solder joints and adjusted the system clock as you suggested. I do not have a second board on hand to test.

    Dan
  • Here is some more information on the issue. I discovered something extremely peculiar that I can't quite put my finger on. Here is the stack at the location of the error:

    The code in rcvr_datablock() is

    /*-----------------------------------------------------------------------*/
    /* Receive a data packet from MMC                                        */
    /*-----------------------------------------------------------------------*/
    
    static
    BOOL rcvr_datablock (
        BYTE *buff,            /* Data buffer to store received data */
        UINT btr            /* Byte count (must be even number) */
    )
    {
        BYTE token;
    
    
        Timer1 = 100;
        do {                            /* Wait for data packet in timeout of 100ms */
            token = rcvr_spi();
        } while ((token == 0xFF) && Timer1);
        if(token != 0xFE) return FALSE;    /* If not valid data token, retutn with error */
    
        do {                            /* Receive the data block into buffer */
            rcvr_spi_m(buff++);
            rcvr_spi_m(buff++);
        } while (btr -= 2);
        rcvr_spi();                        /* Discard CRC */
        rcvr_spi();
    
        return TRUE;                    /* Return with success */
    }

    In the second do loop, btr starts at 512. Once it gets down to 16, rcvr_spi_m() is called and succesfully executes. Once it exits the method, my program jumps to line 237 in the same file (it is always this line) in the middle of the power_on() method and the FaultISR gets triggered. The NVIC_FAULT_STAT has the NVIC_FAULT_STAT_INVSTAT flag raised. The NVIC_FAULT_ADDR is 0xE000EDF8.

    What could cause my code to jump to a seemingly random line?

  • Hello Daniel,

    Could it be a stack overflow? Did you increase the size of the stack and also check with the existing code how the stack pointer progresses over time?

    Regards
    Amit
  • Amit,

    I set a hardware watchpoint to '__stack' and it did not trigger. I increased the stack size anyway and that did not solve the problem.

    Dan
  • Amit,

    My apologies. Although I modified the stack size at first the change did not seem to stick the first time around. Increasing the stack size from 512 to 1024 did solve the problem and I am now able to reliably communicate with both of my SD cards. Thank you so much!

    Regards,

    Dan
  • Hello Dan,

    My worry is that over a longer period of time the stack would cross 1024. You would need to see why SP is getting PUSH-ed more than POP-ed

    Regards
    Amit
  • Amit Ashara said:
    You would need to see why SP is getting PUSH-ed more than POP-ed.   

    Bravo Amit, while poster (seems) satisfied - a weakness appears to have been noted - and even a "higher wall" may not deflect all attackers...

  • Amit,

    Excellent point, I will look into the issue.

    Best,
    Dan
  • Hello Daniel,

    Thank you for following up on the same. Thanks cb1 for emphasizing the point

    Regards
    Amit