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