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.

Compiler/TM4C123GH6PZ: Problem of writing data to micro SD card

Part Number: TM4C123GH6PZ

Tool/software: TI C/C++ Compiler

Hi sir,

I am Facing lots of issue while interfacing SD card with TM4C123. I am new to SD card programming, If any issue is there please let me know.

1.I am trying to display the data in UART terminal. I was getting garbage values in my terminal window. Kept  the program in debug mode and checked getting the correct data in the watch window. I am not understanding  why in PC terminal garbage values are coming.The baud rate in both program and the terminal window is same.

2. Next issue I was facing inside the disk initialisation condition, the program is continuously running in the given below section and it is not executing further step. 

static
BYTE wait_ready (void)
{
BYTE res;


Timer2 = 50; /* Wait for ready in timeout of 500ms */
rcvr_spi();
do
res = rcvr_spi();
while ((res != 0xFF) && Timer2);

return res;
}

where in res I am getting zero continouosly.

Given below is the complete code.

#include "stdint.h"
#include "stdbool.h"
#include "string.h"
#include "stdio.h"
#include "inc/hw_memmap.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "utils/ustdlib.h"
#include "third_party/fatfs/src/ff.h"
#include "third_party/fatfs/src/diskio.h"
#include "inc/hw_nvic.h"
#include "inc/hw_ints.h"


#include "third_party/fatfs/port/mmc-dk-tm4c123g.c" 
//*****************************************************************************
//
// Defines the size of the buffers that hold the path, or temporary data from
// the SD card.  There are two buffers allocated of this size.  The buffer size
// must be large enough to hold the longest expected full path name, including
// the file name, and a trailing null character.
//
//
// The following are data structures used by FatFs.
//
//*****************************************************************************
static FATFS g_sFatFs;    /* Work area (File system object structure (FATFS)) for logical drive */
//static DIR g_sDirObject;  /* Directory object structure (DIR) */
//static FILINFO g_sFileInfo; /* File status structure (FILINFO) */
//static FIL g_sFileObject;   /* File object structure (FIL) */

extern void power_on (void);
//*****************************************************************************
//
// A structure that holds a mapping between an FRESULT numerical code, and a
// string representation.  FRESULT codes are returned from the FatFs FAT file
// system driver.
//
//*****************************************************************************
typedef struct
{
	FRESULT iFResult;  /* File function return code (FRESULT) */
	char *pcResultStr;
}
tFResultString;

//*****************************************************************************
//
// A macro to make it easy to add result codes to the table.
//
//*****************************************************************************
#define FRESULT_ENTRY(f)        { (f), (#f) }   //(stringnizing)convert a macro argument into a string constant(#f) in macro definition

//*****************************************************************************
//
// A table that holds a mapping between the numerical FRESULT code and it's
// name as a string.  This is used for looking up error codes for printing to
// the console.
//
//*****************************************************************************
tFResultString g_psFResultStrings[] =
{
		FRESULT_ENTRY(FR_OK),                /* (0) Succeeded */
		FRESULT_ENTRY(FR_DISK_ERR),          /* (1) A hard error occurred in the low level disk I/O layer */
		FRESULT_ENTRY(FR_INT_ERR),           /* (2) Assertion failed */
		FRESULT_ENTRY(FR_NOT_READY),         /* (3) The physical drive cannot work */
		FRESULT_ENTRY(FR_NO_FILE),           /* (4) Could not find the file */
		FRESULT_ENTRY(FR_NO_PATH),           /* (5) Could not find the path */
		FRESULT_ENTRY(FR_INVALID_NAME),      /* (6) The path name format is invalid */
		FRESULT_ENTRY(FR_DENIED),            /* (7) Access denied due to prohibited access or directory full */
		FRESULT_ENTRY(FR_EXIST),             /* (8) Access denied due to prohibited access */
		FRESULT_ENTRY(FR_INVALID_OBJECT),    /* (9) The file/directory object is invalid */
		FRESULT_ENTRY(FR_WRITE_PROTECTED),   /* (10) The physical drive is write protected */
		FRESULT_ENTRY(FR_INVALID_DRIVE),     /* (11) The logical drive number is invalid */
		FRESULT_ENTRY(FR_NOT_ENABLED),       /* (12) The volume has no work area */
		FRESULT_ENTRY(FR_NO_FILESYSTEM),     /* (13) There is no valid FAT volume */
		FRESULT_ENTRY(FR_MKFS_ABORTED),      /* (14) The f_mkfs() aborted due to any parameter error */
		FRESULT_ENTRY(FR_TIMEOUT),           /* (15) Could not get a grant to access the volume within defined period */
		FRESULT_ENTRY(FR_LOCKED),            /* (16) The operation is rejected according to the file sharing policy */
		FRESULT_ENTRY(FR_NOT_ENOUGH_CORE),   /* (17) LFN working buffer could not be allocated */
		FRESULT_ENTRY(FR_TOO_MANY_OPEN_FILES), 	/* (18) Number of open files > _FS_SHARE */
		FRESULT_ENTRY(FR_INVALID_PARAMETER),    /* (19) Given parameter is invalid */
};

