FRESULT pf_write ( const void* buff, /* Pointer to the data to be written */ UINT btw, /* Number of bytes to write (0:Finalize the current write operation) */ UINT* bw /* Pointer to number of bytes written */ ) { CLUST clst; DWORD sect, remain; const BYTE *p = buff; BYTE cs; UINT wcnt; FATFS *fs = FatFs; *bw = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; if (!btw) { /* Finalize request */ if ((fs->flag & FA__WIP) && disk_writep(0, 0)) ABORT(FR_DISK_ERR); fs->flag &= ~FA__WIP; return FR_OK; } else { /* Write data request */ if (!(fs->flag & FA__WIP)) /* Round-down fptr to the sector boundary */ fs->fptr &= 0xFFFFFE00; } remain = fs->fsize - fs->fptr; if (btw > remain) btw = (UINT)remain; /* Truncate btw by remaining bytes */ while (btw) { /* Repeat until all data transferred */ if ((UINT)fs->fptr % 512 == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ if (fs->fptr == 0) /* On the top of the file? */ clst = fs->org_clust; else clst = get_fat(fs->curr_clust); if (clst <= 1) ABORT(FR_DISK_ERR); fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) ABORT(FR_DISK_ERR); fs->dsect = sect + cs; if (disk_writep(0, fs->dsect)) ABORT(FR_DISK_ERR); /* Initiate a sector write operation */ fs->flag |= FA__WIP; } wcnt = 512 - (UINT)fs->fptr % 512; /* Number of bytes to write to the sector */ if (wcnt > btw) wcnt = btw; if (disk_writep(p, wcnt)) ABORT(FR_DISK_ERR); /* Send data to the sector */ fs->fptr += wcnt; p += wcnt; /* Update pointers and counters */ btw -= wcnt; *bw += wcnt; if ((UINT)fs->fptr % 512 == 0) { if (disk_writep(0, 0)) ABORT(FR_DISK_ERR); /* Finalize the currtent secter write operation */ fs->flag &= ~FA__WIP; } } return FR_OK; }
FRESULT pf_write ( const void* buff, /* Pointer to the data to be written */ u16 btw, /* Number of bytes to write (0:Finalize the current write operation) */ u16* bw /* Pointer to number of bytes written */ ) { CLUST clst; u32 sect, remain; const u8 *p = buff; u16 wcnt; FATFS *fs = FatFs; *bw = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; if (!btw) { /* Finalize request */ if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort; fs->flag &= ~FA__WIP; return FR_OK; } else { /* Write data request */ if (!(fs->flag & FA__WIP)) /* Round down fptr to the sector boundary */ fs->fptr &= 0xFFFFFE00; } remain = fs->fsize - fs->fptr; if (btw > remain) btw = (u16)remain; /* Truncate btw by remaining bytes */ while (btw) { /* Repeat until all data transferred */ if (((u16)fs->fptr % 512) == 0) { /* On the sector boundary? */ if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) goto fw_abort; fs->curr_clust = clst; /* Update current cluster */ fs->csect = 0; /* Reset sector offset in the cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) goto fw_abort; fs->dsect = sect + fs->csect++; if (disk_writep(0, fs->dsect)) goto fw_abort; /* Initiate a sector write operation */ fs->flag |= FA__WIP; } wcnt = 512 - ((u16)fs->fptr % 512); /* Number of bytes to write to the sector */ if (wcnt > btw) wcnt = btw; if (disk_writep(p, wcnt)) goto fw_abort; /* Send data to the sector */ fs->fptr += wcnt; p += wcnt; /* Update pointers and counters */ btw -= wcnt; *bw += wcnt; if (((u16)fs->fptr % 512) == 0) { if (disk_writep(0, 0)) goto fw_abort; /* Finalize the currtent secter write operation */ fs->flag &= ~FA__WIP; } } return FR_OK; fw_abort: fs->flag = 0; return FR_DISK_ERR; }
DSTATUS disk_initialize (void) { BYTE n, cmd, ty, ocr[4]; UINT tmr; #if _PF_USE_WRITE if (CardType && MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */ #endif init_spi(); /* Initialize ports to control MMC */ DESELECT(); for (n = 100; n; n--) rcv_spi(); /* 80*10 dummy clocks with CS=H */ ty = 0; if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); /* Get trailing return value of R7 resp */ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 10000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) dly_100us(); /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ } } } else { /* SDv1 or MMCv3 */ if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 10000; tmr && send_cmd(cmd, 0); tmr--) dly_100us(); /* Wait for leaving idle state */ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } } CardType = ty; DESELECT(); rcv_spi(); //full speed SPI SPCR = (1<<MSTR)|(1<<SPE); SPSR = 0x01; /* SPI clk 2X */ return ty ? 0 : STA_NOINIT; }
FRESULT pf_write ( const void* buff, /* Pointer to the data to be written */ WORD btw, /* Number of bytes to write (0:Finalize the current write operation) */ WORD* bw /* Pointer to number of bytes written */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; WORD rcnt; BYTE cs; const BYTE *rbuff = buff; FATFS *fs = FatFs; *bw = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; remain = fs->fsize - fs->fptr; if (btw > remain) btw = (WORD)remain; /* Truncate btr by remaining bytes */ while (btw) { /* Repeat until all data transferred */ if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) goto fr_abort; fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) goto fr_abort; fs->dsect = sect + cs; } rcnt = (WORD)(512 - (fs->fptr % 512)); /* Get partial sector data from sector buffer */ if (rcnt > btw) rcnt = btw; dr = disk_writep(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); if (dr) goto fr_abort; fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */ btw -= rcnt; *bw += rcnt; } return FR_OK; fr_abort: fs->flag = 0; return FR_DISK_ERR; }
DSTATUS disk_initialize () { BYTE n, cmd, ty, ocr[4]; UINT tmr; //spi_initialize(); #if _USE_WRITE if (CardType && MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */ #endif //SPI_SET_DIVIDER(128); // 16MHz / 128 = 125kHz DESELECT(); for (n = 10; n; n--) SPI_RECEIVE(); /* 80 dummy clocks with CS=H */ ty = 0; if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ for (n = 0; n < 4; n++) ocr[n] = SPI_RECEIVE(); /* Get trailing return value of R7 resp */ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 10000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) DLY100U();//delayMicroseconds(100); //DELAY_100US(); /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) ocr[n] = SPI_RECEIVE(); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ } } } else { /* SDv1 or MMCv3 */ if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 10000; tmr && send_cmd(cmd, 0); tmr--) DLY100U();//delayMicroseconds(100); //DELAY_100US(); /* Wait for leaving idle state */ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } } CardType = ty; DESELECT(); SPI_RECEIVE(); return ty ? 0 : STA_NOINIT; }
//-------------------------------------------------------------------------- // Initialize Disk Drive //-------------------------------------------------------------------------- DSTATUS disk_initialize (void) { BYTE n, cmd, ty, ocr[4]; WORD tmr; INIT_SPI(); if ((PINB&_BV(SD_INS))!=0x00) return STA_NOINIT; #if _WRITE_FUNC if (MMC_SEL) disk_writep(0, 0); // Finalize write process if it is in progress #endif for (n = 100; n; n--) rcv_spi(); // Dummy clocks ty = 0; if (send_cmd(CMD0, 0) == 1) { // Enter Idle state if (send_cmd(CMD8, 0x1AA) == 1) { // SDv2 for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); // Get trailing return value of R7 resp if (ocr[2] == 0x01 && ocr[3] == 0xAA) { // The card can work at vdd range of 2.7-3.6V for (tmr = 12000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; // Wait for leaving idle state (ACMD41 with HCS bit) if (tmr && send_cmd(CMD58, 0) == 0) { // Check CCS bit in the OCR for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; // SDv2 (HC or SC) } } } else { // SDv1 or MMCv3 if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; // SDv1 } else { ty = CT_MMC; cmd = CMD1; // MMCv3 } for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; // Wait for leaving idle state if (!tmr || send_cmd(CMD16, 512) != 0) // Set R/W block length to 512 ty = 0; } } CardType = ty; release_spi(); return ty ? 0 : STA_NOINIT; }
DSTATUS mmc_initialize (void) { BYTE n, cmd, ty, ocr[4]; WORD tmr; GREENLEDON(); INIT_SPI(); #if _WRITE_FUNC if (MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */ #endif for (n = 11; n; --n) XFER_SPI(0xff); /* Dummy clocks */ ty = 0; if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ for (n = 0; n < 4; n++) { ocr[n] = XFER_SPI(0xff); /* Get trailing return value of R7 resp */ } if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 12000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) ocr[n] = XFER_SPI(0xff); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ } } } else { /* SDv1 or MMCv3 */ if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; /* Wait for leaving idle state */ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ { ty = 0; } } } CardType = ty; release_spi(); GREENLEDOFF(); return ty ? 0 : STA_NOINIT; }