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.

Using FatFs to handle SD card with EK-TM4C123GXL

Other Parts Discussed in Thread: EK-TM4C123GXL, TM4C123GH6PM, TM4C123GH6PZ

For some time I have been trying to write in an SD card, using the EK-TM4C123GXL and CCS_6.1.2.00015.

Ti-RTOS has woked but i dont really want to use the SYS/BIOS part, so now I am trying to make work an aplication that use the FatFs APIs but is being really dificult and i would extremly appreciate your help to build it. Any advice is helpful.

My  host is windows 7 

Te Code I am trying to run is this:

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/ssi.h"
#include "ff.h"
#include "diskio.h"


FATFS sdVolume;
FIL logfile;
uint16_t fp;

//*****************************************************************************
//
// Configure the UART and its pins. This must be called before UARTprintf().
//
//*****************************************************************************
void
ConfigureUART(void)
{
//
// 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);

//
// Use the internal 16MHz oscillator as the UART clock source.
//
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

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

void fatalError(char errMessage[]){
UARTprintf(errMessage);
while(1);
}


//*****************************************************************************
//
// Main 'C' Language entry point.
//
//*****************************************************************************
int
main(void)
{
uint32_t ui32Data;

//
// Setup the system clock to run at 40 MHz from PLL with crystal reference
//
ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
SYSCTL_OSC_MAIN);

//
// Initialize the UART.
//
ConfigureUART();

//
// Print the welcome message to the terminal.
//
//UARTprintf("\033[2JNew example\n");
ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
SYSCTL_OSC_MAIN);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//UARTprintf("Configurando SPI\n");
ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);
ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);
ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2 );
SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1, SSI_MODE_MASTER, 10000, 16);
SSIEnable(SSI0_BASE);
UINT bw;

switch(f_mount(&sdVolume, "", 0)){
case FR_OK:
UARTprintf("SD Card mounted successfully\n");
break;
case FR_INVALID_DRIVE:
fatalError("ERROR: Invalid drive number\n");
break;
case FR_DISK_ERR:
fatalError("ERROR: DiskIO error - Check hardware!\n");
break;
case FR_NOT_READY:
fatalError("ERROR: Medium removal or disk_initialize\n");
break;
case FR_NO_FILESYSTEM:
fatalError("ERROR: No valid FAT volume on drive\n");
break;
default:
fatalError("ERROR: Something went wrong\n");
break;
}

if(f_open(&logfile, "PRUEBA.txt", FA_WRITE | FA_OPEN_ALWAYS) == FR_OK) { // Open file - If nonexistent, create
f_write(&logfile, "Texto de prueba\n", 16, &bw);
//UARTprintf("El archivo pesa: %u\n",logfile.fsize);
f_close(&logfile);
}


while(1)
{
ui32Data = 156;
SSIDataPut(SSI0_BASE, ui32Data);
while(SSIBusy(SSI0_BASE));

}

}

The problem i got are:

<Linking>

undefined first referenced
symbol in file
--------- ----------------
IntGPIOb ./startup_ccs.obj
MPU9150I2CIntHandler ./startup_ccs.obj
disk_initialize ./ff.obj
disk_ioctl ./ff.obj
disk_read ./ff.obj
disk_status ./ff.obj
disk_write ./ff.obj
get_fattime ./ff.obj

error #10234-D: unresolved symbols remain
error #10010: errors encountered during linking; "Comunic_SPI.out" not built