//*****************************************************************************
//
// A macro that holds the number of result codes.
//
//*****************************************************************************
#define NUM_FRESULT_CODES       (sizeof(g_psFResultStrings) /                 \
		sizeof(tFResultString))


//*****************************************************************************
//
// This function returns a string representation of an error code that was
// returned from a function call to FatFs.  It can be used for printing human
// readable error messages.
//
//*****************************************************************************
const char * StringFromFResult(FRESULT iFResult)
{
	uint_fast8_t ui8Idx;

	//
	// Enter a loop to search the error code table for a matching error code.
	//
	for(ui8Idx = 0; ui8Idx < NUM_FRESULT_CODES; ui8Idx++)
	{
		//
		// If a match is found, then return the string name of the error code.
		//
		if(g_psFResultStrings[ui8Idx].iFResult == iFResult)
		{
			return(g_psFResultStrings[ui8Idx].pcResultStr);
		}
	}

	//
	// At this point no matching code was found, so return a string indicating
	// an unknown error.
	//
	return("UNKNOWN ERROR CODE");
}

//*****************************************************************************
//
// This is the handler for this SysTick interrupt.  FatFs requires a timer tick
// every 10 ms for internal timing purposes.
//
//*****************************************************************************
void SysTickHandler(void)
{
	disk_timerproc(); //Function inside mmc-dk-tm4c123g.c
}

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void __error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
//
// Configure the UART and its pins.  This must be called before UARTprintf().
//
//*****************************************************************************
void ConfigureUART(void)
{
	 //
    // Enable GPIO port A which is used for UART0 pins.
    // TODO: change this to whichever GPIO port you are using.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    //
    // Enable UART0 so that we can configure the clock.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    //
    // Configure the pin muxing for UART0 functions on port A0 and A1.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    //
    // Use the internal 8MHz oscillator as the UART clock source.
    //
   // UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
		ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
   // UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_NONE));
    //
    // Select the alternate (UART) function for these pins.
    // TODO: change this to select the port/pin you are using.
    //
    //ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
		//ROM_UARTCharPut(UART0_BASE,'A');
		//UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
		//
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 9600, 8000000);
	
		UARTprintf("\n\nSD Card Program\n");
		
		//SysCtlDelay(100);
}

//*****************************************************************************
//
// The program main function.  It performs initialization, then runs a command
// processing loop to read commands from the console.
//
//*****************************************************************************
int main(void)
{
	//int nStatus;

	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();

	//ROM_SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL |SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);//8MHz crystall oscilator
   ROM_SysCtlClockSet(SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_OSC|SYSCTL_SYSDIV_5);//8MHz crystall oscilator
    //
    // Configure SysTick for a 100Hz interrupt.  The FatFs driver wants a 10 ms
    // tick.
    //
		ROM_IntMasterEnable();
		ROM_SysTickPeriodSet(SysCtlClockGet()/100);
		ROM_SysTickIntEnable();
		ROM_SysTickEnable();
	
	
//		//Systick interrupt enable
//	IntMasterEnable();// Enable interrupts to the processor.
//	SysTickPeriodSet(79997);	// Set up the period for the SysTick timer of 1ms.	 
//	SysTickIntEnable(); // Enable the SysTick Interrupt.
//	SysTickEnable();// Enable SysTick.  SysTickEnable();// Enable SysTick.

	
	
//	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
//	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0));
//	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
//	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
//	GPIOPinConfigure(GPIO_PA3_SSI0FSS);
//	GPIOPinConfigure(GPIO_PA4_SSI0RX);
//	GPIOPinConfigure(GPIO_PA5_SSI0TX);
//	GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 |GPIO_PIN_3 | GPIO_PIN_2);
  
    //
    // Initialize the UART as a console for text I/O.
    //
	ConfigureUART();
  SysCtlDelay(100);
	UARTprintf("\n\nSD Card Example Program\n");

	iFResult = f_mount(0, &g_sFatFs);//	/* Mount the file system, using logical disk 1. */
	if(iFResult != FR_OK)
	{
		UARTprintf("f_mount error: %s\n", StringFromFResult(iFResult));
		SysCtlDelay(1000);
		return(1);
	}

	power_on();

	BOOL a = wait_ready(); //Wait for card ready  

	DSTATUS errd;

	if(a) {
		send_initial_clock_train();
		errd = disk_initialize(0);
		UARTprintf("\nInitialising disk 0. Status = %i\n", errd);
	}
/*********************************************************************************************************
	
	create a file testfile.txt with the following content -
	
***********************************************************************************************************/
	FIL fil;                   //fill: Pointer to the blank file object structure
	
	uint32_t count = 8*512;   //multiple write block(4096bytes)
	iFResult = f_open(&fil, "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);

}

Please help me to solve the issue.

Looking forward for a quick reply.

Regards,

Alphy

  • You wrote the below line which assumes the system clock to be 8MHz.
    UARTStdioConfig(0, 9600, 8000000);

    However, you also wrote:
    ROM_SysCtlClockSet(SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_OSC|SYSCTL_SYSDIV_5);//8MHz crystall oscilator

    The above line will configure the system clock to be 40MHz since you are using the PLL and you choose the divider to be 5. The PLL VCO output is 200MHz. After dividing 200MHz by 5 you get 40MHz only. Therefore, this will lead to incorrect baudrate.