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.

SSI1 Sdcard problem

Other Parts Discussed in Thread: TM4C123GH6PM

Hi;

I want to use sdcard with SSi1 prepheral. Sdcard can mount but I get "New file creation error". What is the problem ?

My pin settings

#define SDC_SSI_BASE SSI1_BASE
#define SDC_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI1

// GPIO for SSI pins
#define SDC_GPIO_PORT_BASE GPIO_PORTF_BASE
#define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOF
#define SDC_SSI_CLK GPIO_PIN_2
#define SDC_SSI_TX GPIO_PIN_1
#define SDC_SSI_RX GPIO_PIN_0
#define SDC_SSI_FSS GPIO_PIN_3
#define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK | \
SDC_SSI_FSS)

  • Hello Metin

    PF0 is a locked pin and needs to be unlocked before any configuration. Please see the following post.

    http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/374640

    Regards
    Amit
  • I made it , Nothing changed :/
  • Hello Metin

    Is this a custom board? If yes can you share the schematic. Also are you using the software example for sd_card in TivaWare and share the modifications/code for the same

    Regards
    Amit
  • I added "ff.c" ,  "mmc-dk-tm4c123g.c" ,"cc932.c" . And only changed  pins.


    #define SDC_SSI_BASE SSI1_BASE
    #define SDC_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI1

    // GPIO for SSI pins
    #define SDC_GPIO_PORT_BASE GPIO_PORTF_BASE
    #define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOF
    #define SDC_SSI_CLK GPIO_PIN_2
    #define SDC_SSI_TX GPIO_PIN_1
    #define SDC_SSI_RX GPIO_PIN_0
    #define SDC_SSI_FSS GPIO_PIN_3
    #define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK | \
    SDC_SSI_FSS)

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
    GPIOPinConfigure(GPIO_PF0_SSI1RX);
    GPIOPinConfigure(GPIO_PF1_SSI1TX);

    GPIOPinConfigure(GPIO_PF3_SSI1FSS);
    GPIOPinConfigure(GPIO_PF2_SSI1CLK);
    GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0| GPIO_PIN_1 | GPIO_PIN_2);

    It is custom board.  Schematic is here:

    And I check CCLK signal with osciloscope , No clock signal !

  • Hello Metin,

    The FSS pin has to be configured as a GPIO and not as SSI Controlled Pin. So the following line

    GPIOPinConfigure(GPIO_PF3_SSI1FSS);

    must be replaced by

    GPIOPinTypeGPIOOutput(SDC_GPIO_PORT_BASE, SDC_SSI_FSS);

    Are you making the changes in the mmc-dk-tm4c123g.c file or in the main code?

    Regards
    Amit
  • I dont change anything, it is written in mmc-dk-tm4c123g.c File.

  • Hello Metin,

    But what about the code post mentioned above along with the schematics? If you can share your CCS project, I could be able to help you out.

    Regards
    Amit
  • Hi Amit;

    Code here. Defines : PART_TM4C123GH6PM TARGET_IS_BLIZZARD_RA1 ENABLE_LFN

    modele_sdcard.h

    #ifndef __DRIVERLIB_ISL_SDCARD_H__
    #define __DRIVERLIB_ISL_SDCARD_H__
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "inc/hw_can.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/can.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/ssi.h"
    #include "driverlib/rom_map.h"
    
    #include "fatfs/src/ff.h"
    #include "fatfs/src/diskio.h"
    
    int WriteFile(char *file, char *data);
    void SetSdcardSettings(void);
    
    #endif

    modele_sdcard.c

    #include "module_sdcard.h"
    
    #define SDCARD_SSI1
    
    #define FRESULT_ENTRY(f)        { (f), (#f) }
    
    static FATFS g_sFatFs;
    static FIL g_sFileObject;
    
    extern uint32_t SysClock;
    
    #define NUM_FRESULT_CODES       (sizeof(g_psFResultStrings) /                 \
                                     sizeof(tFResultString))
    
    
    void
    SysTickHandler(void)
    {
        disk_timerproc();
    }
    
    void GPIOPinUnlockGPIO(uint32_t ui32Port, uint8_t ui8Pins)
    {
    	HWREG(ui32Port + GPIO_O_LOCK) = GPIO_LOCK_KEY;      // Unlock the port
    	HWREG(ui32Port + GPIO_O_CR) |= ui8Pins;             // Commit specified pins for next access
    	HWREG(ui32Port + GPIO_O_AFSEL) &= ~ui8Pins;         // Function: GPIO (disable alternate function)
    	HWREG(ui32Port + GPIO_O_DEN) &= ~ui8Pins;           // Disable digital driver
    	HWREG(ui32Port + GPIO_O_LOCK) = 0;                  // Lock the port
    }
    
    void
    SetSdcardSettings(void)
    {
    	FRESULT iFResult;
    	
    	ROM_SysTickPeriodSet(SysCtlClockGet() / 100);
    	ROM_SysTickEnable();
    	ROM_SysTickIntEnable();
    	 
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
    	GPIOPinConfigure(GPIO_PF0_SSI1RX); 
    	GPIOPinConfigure(GPIO_PF1_SSI1TX);
    	
    	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);
    	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3);
    	//GPIOPinConfigure(GPIO_PF3_SSI1FSS);
    	GPIOPinConfigure(GPIO_PF2_SSI1CLK);
    	GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0| GPIO_PIN_1 | GPIO_PIN_2);
    	 
    	 f_mount(0, &g_sFatFs);
    }
    
    int 
    WriteFile(char *file, char *data)
    {
    	unsigned int usBytesWrite;
    
    	if (f_open(&g_sFileObject, file, FA_CREATE_NEW | FA_WRITE)==FR_OK)
    	{
    		//
    		// write file
    		//
    		if(f_write(&g_sFileObject,data,strlen(data),&usBytesWrite)==FR_OK) 
    		{
    			//UARTprintf("Write file successn");	
    			f_sync(&g_sFileObject);
    			return 1;
    		}
    		else
    		{
    		//UARTprintf("Write into file Errorrn");	
    			return 2;
    		} 
    	}
    	else
    	{
    	// if the file is exist 
    		if (f_open(&g_sFileObject, file, FA_CREATE_NEW | FA_WRITE)==FR_EXIST)
    		{
    
    		if (f_open(&g_sFileObject, file, FA_OPEN_EXISTING | FA_WRITE)==FR_OK)
    			{ 
    			//
    			// write file
    			//
    				if(f_lseek(&g_sFileObject, g_sFileObject.fsize)==FR_OK)
    				{
    					if(f_write(&g_sFileObject,data,strlen(data),&usBytesWrite)==FR_OK) 
    					{
    						//UARTprintf("File append successn");	
    						f_close(&g_sFileObject);
    						return 3;
    					}
    					else
    					{
    					//UARTprintf("Write into file Errorrn");	
    						return 4;
    					} 
    				}
    			}
    			else
    			{
    			//UARTprintf("Append File ceation Error, file not foundn");
    				return 5;
    			} 
    		}
    		else 
    		//UARTprintf("New File ceation Errorn");
    		return 6;
    	}
    
    	return(0);
    	
    }
    

    mmc-dk-tm4c123g.c

    /*-----------------------------------------------------------------------*/
    /* MMC/SDC (in SPI mode) control module  (C)ChaN, 2007                   */
    /*-----------------------------------------------------------------------*/
    /* Only rcvr_spi(), xmit_spi(), disk_timerproc() and some macros         */
    /* are platform dependent.                                               */
    /*-----------------------------------------------------------------------*/
    
    /*
     * This file was modified from a sample available from the FatFs
     * web site. It was modified to work with an DK-TM4C123G development
     * board.
     */
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/ssi.h"
    #include "driverlib/sysctl.h"
    #include "fatfs/src/diskio.h"
    
    /* Definitions for MMC/SDC command */
    #define CMD0    (0x40+0)    /* GO_IDLE_STATE */
    #define CMD1    (0x40+1)    /* SEND_OP_COND */
    #define CMD8    (0x40+8)    /* SEND_IF_COND */
    #define CMD9    (0x40+9)    /* SEND_CSD */
    #define CMD10    (0x40+10)    /* SEND_CID */
    #define CMD12    (0x40+12)    /* STOP_TRANSMISSION */
    #define CMD16    (0x40+16)    /* SET_BLOCKLEN */
    #define CMD17    (0x40+17)    /* READ_SINGLE_BLOCK */
    #define CMD18    (0x40+18)    /* READ_MULTIPLE_BLOCK */
    #define CMD23    (0x40+23)    /* SET_BLOCK_COUNT */
    #define CMD24    (0x40+24)    /* WRITE_BLOCK */
    #define CMD25    (0x40+25)    /* WRITE_MULTIPLE_BLOCK */
    #define CMD41    (0x40+41)    /* SEND_OP_COND (ACMD) */
    #define CMD55    (0x40+55)    /* APP_CMD */
    #define CMD58    (0x40+58)    /* READ_OCR */
    
    /* Peripheral definitions for DK-TM4C123G board */
    // SSI port
    #define SDC_SSI_BASE            SSI1_BASE
    #define SDC_SSI_SYSCTL_PERIPH   SYSCTL_PERIPH_SSI1
    
    // GPIO for SSI pins
    #define SDC_GPIO_PORT_BASE      GPIO_PORTF_BASE
    #define SDC_GPIO_SYSCTL_PERIPH  SYSCTL_PERIPH_GPIOF
    #define SDC_SSI_CLK             GPIO_PIN_2
    #define SDC_SSI_TX              GPIO_PIN_1
    #define SDC_SSI_RX              GPIO_PIN_0
    #define SDC_SSI_FSS             GPIO_PIN_3
    #define SDC_SSI_PINS            (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK |      \
                                     SDC_SSI_FSS)
    
    // asserts the CS pin to the card
    static
    void SELECT (void)
    {
        ROM_GPIOPinWrite(SDC_GPIO_PORT_BASE, SDC_SSI_FSS, 0);
    }
    
    // de-asserts the CS pin to the card
    static
    void DESELECT (void)
    {
        ROM_GPIOPinWrite(SDC_GPIO_PORT_BASE, SDC_SSI_FSS, SDC_SSI_FSS);
    }
    
    /*--------------------------------------------------------------------------
    
       Module Private Functions
    
    ---------------------------------------------------------------------------*/
    
    static volatile
    DSTATUS Stat = STA_NOINIT;    /* Disk status */
    
    static volatile
    BYTE Timer1, Timer2;    /* 100Hz decrement timer */
    
    static
    BYTE CardType;            /* b0:MMC, b1:SDC, b2:Block addressing */
    
    static
    BYTE PowerFlag = 0;     /* indicates if "power" is on */
    
    /*-----------------------------------------------------------------------*/
    /* Transmit a byte to MMC via SPI  (Platform dependent)                  */
    /*-----------------------------------------------------------------------*/
     
    static
    void xmit_spi(BYTE dat)
    {
        uint32_t ui32RcvDat;
    
        ROM_SSIDataPut(SDC_SSI_BASE, dat); /* Write the data to the tx fifo */
    
        ROM_SSIDataGet(SDC_SSI_BASE, &ui32RcvDat); /* flush data read during the write */
    }
    
    
    /*-----------------------------------------------------------------------*/
    /* Receive a byte from MMC via SPI  (Platform dependent)                 */
    /*-----------------------------------------------------------------------*/
    
    static
    BYTE rcvr_spi (void)
    {
        uint32_t ui32RcvDat;
    
        ROM_SSIDataPut(SDC_SSI_BASE, 0xFF); /* write dummy data */
    
        ROM_SSIDataGet(SDC_SSI_BASE, &ui32RcvDat); /* read data frm rx fifo */
    
        return (BYTE)ui32RcvDat;
    }
    
    
    static
    void rcvr_spi_m (BYTE *dst)
    {
        *dst = rcvr_spi();
    }
    
    /*-----------------------------------------------------------------------*/
    /* Wait for card ready                                                   */
    /*-----------------------------------------------------------------------*/
    
    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;
    }
    
    /*-----------------------------------------------------------------------*/
    /* 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);
    }
    
    /*-----------------------------------------------------------------------*/
    /* Power Control  (Platform dependent)                                   */
    /*-----------------------------------------------------------------------*/
    /* When the target system does not support socket power control, there   */
    /* is nothing to do in these functions and chk_power always returns 1.   */
    
    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);
    
        /*
         * 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, 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;
    }
    
    // set the SSI speed to the max setting
    static
    void set_max_speed(void)
    {
        unsigned long i;
    
        /* Disable the SSI */
        ROM_SSIDisable(SDC_SSI_BASE);
    
        /* Set the maximum speed as half the system clock, with a max of 12.5 MHz. */
        i = SysCtlClockGet() / 2;
        if(i > 12500000)
        {
            i = 12500000;
        }
    
        /* Configure the SSI0 port to run at 12.5MHz */
        SSIConfigSetExpClk(SDC_SSI_BASE, SysCtlClockGet(),
                               SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, i, 8);
    
        /* Enable the SSI */
        ROM_SSIEnable(SDC_SSI_BASE);
    }
    
    static
    void power_off (void)
    {
        PowerFlag = 0;
    }
    
    static
    int chk_power(void)        /* Socket power state: 0=off, 1=on */
    {
        return PowerFlag;
    }
    
    
    
    /*-----------------------------------------------------------------------*/
    /* 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 */
    }
    
    
    
    /*-----------------------------------------------------------------------*/
    /* Send a data packet to MMC                                             */
    /*-----------------------------------------------------------------------*/
    
    #if _READONLY == 0
    static
    BOOL xmit_datablock (
        const BYTE *buff,    /* 512 byte data block to be transmitted */
        BYTE token            /* Data/Stop token */
    )
    {
        BYTE resp, wc;
    
    
        if (wait_ready() != 0xFF) return FALSE;
    
        xmit_spi(token);                    /* Xmit data token */
        if (token != 0xFD) {    /* Is data token */
            wc = 0;
            do {                            /* Xmit the 512 byte data block to MMC */
                xmit_spi(*buff++);
                xmit_spi(*buff++);
            } while (--wc);
            xmit_spi(0xFF);                    /* CRC (Dummy) */
            xmit_spi(0xFF);
            resp = rcvr_spi();                /* Reveive data response */
            if ((resp & 0x1F) != 0x05)        /* If not accepted, return with error */
                return FALSE;
        }
    
        return TRUE;
    }
    #endif /* _READONLY */
    
    
    
    /*-----------------------------------------------------------------------*/
    /* Send a command packet to MMC                                          */
    /*-----------------------------------------------------------------------*/
    
    static
    BYTE send_cmd (
        BYTE cmd,        /* Command byte */
        DWORD arg        /* Argument */
    )
    {
        BYTE n, res;
    
    
        if (wait_ready() != 0xFF) return 0xFF;
    
        /* Send command packet */
        xmit_spi(cmd);                        /* Command */
        xmit_spi((BYTE)(arg >> 24));        /* Argument[31..24] */
        xmit_spi((BYTE)(arg >> 16));        /* Argument[23..16] */
        xmit_spi((BYTE)(arg >> 8));            /* Argument[15..8] */
        xmit_spi((BYTE)arg);                /* Argument[7..0] */
        n = 0xff;
        if (cmd == CMD0) n = 0x95;            /* CRC for CMD0(0) */
        if (cmd == CMD8) n = 0x87;            /* CRC for CMD8(0x1AA) */
        xmit_spi(n);
    
        /* Receive command response */
        if (cmd == CMD12) rcvr_spi();        /* Skip a stuff byte when stop reading */
        n = 10;                                /* Wait for a valid response in timeout of 10 attempts */
        do
            res = rcvr_spi();
        while ((res & 0x80) && --n);
    
        return res;            /* Return with the response value */
    }
    
    /*-----------------------------------------------------------------------*
     * Send the special command used to terminate a multi-sector read.
     *
     * This is the only command which can be sent while the SDCard is sending
     * data. The SDCard spec indicates that the data transfer will stop 2 bytes
     * after the 6 byte CMD12 command is sent and that the card will then send
     * 0xFF for between 2 and 6 more bytes before the R1 response byte.  This
     * response will be followed by another 0xFF byte.  In testing, however, it
     * seems that some cards don't send the 2 to 6 0xFF bytes between the end of
     * data transmission and the response code.  This function, therefore, merely
     * reads 10 bytes and, if the last one read is 0xFF, returns the value of the
     * latest non-0xFF byte as the response code.
     *
     *-----------------------------------------------------------------------*/
    
    static
    BYTE send_cmd12 (void)
    {
        BYTE n, res, val;
    
        /* For CMD12, we don't wait for the card to be idle before we send
         * the new command.
         */
    
        /* Send command packet - the argument for CMD12 is ignored. */
        xmit_spi(CMD12);
        xmit_spi(0);
        xmit_spi(0);
        xmit_spi(0);
        xmit_spi(0);
        xmit_spi(0);
    
        /* Read up to 10 bytes from the card, remembering the value read if it's
           not 0xFF */
        for(n = 0; n < 10; n++)
        {
            val = rcvr_spi();
            if(val != 0xFF)
            {
                res = val;
            }
        }
    
        return res;            /* Return with the response value */
    }
    
    /*--------------------------------------------------------------------------
    
       Public Functions
    
    ---------------------------------------------------------------------------*/
    
    
    /*-----------------------------------------------------------------------*/
    /* Initialize Disk Drive                                                 */
    /*-----------------------------------------------------------------------*/
    
    DSTATUS disk_initialize (
        BYTE drv        /* Physical drive nmuber (0) */
    )
    {
        BYTE n, ty, ocr[4];
    
    
        if (drv) return STA_NOINIT;            /* Supports only single drive */
        if (Stat & STA_NODISK) return Stat;    /* No card in the socket */
    
        power_on();                            /* Force socket power on */
        send_initial_clock_train();            /* Ensure the card is in SPI mode */
    
        SELECT();                /* CS = L */
        ty = 0;
        if (send_cmd(CMD0, 0) == 1) {            /* Enter Idle state */
            Timer1 = 100;                        /* Initialization timeout of 1000 msec */
            if (send_cmd(CMD8, 0x1AA) == 1) {    /* SDC Ver2+ */
                for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
                if (ocr[2] == 0x01 && ocr[3] == 0xAA) {    /* The card can work at vdd range of 2.7-3.6V */
                    do {
                        if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0)    break;    /* ACMD41 with HCS bit */
                    } while (Timer1);
                    if (Timer1 && send_cmd(CMD58, 0) == 0) {    /* Check CCS bit */
                        for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
                        ty = (ocr[0] & 0x40) ? 6 : 2;
                    }
                }
            } else {                            /* SDC Ver1 or MMC */
                ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1;    /* SDC : MMC */
                do {
                    if (ty == 2) {
                        if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break;    /* ACMD41 */
                    } else {
                        if (send_cmd(CMD1, 0) == 0) break;                                /* CMD1 */
                    }
                } while (Timer1);
                if (!Timer1 || send_cmd(CMD16, 512) != 0)    /* Select R/W block length */
                    ty = 0;
            }
        }
        CardType = ty;
        DESELECT();            /* CS = H */
        rcvr_spi();            /* Idle (Release DO) */
    
        if (ty) {            /* Initialization succeded */
            Stat &= ~STA_NOINIT;        /* Clear STA_NOINIT */
            set_max_speed();
        } else {            /* Initialization failed */
            power_off();
        }
    
        return Stat;
    }
    
    
    
    /*-----------------------------------------------------------------------*/
    /* Get Disk Status                                                       */
    /*-----------------------------------------------------------------------*/
    
    DSTATUS disk_status (
        BYTE drv        /* Physical drive nmuber (0) */
    )
    {
        if (drv) return STA_NOINIT;        /* Supports only single drive */
        return Stat;
    }
    
    
    
    /*-----------------------------------------------------------------------*/
    /* Read Sector(s)                                                        */
    /*-----------------------------------------------------------------------*/
    
    DRESULT disk_read (
        BYTE drv,            /* Physical drive nmuber (0) */
        BYTE *buff,            /* Pointer to the data buffer to store read data */
        DWORD sector,        /* Start sector number (LBA) */
        BYTE count            /* Sector count (1..255) */
    )
    {
        if (drv || !count) return RES_PARERR;
        if (Stat & STA_NOINIT) return RES_NOTRDY;
    
        if (!(CardType & 4)) sector *= 512;    /* Convert to byte address if needed */
    
        SELECT();            /* CS = L */
    
        if (count == 1) {    /* Single block read */
            if ((send_cmd(CMD17, sector) == 0)    /* READ_SINGLE_BLOCK */
                && rcvr_datablock(buff, 512))
                count = 0;
        }
        else {                /* Multiple block read */
            if (send_cmd(CMD18, sector) == 0) {    /* READ_MULTIPLE_BLOCK */
                do {
                    if (!rcvr_datablock(buff, 512)) break;
                    buff += 512;
                } while (--count);
                send_cmd12();                /* STOP_TRANSMISSION */
            }
        }
    
        DESELECT();            /* CS = H */
        rcvr_spi();            /* Idle (Release DO) */
    
        return count ? RES_ERROR : RES_OK;
    }
    
    
    
    /*-----------------------------------------------------------------------*/
    /* Write Sector(s)                                                       */
    /*-----------------------------------------------------------------------*/
    
    #if _READONLY == 0
    DRESULT disk_write (
        BYTE drv,            /* Physical drive nmuber (0) */
        const BYTE *buff,    /* Pointer to the data to be written */
        DWORD sector,        /* Start sector number (LBA) */
        BYTE count            /* Sector count (1..255) */
    )
    {
        if (drv || !count) return RES_PARERR;
        if (Stat & STA_NOINIT) return RES_NOTRDY;
        if (Stat & STA_PROTECT) return RES_WRPRT;
    
        if (!(CardType & 4)) sector *= 512;    /* Convert to byte address if needed */
    
        SELECT();            /* CS = L */
    
        if (count == 1) {    /* Single block write */
            if ((send_cmd(CMD24, sector) == 0)    /* WRITE_BLOCK */
                && xmit_datablock(buff, 0xFE))
                count = 0;
        }
        else {                /* Multiple block write */
            if (CardType & 2) {
                send_cmd(CMD55, 0); send_cmd(CMD23, count);    /* ACMD23 */
            }
            if (send_cmd(CMD25, sector) == 0) {    /* WRITE_MULTIPLE_BLOCK */
                do {
                    if (!xmit_datablock(buff, 0xFC)) break;
                    buff += 512;
                } while (--count);
                if (!xmit_datablock(0, 0xFD))    /* STOP_TRAN token */
                    count = 1;
            }
        }
    
        DESELECT();            /* CS = H */
        rcvr_spi();            /* Idle (Release DO) */
    
        return count ? RES_ERROR : RES_OK;
    }
    #endif /* _READONLY */
    
    
    
    /*-----------------------------------------------------------------------*/
    /* Miscellaneous Functions                                               */
    /*-----------------------------------------------------------------------*/
    
    DRESULT disk_ioctl (
        BYTE drv,        /* Physical drive nmuber (0) */
        BYTE ctrl,        /* Control code */
        void *buff        /* Buffer to send/receive control data */
    )
    {
        DRESULT res;
        BYTE n, csd[16], *ptr = buff;
        WORD csize;
    
    
        if (drv) return RES_PARERR;
    
        res = RES_ERROR;
    
        if (ctrl == CTRL_POWER) {
            switch (*ptr) {
            case 0:        /* Sub control code == 0 (POWER_OFF) */
                if (chk_power())
                    power_off();        /* Power off */
                res = RES_OK;
                break;
            case 1:        /* Sub control code == 1 (POWER_ON) */
                power_on();                /* Power on */
                res = RES_OK;
                break;
            case 2:        /* Sub control code == 2 (POWER_GET) */
                *(ptr+1) = (BYTE)chk_power();
                res = RES_OK;
                break;
            default :
                res = RES_PARERR;
            }
        }
        else {
            if (Stat & STA_NOINIT) return RES_NOTRDY;
    
            SELECT();        /* CS = L */
    
            switch (ctrl) {
            case GET_SECTOR_COUNT :    /* Get number of sectors on the disk (DWORD) */
                if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
                    if ((csd[0] >> 6) == 1) {    /* SDC ver 2.00 */
                        csize = csd[9] + ((WORD)csd[8] << 8) + 1;
                        *(DWORD*)buff = (DWORD)csize << 10;
                    } else {                    /* MMC or SDC ver 1.XX */
                        n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
                        csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
                        *(DWORD*)buff = (DWORD)csize << (n - 9);
                    }
                    res = RES_OK;
                }
                break;
    
            case GET_SECTOR_SIZE :    /* Get sectors on the disk (WORD) */
                *(WORD*)buff = 512;
                res = RES_OK;
                break;
    
            case CTRL_SYNC :    /* Make sure that data has been written */
                if (wait_ready() == 0xFF)
                    res = RES_OK;
                break;
    
            case MMC_GET_CSD :    /* Receive CSD as a data block (16 bytes) */
                if (send_cmd(CMD9, 0) == 0        /* READ_CSD */
                    && rcvr_datablock(ptr, 16))
                    res = RES_OK;
                break;
    
            case MMC_GET_CID :    /* Receive CID as a data block (16 bytes) */
                if (send_cmd(CMD10, 0) == 0        /* READ_CID */
                    && rcvr_datablock(ptr, 16))
                    res = RES_OK;
                break;
    
            case MMC_GET_OCR :    /* Receive OCR as an R3 resp (4 bytes) */
                if (send_cmd(CMD58, 0) == 0) {    /* READ_OCR */
                    for (n = 0; n < 4; n++)
                        *ptr++ = rcvr_spi();
                    res = RES_OK;
                }
    
    //        case MMC_GET_TYPE :    /* Get card type flags (1 byte) */
    //            *ptr = CardType;
    //            res = RES_OK;
    //            break;
    
            default:
                res = RES_PARERR;
            }
    
            DESELECT();            /* CS = H */
            rcvr_spi();            /* Idle (Release DO) */
        }
    
        return res;
    }
    
    
    
    /*-----------------------------------------------------------------------*/
    /* Device Timer Interrupt Procedure  (Platform dependent)                */
    /*-----------------------------------------------------------------------*/
    /* This function must be called in period of 10ms                        */
    
    void disk_timerproc (void)
    {
    //    BYTE n, s;
        BYTE n;
    
    
        n = Timer1;                        /* 100Hz decrement timer */
        if (n) Timer1 = --n;
        n = Timer2;
        if (n) Timer2 = --n;
    
    }
    
    /*---------------------------------------------------------*/
    /* User Provided Timer Function for FatFs module           */
    /*---------------------------------------------------------*/
    /* This is a real time clock service to be called from     */
    /* FatFs module. Any valid time must be returned even if   */
    /* the system does not support a real time clock.          */
    
    DWORD get_fattime (void)
    {
    
        return    ((2007UL-1980) << 25)    // Year = 2007
                | (6UL << 21)            // Month = June
                | (5UL << 16)            // Day = 5
                | (11U << 11)            // Hour = 11
                | (38U << 5)            // Min = 38
                | (0U >> 1)                // Sec = 0
                ;
    
    }
    

  • Reading, "War and Peace" required less effort - and was faster...

  • Hello Metin,

    The Port Control registers have not been programmed. Please note that for SSI-0 the PCTL are programmed as reset value on the TM4C123. Since I do not have your board I had to retrofit one on my own and following function needs an update in the mmc-dk-tm4c123g,c Also do add the include file "driverlib/pin_map.h"

    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);
    /*
    * 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.
    */
    GPIOPinConfigure(GPIO_PF0_SSI1RX);
    GPIOPinConfigure(GPIO_PF1_SSI1TX);
    GPIOPinConfigure(GPIO_PF2_SSI1CLK);
    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, 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;
    }


    Regards
    Amit
  • And leave you more happy than tired and don't remember my war with this code too ;)
  • GPIOPinConfigure(GPIO_PF0_SSI1RX);

    GPIOPinConfigure(GPIO_PF1_SSI1TX);

    GPIOPinConfigure(GPIO_PF2_SSI1CLK);

    Hello Amit,

    I had written this codes, but something wrong currently :/

  • Hello Metin,

    The code post you had sent while had the functions defined, it was not clear as to how they were integrated. So I changed the sd-card example to use SSI-1 Port and checked for the Clock, CS, TX data and they were changing as expected.

    Regards
    Amit
  • Hi again Amit;

    I am sending you my full project. Libs are in the "libs" folder. What is the wrong i can't find :/ Please help me.

     http://www.teknikyazi.com/TIVASD.rar 

  • Hello Metin

    Please elaborate the issue?

    Regards
    Amit
  • Hello Amit;

    In the code , i want to write file to sdcard. This card's previus version, sd card is working successfully with SSI0. But at new version , it is not writing file to sdcard with SSI1.  At the code  it can mount sdcard. But WriteFile function returns 6. ( "New File ceation Errorn" ).  WriteFile function at bottom.

    I made them: 

    1. Change pins to F Ports and SSI number to 1 at mmc-dk-tm4c123g.c file.
    2. Unlock the PF0.
    3. GPIOPinconfigure for PF0, PF1, PF2

    So it is still not working. Please help me.

    int 
    WriteFile(char *file, char *data)
    {
    	unsigned int usBytesWrite;
    
    	if (f_open(&g_sFileObject, file, FA_CREATE_NEW | FA_WRITE)==FR_OK)
    	{
    		//
    		// write file
    		//
    		if(f_write(&g_sFileObject,data,strlen(data),&usBytesWrite)==FR_OK) 
    		{
    			//UARTprintf("Write file successn");	
    			f_sync(&g_sFileObject);
    			return 1;
    		}
    		else
    		{
    			//UARTprintf("Write into file Errorrn");	
    			return 2;
    		} 
    	}
    	else
    	{
    		// if the file is exist 
    		if (f_open(&g_sFileObject, file, FA_CREATE_NEW | FA_WRITE)==FR_EXIST)
    		{
    
    		if (f_open(&g_sFileObject, file, FA_OPEN_EXISTING | FA_WRITE)==FR_OK)
    			{ 
    				//
    				// write file
    				//
    				if(f_lseek(&g_sFileObject, g_sFileObject.fsize)==FR_OK)
    				{
    					if(f_write(&g_sFileObject,data,strlen(data),&usBytesWrite)==FR_OK) 
    					{
    						//UARTprintf("File append successn");	
    						f_close(&g_sFileObject);
    						return 3;
    					}
    					else
    					{
    						//UARTprintf("Write into file Errorrn");	
    						return 4;
    					} 
    				}
    			}
    			else
    			{
    				//UARTprintf("Append File ceation Error, file not foundn");
    				return 5;
    			} 
    		}
    		else 
    		//UARTprintf("New File ceation Errorn");
    		return 6;
    	}
    
    	return(0);
    	
    }

  • Hello Metin,

    I reused the sd_card code on DK-TM4C123GXL to create new files and write to them and it works fine. Maybe you can check the framework and reuse the same (or send in the project)

    int
    Cmd_wr(int argc, char *argv[])
    {
    FRESULT iFResult;
    uint32_t ui32BytesRead;

    //
    // First, check to make sure that the current path (CWD), plus the file
    // name, plus a separator and trailing null, will all fit in the temporary
    // buffer that will be used to hold the file name. The file name must be
    // fully specified, with path, to FatFs.
    //
    if(strlen(g_pcCwdBuf) + strlen(argv[1]) + 1 + 1 > sizeof(g_pcTmpBuf))
    {
    UARTprintf("Resulting path name is too long\n");
    return(0);
    }

    //
    // Copy the current path to the temporary buffer so it can be manipulated.
    //
    strcpy(g_pcTmpBuf, g_pcCwdBuf);

    //
    // If not already at the root level, then append a separator.
    //
    if(strcmp("/", g_pcCwdBuf))
    {
    strcat(g_pcTmpBuf, "/");
    }

    //
    // Now finally, append the file name to result in a fully specified file.
    //
    strcat(g_pcTmpBuf, argv[1]);

    //
    // Open the file for reading.
    //
    iFResult = f_open(&g_sFileObject, g_pcTmpBuf, (FA_WRITE | FA_CREATE_NEW));

    //
    // If there was some problem opening the file, then return an error.
    //
    if(iFResult != FR_OK)
    {
    return((int)iFResult);
    }

    //
    // Now read the data into the buffer
    //
    strcpy(g_pcDatBuf, argv[2]);

    //
    // Enter a loop to repeatedly read data from the file and display it, until
    // the end of the file is reached.
    //
    iFResult = f_write(&g_sFileObject, g_pcDatBuf, sizeof(g_pcDatBuf) - 1,
    (UINT *)&ui32BytesRead);

    //
    // If there was an error writing, then print a newline and return the
    // error to the user.
    //
    if(iFResult != FR_OK)
    {
    return((int)iFResult);
    }

    f_close(&g_sFileObject);
    //
    // Return success.
    //
    return(0);
    }


    Regards
    Amit
  • Hello Amit;

    is "sd_card  project" in example ? if it is , it is working with SSI0, Can you run on SSI1 ?

  • Hello Metin,

    Yes. sd_card is a project example. I made the change to run it from SSI1

    1. Made sure that SSI0 Pins are GPIO Inputs
    2. On the DK-TM4C123 rewired the SSI1 pins to the sd_card

    Regards
    Amit
  • Hello Amit;

    I look sd_card project , But it is TM4C129X project. Not 123X. Do you run code with TM4C123GH6PM ?
  • Hello Metin,

    It is under dk-tm4c123g

    C:\ti\TivaWare_C_Series-2.1.0.12573\examples\boards\dk-tm4c123g\sd_card

    Regards
    Amit
  • Just to be sure, does your SDcard not have the switch for the write protection in the ON position, can you read from it?
  • Hi Amit;

    Continuing problem. fopen function returning 3 (FR_NOT_READY). I changed sdcard slot and sdcard. so It is same. SSI0 is working but SSI1 is not working :/

  • Hello Metin,

    FR_NOT_READY, would mean that there is a issue with the assembly or the card not making contact. Can you please share your simplified project (I will have to schedule some time to try it on the board) ?

    Regards
    Amit
  • Hello Amit,

    Full project :

  • Hello Metin,

    As mentioned, it will be some time before I can visit the project...

    Regards
    Amit
  • Hello Amit,

    Thank you very much. I am waiting your feedback.

  • Hello Amit;

    Did you look my project ? Could you try it ?

  • Hello Metin,

    Yes, I tried your code (My keil is out of license) in CCS by importing the files from your project. The file write works fine

    Regards

    Amit

  • Hello Amit;

     Thanks for support. We must check our schematic then if error , I will share schematic with you.

  • Hello Metin,

    To accelerate your development, may I suggest purchasing the sd card boosterpack while the board is being checked?

    Regards
    Amit
  • My problem not with SDcard , My problem with only "SDcard on SSI1 at Tiva "
  • Hello Metin,

    And are you rewiring the sd-card between SSI-0 and SSI-1?

    Regards
    Amit
  • Yes, I transfer pins SSI0 to SSI1 and schematic is this.

  • Hello Metin,

    The schematic is correct and so are the connections. I would suggest connecting a scope probe to see what is happening on the signals when the f_mount is called.

    Regards
    Amit
  • Hello Amit;

    Nothing is changed. Clock -> Zero , FSS -> High , Tx -> Low , Rx-> High, And f_mount is returning FR_OK

  • Hello Metin,

    Does any of the function cause the SSI Lines to change. You may need to check the GPIO configuration and SSI configuration.

    Regards
    Amit
  • Hello Amit;

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	
    	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; 
    	HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= GPIO_PIN_0;
    	
    	GPIOPinConfigure(GPIO_PF0_SSI1RX);
    	GPIOPinConfigure(GPIO_PF1_SSI1TX);
    	GPIOPinConfigure(GPIO_PF2_SSI1CLK);
    	
    	
    	/*
    	Prepare SysTick Timer
    	*/
    	ROM_SysTickPeriodSet(SysCtlClockGet() / 100);
    	ROM_SysTickEnable();
    	ROM_SysTickIntEnable();
    	
    	/*
    	Mount Sd Card
    	*/
    	if(f_mount(0, &g_sFatFs)!=FR_OK)
    	{
    		while(1); //if problem loop
    	}

  • Hello Metin,

    Can you step debug the ff.c which contains the f_mount to see where it is returning an Err from?

    Regards
    Amit
  • HEllo Amit;

    it is return at 2120 line. in chk_mounted function. it is returning FR_NOT_READY;

    if (stat & STA_NOINIT) /* Check if the initialization succeeded */
    return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
  • Hello Metin,

    But that is happening during f_open function call. Is that right? The reason I ask so is because the program snapshot only has f_mount. What I would suggest doing is to monitor the SSI signals during f_open for SSI0 and SSI1 and comparing them to see what the difference is. Also try lowering the SSI-1 Clock frequency to weed out any board issues like setup timing

    Regards
    Amit