>> Compilation failure
gmake: *** [Comunic_SPI.out] Error 1
gmake: Target `all' not remade because of errors.

  • Hello Frank

    For using the FAT File System, the FSS pin must be configured as a GPIO. Also the change has to be made in the port driver under fat file system

    Also you need to include the fat file system files in your compilation flow which does not seem to be the case.,

    Regards
    Amit
  • Hello Amit!

    I got frustrated with FATFS because I never was able to see a response from the ssi pins I was trying to use, even when i declared them as GPIO and SSI. I had  a progress with ti-RTOS, to write and read the SD card, but seems imposible combine it with the TivaWare librarys I need to use. So I want to give FATFS another try.

    What i need to do is just log data obtained form the Sensor Hub Booster Pack into an SD using an EK-TM4C123G .  ¿Can you please give me an advise of what should i do to  finally acomplish?

    Thanks.

  • Hello Frank,

    Can you please share the project files that you had updated for the sd-card with EK-TM4C123GXL?

    Regards
    Amit
  • I have not updated any file.

    I tried to run a simple code on the sd_card example for de DK-TM4C123G, and move my conections on the EK-TM4C123G to be the same:

    // 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)

    But it did not work. 

    This is the code: 

    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_ssi.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "driverlib/ssi.h"
    #include "grlib/grlib.h"
    #include "utils/uartstdio.h"
    #include "ff.h"
    #include "diskio.h"
    
    
    FATFS sdVolume;
    FIL logfile;
    uint16_t fp;
    
    void ConfigureUART(void){
    
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    	GPIOPinConfigure(GPIO_PA0_U0RX);
    	GPIOPinConfigure(GPIO_PA1_U0TX);
    	ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    void fatalError(char errMessage[]){
    	UARTprintf(errMessage);
    	while(1);
    }
    
    int main(void){
    
    	ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    	ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    
    	ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);
    
    	ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5);
    	ROM_SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 4000, 8);
    
    	ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0xFF);
    
    
    
    
    	ConfigureUART();
    	UARTprintf("Programa SD\n");
    
    	UINT bw;
    
    	switch(f_mount( &sdVolume,"",0)){
    		case FR_OK:
    			UARTprintf("SD Card mounted successfully\n");
    			break;
    		case FR_INVALID_DRIVE:
    			fatalError("ERROR: Invalid drive number\n");
    			break;
    		case FR_DISK_ERR:
    			fatalError("ERROR: DiskIO error - Check hardware!\n");
    			break;
    		case FR_NOT_READY:
    			fatalError("ERROR: Medium removal or disk_initialize\n");
    			break;
    		case FR_NO_FILESYSTEM:
    			fatalError("ERROR: No valid FAT volume on drive\n");
    			break;
    		default:
    			fatalError("ERROR: Something went wrong\n");
    			break;
    	}
    
    	if(f_open(&logfile, "PRUEBA.txt", FA_WRITE | FA_OPEN_ALWAYS) == FR_OK) {	// Open file - If nonexistent, create
    		f_write(&logfile, "Texto de prueba\n", 16, &bw);
    		UARTprintf("El archivo pesa: %u\n",logfile.f_size);
    		f_close(&logfile);
    		}
    	while(1);
    	}
    

  • Hello Frank

    The pin FSS must be configured as a GPIO. So instead of performing ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS); you need to configure it as ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);

    However the fat file system port files should have taken care of it as well.

    Can you check and confirm if the GPIO A3 is configured for output function and A2, A4, A5 are SSI functions. Also when it fails the communication, the pin A2 should read as logic 1.

    Regards
    Amit
  • Hello Amit.

    So the comunication failed, the pin A2 shows logic 1.

    I added the lines you suggested in both files.

    The sd_card.c

    int main(void){
    
    	ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_2);
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_4);
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_5);
    
    	ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    	ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);
    
    	ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5);
    	ROM_SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 4000, 8);
    

    And the mmc-dk-tm4c123g.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(SDC_GPIO_SYSCTL_PERIPH);
    
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_2);
        	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
        	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_4);
        	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_5);
        /*
         * 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.
         */
        MAP_GPIOPadConfigSet(SDC_GPIO_PORT_BASE, SDC_SSI_RX, GPIO_STRENGTH_4MA,
                             GPIO_PIN_TYPE_STD_WPU);
        MAP_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_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;
    }
    

    ¿Is it correct the way i did it??

    The f_mount API still sending FR_INVALID_DRIVE

    Thanks

  • I realized the only problem i had, to make it work, was change the target configuration of sd_card project, from TM4C123GH6PZ to TM4C123GH6PM, now the comunication between the SD and my Launch Pad is going on well.
  • Hello Frank

    The launchpad has the TM4C123GH6PM device and not the TM4C123GH6PZ.

    Regards
    Amit
  • I am really thankful

    So , i have been working to log data from the sensor hub booster pack to the SD, but i have had problems with the f_write function, it does not accept the variable that I want to register, it shows this warning:
    #169-D argument of type "char" is incompatible with parameter of type "const void *"

    I did not found anything useful to change the "char" variable to "const void"

    Besides I tried to use f_puts and fputc but it gives me the unresolved simbol error. ¿Can you help me a little more please?
  • Hello Frank,

    You may want to refer to the following application note (It is for TM4C129x but shows how file write can be used).

    www.ti.com/.../spma076.pdf

    You can try to typecast the variable, that is creating the issue.

    Regards
    Amit
  • I cant find something useful for my problem in the pdf you suggested me. :(
  • Hello Frank,

    Download the project collateral as given in the document (Page-1)

    Regards
    Amit