logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

TMS320F2812 - Obsługa karty uSD - moduł FatFs - zapis do pliku

RydelW 25 Sie 2014 11:14 3201 2
REKLAMA
  • #1 13905583
    RydelW
    Poziom 2  
    Witam,
    Jak w temacie, mam problem z zapisem danych do pliku. Sprawa wygląda tak, że mogę odczytać dane z pliku utworzonego przy użyciu PC bez problemu i nadpisać do niego dane. Mogę także utworzyć nowy plik przy użyciu modułu FatFs ale nie mogę do niego zapisać żadnych danych, f_write zwraca błąd. Wygląda to tak jakby funkcje zapisu nie mogły "rozszerzyć" rozmiaru pliku podczas zapisu, ponieważ, gdy nadpisuję dane do pliku wcześniej utworzonego na PC to mogę tylko tyle danych zapisać/nadpisać ile ten plik miał wcześniej zapisanych danych, nie mogę dopisać niczego więcej.

    Ktoś pomoże?
  • REKLAMA
  • #2 13906210
    mi14chal
    Poziom 28  
    Gdzie kod? Co za błąd zwraca f_write?
  • #3 13906273
    RydelW
    Poziom 2  
    Plik main:
    
    #include "DSP281x_Device.h"
    #include "spi_sd.h"
    #include "SD_SPI.h"
    #include "ff.h"
    #include "diskio.h"
    
    void Gpio_select(void);
    void InitSystem(void);
    void SPI_Init(void);
    interrupt void cpu_timer0_isr(void); // Prototype for Timer 0 Interrupt Service Routine
    
    
    FATFS fatfs;
    FIL plik;
    FRESULT fresult,res1,res2,res3,res4,res5,res6,res7,res8,res9;
    DWORD size,point;
    UINT zapisanych_bajtow = 0 , br;
    UINT zapianie_bajtow = 0;
    BYTE * buffor = "123456789abcdef\r\n";
    char *a = "5";
    unsigned short int i;
    int error;
    char Buff[40];
    char buf;
    void main(void) {
    
    	int i = 0;
    	InitSystem();		// Initialize the DSP's core Registers
    
    	// Speed_up the silicon A Revision.
    	// No need to call this function for Rev. C  later silicon versions
    
    	Gpio_select();		// Setup the GPIO Multiplex Registers
    
    	InitPieCtrl();// Function Call to init PIE-unit ( code : DSP281x_PieCtrl.c)
    
    	InitPieVectTable(); // Function call to init PIE vector table ( code : DSP281x_PieVect.c )
    
    	// re-map PIE - entry for Timer 0 Interrupt
    	EALLOW;
    	// This is needed to write to EALLOW protected registers
    	PieVectTable.TINT0 = &cpu_timer0_isr;
    	EDIS;
    	// This is needed to disable write to EALLOW protected registers
    
    	InitCpuTimers();
    
    	// Configure CPU-Timer 0 to interrupt every 10 ms:
    	// 150MHz CPU Freq, 10000 µseconds interrupt period
    	ConfigCpuTimer(&CpuTimer0, 150, 10000);
    
    	// Enable TINT0 in the PIE: Group 1 interrupt 7
    	//PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    
    	// Enable CPU INT1 which is connected to CPU-Timer 0:
    	IER = 1;
    
    	// Enable global Interrupts and higher priority real-time debug events:
    	EINT;
    	// Enable Global interrupt INTM
    	ERTM;
    	// Enable Global realtime interrupt DBGM
    	CpuTimer0.InterruptCount = 0;
    	CpuTimer0Regs.TCR.bit.TSS = 0;
    
    	SPI_SD_Init();
    	res1 = f_mount(&fatfs,"",0);
    	   res2 = f_open( &plik, "pliczek.txt", FA_OPEN_EXISTING | FA_READ );
    	    if( res2 == FR_OK )
    	    {
    	    	res3 = f_read(&plik,Buff,14,&zapisanych_bajtow);
    
    	    }
    
    	    res4 = f_close( &plik );
    
    	   res5 = f_open(&plik, "file9.txt", FA_CREATE_NEW | FA_WRITE);
    	   res6 = f_write(&plik,Buff,14,&br);
    	   res7 = f_close(&plik);
    
    
    	    for(;;)
    	    {
    
    	    }
    }
    
    void Gpio_select(void) {
    	EALLOW;
    	GpioMuxRegs.GPAMUX.all = 0x0;	// all GPIO port Pin's to I/O
    	GpioMuxRegs.GPBMUX.all = 0x0;
    	GpioMuxRegs.GPDMUX.all = 0x0;
    
    	GpioMuxRegs.GPFMUX.all = 0xF;
    	GpioMuxRegs.GPEMUX.all = 0x0;
    	GpioMuxRegs.GPGMUX.all = 0x0;
    
    	GpioMuxRegs.GPADIR.all = 0x0;	// GPIO PORT  as input
    	GpioMuxRegs.GPBDIR.all = 0x0;	
    	GpioMuxRegs.GPBDIR.bit.GPIOB10 = 1;	// CS01
    	GpioMuxRegs.GPBDIR.bit.GPIOB11 = 0;	// input INSIDE_CARD
    	GpioMuxRegs.GPBDIR.bit.GPIOB14 = 1;	// CS02
    	GpioMuxRegs.GPDDIR.all = 0x0;	// GPIO PORT  as input
    	GpioMuxRegs.GPEDIR.all = 0x0;	// GPIO PORT  as input
    	GpioMuxRegs.GPFDIR.all = 0x0;	// GPIO PORT  as input
    	GpioMuxRegs.GPFDIR.bit.GPIOF3 = 1;	// SPICS as output
    	GpioMuxRegs.GPFDIR.bit.GPIOF2 = 1;	// SPICLK as output
    	GpioMuxRegs.GPFDIR.bit.GPIOF0 = 1;	// SPISIMO as output
    	GpioMuxRegs.GPGDIR.all = 0x0;	// GPIO PORT  as input
    
    	GpioMuxRegs.GPAQUAL.all = 0x0;	// Set GPIO input qualifier values to zero
    	GpioMuxRegs.GPBQUAL.all = 0x0;
    	GpioMuxRegs.GPDQUAL.all = 0x0;
    	GpioMuxRegs.GPEQUAL.all = 0x0;
    	EDIS;
    }
    
    void InitSystem(void) {
    	EALLOW;
    	SysCtrlRegs.WDCR = 0x00E8;		// Setup the watchdog
    									// 0x00E8  to disable the Watchdog , Prescaler = 1
    									// 0x00AF  to NOT disable the Watchdog, Prescaler = 64
    	SysCtrlRegs.SCSR = 0; 			// Watchdog generates a RESET
    	SysCtrlRegs.PLLCR.bit.DIV = 10;	// Setup the Clock PLL to multiply by 5
    
    	SysCtrlRegs.HISPCP.all = 0x1; // Setup Highspeed Clock Prescaler to divide by 2
    	SysCtrlRegs.LOSPCP.all = 0x2; // Setup Lowspeed CLock Prescaler to divide by 4
    
    	// Peripheral clock enables set for the selected peripherals.
    	SysCtrlRegs.PCLKCR.bit.EVAENCLK = 0;
    	SysCtrlRegs.PCLKCR.bit.EVBENCLK = 0;
    	SysCtrlRegs.PCLKCR.bit.SCIAENCLK = 0;
    	SysCtrlRegs.PCLKCR.bit.SCIBENCLK = 0;
    	SysCtrlRegs.PCLKCR.bit.MCBSPENCLK = 0;
    	SysCtrlRegs.PCLKCR.bit.SPIENCLK = 1;
    	SysCtrlRegs.PCLKCR.bit.ECANENCLK = 0;
    	SysCtrlRegs.PCLKCR.bit.ADCENCLK = 0;
    	EDIS;
    }
    
    interrupt void cpu_timer0_isr(void) {
    	CpuTimer0.InterruptCount++;
    	// Serve the watchdog every Timer 0 interrupt
    	disk_timerproc();
    	EALLOW;
    	SysCtrlRegs.WDKEY = 0x55;		// Serve watchdog #1
    	EDIS;
    
    	// Acknowledge this interrupt to receive more interrupts from group 1
    	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1
    	;
    }
    
    void SPI_Init(void) {
    	SpiaRegs.SPICCR.bit.SPISWRESET = 0;	// Reset the SPI
    
    	SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;	// data output at rising edge of clk
    	SpiaRegs.SPICCR.bit.SPICHAR = 7;	// 8 bit per data frame
    
    	SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0;
    	SpiaRegs.SPICTL.bit.SPIINTENA = 0;
    	SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;	// Master mode
    	SpiaRegs.SPICTL.bit.TALK = 1;	// enabled transmission
    	SpiaRegs.SPICTL.bit.CLK_PHASE = 1;	// no delay
    
    	SpiaRegs.SPIBRR = 124;	// 150MHz/4/(124+1)= 300 kHz
    
    	SpiaRegs.SPICCR.bit.SPISWRESET = 1;	// relinquish SPI from reset
    }
    


    Obsługa transmisji:
    
    /*-----------------------------------------------------------------------*/
    /* MMC/SDC (in SPI mode) control module  (C)ChaN, 2007                   */
    /*-----------------------------------------------------------------------*/
    /* Only rcvr_spi(), xmit_spi(), disk_timerproc() and some macros         */
    /* are platform dependent.                                               */
    /*-----------------------------------------------------------------------*/
    #include "spi_sd.h"
    #include "diskio.h"
    #include "DSP281x_Device.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 */
    
    /*--------------------------------------------------------------------------
    
       Module Private Functions
    
    ---------------------------------------------------------------------------*/
    
    typedef enum { TRUE = 1, FALSE = 0 } bool;
    
    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 */
    
    static
    void SELECT (void) 		// CS w stan niski
    {
    	EALLOW;
    	GpioDataRegs.GPBDAT.bit.GPIOB10 = 0;
    	EDIS;
    }
    
    static
    void DESELECT (void) 	// CS w stan wysoki
    {
    	EALLOW;
    	GpioDataRegs.GPBDAT.bit.GPIOB10 = 1;
    	EDIS;
    }
    
    void SPI_SD_Init( void )
    {
        SPI_Init();
    
    	DESELECT();
    }
    
    static
    void xmit_spi (BYTE Data)  // Wyslanie bajtu do SD
    {
    	SpiaRegs.SPITXBUF = Data << 8;
    	while (!SpiaRegs.SPISTS.bit.INT_FLAG)
    		;
    	SpiaRegs.SPIRXBUF = SpiaRegs.SPIRXBUF;
    }
    
    static
    BYTE rcvr_spi (void) 		// Odebranie bajtu z SD
    {
      u8 Data = 0;
    
    	SpiaRegs.SPITXBUF = 0xFF << 8;
    	while (!SpiaRegs.SPISTS.bit.INT_FLAG)
    		;
    	Data = SpiaRegs.SPIRXBUF;
    
    
      return Data;
    }
    
    
    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;
    }
    
    /*-----------------------------------------------------------------------*/
    /* 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)
    {
    	u8 i;
    
      DESELECT();      // CS = 1
    
      //Wyslanie 10 razy 0xFF co daje ponad 80 (>74) cykle zegara
      //wymagane przez specyfikacje SD
      for (i = 0; i < 10; i++)
        xmit_spi(0xFF);
    
      PowerFlag = 1;
    }
    
    
    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 = 10;
        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;
    	u32 i = 0;
    
        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);
    
     		rcvr_spi();
    		rcvr_spi();
    
    		while (i <= 64)
    		{
            	resp = rcvr_spi();                /* Reveive data response */
            	if ((resp & 0x1F) == 0x05)        /* If not accepted, return with error */
                	break;
    			i++;
        	}
    		while (rcvr_spi() == 0);
    	}
    	if ((resp & 0x1F) == 0x05)
    		return TRUE;
    	else
    		return FALSE;
    }
    #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);
        xmit_spi(0xFF);
    
        /* 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 */
    }
    
    
    
    /*--------------------------------------------------------------------------
    
       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();
    
        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 */
    	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_cmd(CMD12, 0);                /* 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  ((2011UL-1980) << 25)    // Year = 2011
                | (1UL << 21)            // Month = January
                | (1UL << 16)            // Day = 1
                | (12U << 11)            // Hour = 12
                | (0U << 5)              // Min = 00
                | (0U >> 1)              // Sec = 00
                ;
    
    }
    


    Od res1 do res5 zwracane jest FR_OK

    f_write() w res6 zwraca FR_DISK_ERR
REKLAMA