Attic: tar up 'original-pff' for less clutter on grep'ing.
This commit is contained in:
parent
c79dc3206e
commit
4c4f2603f5
Binary file not shown.
|
|
@ -1,46 +0,0 @@
|
||||||
Petit FatFs Module Source Files R0.03 (C)ChaN, 2014
|
|
||||||
|
|
||||||
|
|
||||||
FILES
|
|
||||||
|
|
||||||
pff.h Common include file for Petit FatFs and application module.
|
|
||||||
pff.c Petit FatFs module.
|
|
||||||
diskio.h Common include file for Petit FatFs and disk I/O module.
|
|
||||||
diskio.c Skeleton of low level disk I/O module.
|
|
||||||
integer.h Alternative type definitions for integer variables.
|
|
||||||
|
|
||||||
Low level disk I/O module is not included in this archive because the Petit
|
|
||||||
FatFs module is only a generic file system layer and not depend on any
|
|
||||||
specific storage device. You have to provide a low level disk I/O module that
|
|
||||||
written to control your storage device.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AGREEMENTS
|
|
||||||
|
|
||||||
Petit FatFs module is an open source software to implement FAT file system to
|
|
||||||
small embedded systems. This is a free software and is opened for education,
|
|
||||||
research and commercial developments under license policy of following trems.
|
|
||||||
|
|
||||||
Copyright (C) 2014, ChaN, all right reserved.
|
|
||||||
|
|
||||||
* The Petit FatFs module is a free software and there is NO WARRANTY.
|
|
||||||
* No restriction on use. You can use, modify and redistribute it for
|
|
||||||
personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
|
|
||||||
* Redistributions of source code must retain the above copyright notice.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
REVISION HISTORY
|
|
||||||
|
|
||||||
Jun 15, 2009 R0.01a First release (Branched from FatFs R0.07b)
|
|
||||||
|
|
||||||
Dec 14, 2009 R0.02 Added multiple code page support.
|
|
||||||
Added write funciton.
|
|
||||||
Changed stream read mode interface.
|
|
||||||
Dec 07,'2010 R0.02a Added some configuration options.
|
|
||||||
Fixed fails to open objects with DBCS character.
|
|
||||||
|
|
||||||
Jun 10, 2014 R0.03 Separated out configuration options to pffconf.h.
|
|
||||||
Added _USE_LCC option.
|
|
||||||
Added _FS_FAT16 option.
|
|
||||||
|
|
@ -1,261 +0,0 @@
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
/* PFF - Low level disk control module for AVR (C)ChaN, 2014 */
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "pff.h"
|
|
||||||
#include "diskio.h"
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
/* Platform dependent macros and functions needed to be modified */
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include <avr/io.h> /* Device specific include files */
|
|
||||||
|
|
||||||
#define SELECT() PORTB &= ~_BV(3) /* CS = L */
|
|
||||||
#define DESELECT() PORTB |= _BV(3) /* CS = H */
|
|
||||||
#define SELECTING !(PORTB & _BV(3)) /* CS status (true:CS low) */
|
|
||||||
#define FORWARD(d) xmit(d) /* Data forwarding function (console out) */
|
|
||||||
|
|
||||||
void xmit (char); /* suart.S: Send a byte via software UART */
|
|
||||||
void dly_100us (void); /* usi.S: Delay 100 microseconds */
|
|
||||||
void init_spi (void); /* usi.S: Initialize MMC control ports */
|
|
||||||
void xmit_spi (BYTE d); /* usi.S: Send a byte to the MMC */
|
|
||||||
BYTE rcv_spi (void); /* usi.S: Send a 0xFF to the MMC and get the received byte */
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Module Private Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Definitions for MMC/SDC command */
|
|
||||||
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
|
|
||||||
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
|
|
||||||
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
|
|
||||||
#define CMD8 (0x40+8) /* SEND_IF_COND */
|
|
||||||
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
|
|
||||||
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
|
|
||||||
#define CMD24 (0x40+24) /* WRITE_BLOCK */
|
|
||||||
#define CMD55 (0x40+55) /* APP_CMD */
|
|
||||||
#define CMD58 (0x40+58) /* READ_OCR */
|
|
||||||
|
|
||||||
|
|
||||||
/* Card type flags (CardType) */
|
|
||||||
#define CT_MMC 0x01 /* MMC ver 3 */
|
|
||||||
#define CT_SD1 0x02 /* SD ver 1 */
|
|
||||||
#define CT_SD2 0x04 /* SD ver 2 */
|
|
||||||
#define CT_BLOCK 0x08 /* Block addressing */
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE CardType;
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Send a command packet to MMC */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE send_cmd (
|
|
||||||
BYTE cmd, /* 1st byte (Start + Index) */
|
|
||||||
DWORD arg /* Argument (32 bits) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
BYTE n, res;
|
|
||||||
|
|
||||||
|
|
||||||
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
|
|
||||||
cmd &= 0x7F;
|
|
||||||
res = send_cmd(CMD55, 0);
|
|
||||||
if (res > 1) return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the card */
|
|
||||||
DESELECT();
|
|
||||||
rcv_spi();
|
|
||||||
SELECT();
|
|
||||||
rcv_spi();
|
|
||||||
|
|
||||||
/* Send a command packet */
|
|
||||||
xmit_spi(cmd); /* Start + Command index */
|
|
||||||
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 = 0x01; /* Dummy CRC + Stop */
|
|
||||||
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
|
|
||||||
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
|
|
||||||
xmit_spi(n);
|
|
||||||
|
|
||||||
/* Receive a command response */
|
|
||||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
|
||||||
do {
|
|
||||||
res = rcv_spi();
|
|
||||||
} while ((res & 0x80) && --n);
|
|
||||||
|
|
||||||
return res; /* Return with the response value */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Public Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Initialize Disk Drive */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DSTATUS disk_initialize (void)
|
|
||||||
{
|
|
||||||
BYTE n, cmd, ty, ocr[4];
|
|
||||||
UINT tmr;
|
|
||||||
|
|
||||||
#if _USE_WRITE
|
|
||||||
if (CardType && SELECTING) disk_writep(0, 0); /* Finalize write process if it is in progress */
|
|
||||||
#endif
|
|
||||||
init_spi(); /* Initialize ports to control MMC */
|
|
||||||
DESELECT();
|
|
||||||
for (n = 10; n; n--) rcv_spi(); /* 80 dummy clocks with CS=H */
|
|
||||||
|
|
||||||
ty = 0;
|
|
||||||
if (send_cmd(CMD0, 0) == 1) { /* GO_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();
|
|
||||||
|
|
||||||
return ty ? 0 : STA_NOINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Read partial sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DRESULT disk_readp (
|
|
||||||
BYTE *buff, /* Pointer to the read buffer (NULL:Forward to the stream) */
|
|
||||||
DWORD sector, /* Sector number (LBA) */
|
|
||||||
UINT offset, /* Byte offset to read from (0..511) */
|
|
||||||
UINT count /* Number of bytes to read (ofs + cnt mus be <= 512) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
BYTE rc;
|
|
||||||
UINT bc;
|
|
||||||
|
|
||||||
|
|
||||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */
|
|
||||||
|
|
||||||
bc = 40000; /* Time counter */
|
|
||||||
do { /* Wait for data packet */
|
|
||||||
rc = rcv_spi();
|
|
||||||
} while (rc == 0xFF && --bc);
|
|
||||||
|
|
||||||
if (rc == 0xFE) { /* A data packet arrived */
|
|
||||||
|
|
||||||
bc = 512 + 2 - offset - count; /* Number of trailing bytes to skip */
|
|
||||||
|
|
||||||
/* Skip leading bytes */
|
|
||||||
while (offset--) rcv_spi();
|
|
||||||
|
|
||||||
/* Receive a part of the sector */
|
|
||||||
if (buff) { /* Store data to the memory */
|
|
||||||
do {
|
|
||||||
*buff++ = rcv_spi();
|
|
||||||
} while (--count);
|
|
||||||
} else { /* Forward data to the outgoing stream */
|
|
||||||
do {
|
|
||||||
FORWARD(rcv_spi());
|
|
||||||
} while (--count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip trailing bytes and CRC */
|
|
||||||
do rcv_spi(); while (--bc);
|
|
||||||
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DESELECT();
|
|
||||||
rcv_spi();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Write partial sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if _USE_WRITE
|
|
||||||
DRESULT disk_writep (
|
|
||||||
const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
|
|
||||||
DWORD sc /* Number of bytes to send, Sector number (LBA) or zero */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
UINT bc;
|
|
||||||
static UINT wc; /* Sector write counter */
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
|
|
||||||
if (buff) { /* Send data bytes */
|
|
||||||
bc = sc;
|
|
||||||
while (bc && wc) { /* Send data bytes to the card */
|
|
||||||
xmit_spi(*buff++);
|
|
||||||
wc--; bc--;
|
|
||||||
}
|
|
||||||
res = RES_OK;
|
|
||||||
} else {
|
|
||||||
if (sc) { /* Initiate sector write process */
|
|
||||||
if (!(CardType & CT_BLOCK)) sc *= 512; /* Convert to byte address if needed */
|
|
||||||
if (send_cmd(CMD24, sc) == 0) { /* WRITE_SINGLE_BLOCK */
|
|
||||||
xmit_spi(0xFF); xmit_spi(0xFE); /* Data block header */
|
|
||||||
wc = 512; /* Set byte counter */
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
} else { /* Finalize sector write process */
|
|
||||||
bc = wc + 2;
|
|
||||||
while (bc--) xmit_spi(0); /* Fill left bytes and CRC with zeros */
|
|
||||||
if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 500ms */
|
|
||||||
for (bc = 5000; rcv_spi() != 0xFF && bc; bc--) /* Wait for ready */
|
|
||||||
dly_100us();
|
|
||||||
if (bc) res = RES_OK;
|
|
||||||
}
|
|
||||||
DESELECT();
|
|
||||||
rcv_spi();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Low level disk I/O module skeleton for Petit FatFs (C)ChaN, 2014 */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "diskio.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Initialize Disk Drive */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DSTATUS disk_initialize (void)
|
|
||||||
{
|
|
||||||
DSTATUS stat;
|
|
||||||
|
|
||||||
// Put your code here
|
|
||||||
|
|
||||||
return stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Read Partial Sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DRESULT disk_readp (
|
|
||||||
BYTE* buff, /* Pointer to the destination object */
|
|
||||||
DWORD sector, /* Sector number (LBA) */
|
|
||||||
UINT offset, /* Offset in the sector */
|
|
||||||
UINT count /* Byte count (bit15:destination) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
|
|
||||||
// Put your code here
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Write Partial Sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DRESULT disk_writep (
|
|
||||||
BYTE* buff, /* Pointer to the data to be written, NULL:Initiate/Finalize write operation */
|
|
||||||
DWORD sc /* Sector number (LBA) or Number of bytes to send */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
|
|
||||||
|
|
||||||
if (!buff) {
|
|
||||||
if (sc) {
|
|
||||||
|
|
||||||
// Initiate write process
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Finalize write process
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Send data to the disk
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
/*-----------------------------------------------------------------------
|
|
||||||
/ PFF - Low level disk interface modlue include file (C)ChaN, 2014
|
|
||||||
/-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef _DISKIO_DEFINED
|
|
||||||
#define _DISKIO_DEFINED
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "integer.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
|
||||||
typedef BYTE DSTATUS;
|
|
||||||
|
|
||||||
|
|
||||||
/* Results of Disk Functions */
|
|
||||||
typedef enum {
|
|
||||||
RES_OK = 0, /* 0: Function succeeded */
|
|
||||||
RES_ERROR, /* 1: Disk error */
|
|
||||||
RES_NOTRDY, /* 2: Not ready */
|
|
||||||
RES_PARERR /* 3: Invalid parameter */
|
|
||||||
} DRESULT;
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------*/
|
|
||||||
/* Prototypes for disk control functions */
|
|
||||||
|
|
||||||
DSTATUS disk_initialize (void);
|
|
||||||
DRESULT disk_readp (BYTE* buff, DWORD sector, UINT offser, UINT count);
|
|
||||||
DRESULT disk_writep (const BYTE* buff, DWORD sc);
|
|
||||||
|
|
||||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
|
||||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _DISKIO_DEFINED */
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
/*-------------------------------------------*/
|
|
||||||
/* Integer type definitions for FatFs module */
|
|
||||||
/*-------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef _FF_INTEGER
|
|
||||||
#define _FF_INTEGER
|
|
||||||
|
|
||||||
#ifdef _WIN32 /* FatFs development platform */
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <tchar.h>
|
|
||||||
|
|
||||||
#else /* Embedded platform */
|
|
||||||
|
|
||||||
/* This type MUST be 8 bit */
|
|
||||||
typedef unsigned char BYTE;
|
|
||||||
|
|
||||||
/* These types MUST be 16 bit */
|
|
||||||
typedef short SHORT;
|
|
||||||
typedef unsigned short WORD;
|
|
||||||
typedef unsigned short WCHAR;
|
|
||||||
|
|
||||||
/* These types MUST be 16 bit or 32 bit */
|
|
||||||
typedef int INT;
|
|
||||||
typedef unsigned int UINT;
|
|
||||||
|
|
||||||
/* These types MUST be 32 bit */
|
|
||||||
typedef long LONG;
|
|
||||||
typedef unsigned long DWORD;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,159 +0,0 @@
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ Petit FatFs - FAT file system module include file R0.03 (C)ChaN, 2014
|
|
||||||
/----------------------------------------------------------------------------/
|
|
||||||
/ Petit FatFs module is an open source software to implement FAT file system to
|
|
||||||
/ small embedded systems. This is a free software and is opened for education,
|
|
||||||
/ research and commercial developments under license policy of following trems.
|
|
||||||
/
|
|
||||||
/ Copyright (C) 2014, ChaN, all right reserved.
|
|
||||||
/
|
|
||||||
/ * The Petit FatFs module is a free software and there is NO WARRANTY.
|
|
||||||
/ * No restriction on use. You can use, modify and redistribute it for
|
|
||||||
/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
|
|
||||||
/ * Redistributions of source code must retain the above copyright notice.
|
|
||||||
/
|
|
||||||
/----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef _PFATFS
|
|
||||||
#define _PFATFS 4004 /* Revision ID */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "integer.h"
|
|
||||||
#include "pffconf.h"
|
|
||||||
|
|
||||||
#if _PFATFS != _PFFCONF
|
|
||||||
#error Wrong configuration file (pffconf.h).
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _FS_FAT32
|
|
||||||
#define CLUST DWORD
|
|
||||||
#else
|
|
||||||
#define CLUST WORD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* File system object structure */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BYTE fs_type; /* FAT sub type */
|
|
||||||
BYTE flag; /* File status flags */
|
|
||||||
BYTE csize; /* Number of sectors per cluster */
|
|
||||||
BYTE pad1;
|
|
||||||
WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */
|
|
||||||
CLUST n_fatent; /* Number of FAT entries (= number of clusters + 2) */
|
|
||||||
DWORD fatbase; /* FAT start sector */
|
|
||||||
DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */
|
|
||||||
DWORD database; /* Data start sector */
|
|
||||||
DWORD fptr; /* File R/W pointer */
|
|
||||||
DWORD fsize; /* File size */
|
|
||||||
CLUST org_clust; /* File start cluster */
|
|
||||||
CLUST curr_clust; /* File current cluster */
|
|
||||||
DWORD dsect; /* File current data sector */
|
|
||||||
} FATFS;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Directory object structure */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
WORD index; /* Current read/write index number */
|
|
||||||
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
|
||||||
CLUST sclust; /* Table start cluster (0:Static table) */
|
|
||||||
CLUST clust; /* Current cluster */
|
|
||||||
DWORD sect; /* Current sector */
|
|
||||||
} DIR;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File status structure */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
DWORD fsize; /* File size */
|
|
||||||
WORD fdate; /* Last modified date */
|
|
||||||
WORD ftime; /* Last modified time */
|
|
||||||
BYTE fattrib; /* Attribute */
|
|
||||||
char fname[13]; /* File name */
|
|
||||||
} FILINFO;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File function return code (FRESULT) */
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FR_OK = 0, /* 0 */
|
|
||||||
FR_DISK_ERR, /* 1 */
|
|
||||||
FR_NOT_READY, /* 2 */
|
|
||||||
FR_NO_FILE, /* 3 */
|
|
||||||
FR_NOT_OPENED, /* 4 */
|
|
||||||
FR_NOT_ENABLED, /* 5 */
|
|
||||||
FR_NO_FILESYSTEM /* 6 */
|
|
||||||
} FRESULT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------*/
|
|
||||||
/* Petit FatFs module application interface */
|
|
||||||
|
|
||||||
FRESULT pf_mount (FATFS* fs); /* Mount/Unmount a logical drive */
|
|
||||||
FRESULT pf_open (const char* path); /* Open a file */
|
|
||||||
FRESULT pf_read (void* buff, UINT btr, UINT* br); /* Read data from the open file */
|
|
||||||
FRESULT pf_write (const void* buff, UINT btw, UINT* bw); /* Write data to the open file */
|
|
||||||
FRESULT pf_lseek (DWORD ofs); /* Move file pointer of the open file */
|
|
||||||
FRESULT pf_opendir (DIR* dj, const char* path); /* Open a directory */
|
|
||||||
FRESULT pf_readdir (DIR* dj, FILINFO* fno); /* Read a directory item from the open directory */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------*/
|
|
||||||
/* Flags and offset address */
|
|
||||||
|
|
||||||
/* File status flag (FATFS.flag) */
|
|
||||||
|
|
||||||
#define FA_OPENED 0x01
|
|
||||||
#define FA_WPRT 0x02
|
|
||||||
#define FA__WIP 0x40
|
|
||||||
|
|
||||||
|
|
||||||
/* FAT sub type (FATFS.fs_type) */
|
|
||||||
|
|
||||||
#define FS_FAT12 1
|
|
||||||
#define FS_FAT16 2
|
|
||||||
#define FS_FAT32 3
|
|
||||||
|
|
||||||
|
|
||||||
/* File attribute bits for directory entry */
|
|
||||||
|
|
||||||
#define AM_RDO 0x01 /* Read only */
|
|
||||||
#define AM_HID 0x02 /* Hidden */
|
|
||||||
#define AM_SYS 0x04 /* System */
|
|
||||||
#define AM_VOL 0x08 /* Volume label */
|
|
||||||
#define AM_LFN 0x0F /* LFN entry */
|
|
||||||
#define AM_DIR 0x10 /* Directory */
|
|
||||||
#define AM_ARC 0x20 /* Archive */
|
|
||||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------*/
|
|
||||||
/* Multi-byte word access macros */
|
|
||||||
|
|
||||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
|
||||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
|
||||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
|
||||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
|
||||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
|
||||||
#else /* Use byte-by-byte access to the FAT structure */
|
|
||||||
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
|
||||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
|
|
||||||
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
|
|
||||||
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _PFATFS */
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ Petit FatFs - Configuration file R0.03 (C)ChaN, 2014
|
|
||||||
/---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef _PFFCONF
|
|
||||||
#define _PFFCONF 4004 /* Revision ID */
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ Function Configurations
|
|
||||||
/---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define _USE_READ 1 /* Enable pf_read() function */
|
|
||||||
#define _USE_DIR 0 /* Enable pf_opendir() and pf_readdir() function */
|
|
||||||
#define _USE_LSEEK 0 /* Enable pf_lseek() function */
|
|
||||||
#define _USE_WRITE 0 /* Enable pf_write() function */
|
|
||||||
|
|
||||||
#define _FS_FAT12 0 /* Enable FAT12 */
|
|
||||||
#define _FS_FAT16 1 /* Enable FAT16 */
|
|
||||||
#define _FS_FAT32 0 /* Enable FAT32 */
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ Locale and Namespace Configurations
|
|
||||||
/---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define _USE_LCC 0 /* Allow lower case characters for path name */
|
|
||||||
|
|
||||||
#define _CODE_PAGE 437
|
|
||||||
/* The _CODE_PAGE specifies the code page to be used on the target system.
|
|
||||||
/ SBCS code pages with _USE_LCC == 1 requiers a 128 byte of case conversion
|
|
||||||
/ table. This might occupy RAM on some platforms, e.g. avr-gcc.
|
|
||||||
/ When _USE_LCC == 0, _CODE_PAGE has no effect.
|
|
||||||
/
|
|
||||||
/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
|
|
||||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
|
||||||
/ 949 - Korean (DBCS, OEM, Windows)
|
|
||||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
|
||||||
/ 1250 - Central Europe (Windows)
|
|
||||||
/ 1251 - Cyrillic (Windows)
|
|
||||||
/ 1252 - Latin 1 (Windows)
|
|
||||||
/ 1253 - Greek (Windows)
|
|
||||||
/ 1254 - Turkish (Windows)
|
|
||||||
/ 1255 - Hebrew (Windows)
|
|
||||||
/ 1256 - Arabic (Windows)
|
|
||||||
/ 1257 - Baltic (Windows)
|
|
||||||
/ 1258 - Vietnam (OEM, Windows)
|
|
||||||
/ 437 - U.S. (OEM)
|
|
||||||
/ 720 - Arabic (OEM)
|
|
||||||
/ 737 - Greek (OEM)
|
|
||||||
/ 775 - Baltic (OEM)
|
|
||||||
/ 850 - Multilingual Latin 1 (OEM)
|
|
||||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
|
||||||
/ 852 - Latin 2 (OEM)
|
|
||||||
/ 855 - Cyrillic (OEM)
|
|
||||||
/ 866 - Russian (OEM)
|
|
||||||
/ 857 - Turkish (OEM)
|
|
||||||
/ 862 - Hebrew (OEM)
|
|
||||||
/ 874 - Thai (OEM, Windows)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ System Configurations
|
|
||||||
/---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define _WORD_ACCESS 0
|
|
||||||
/* The _WORD_ACCESS option is an only platform dependent option. It defines
|
|
||||||
/ which access method is used to the word data on the FAT volume.
|
|
||||||
/
|
|
||||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
|
||||||
/ 1: Word access. Do not choose this unless under both the following conditions.
|
|
||||||
/
|
|
||||||
/ * Address misaligned memory access is always allowed for ALL instructions.
|
|
||||||
/ * Byte order on the memory is little-endian.
|
|
||||||
/
|
|
||||||
/ If it is the case, _WORD_ACCESS can also be set to 1 to improve performance and
|
|
||||||
/ reduce code size. Following table shows an example of some processor types.
|
|
||||||
/
|
|
||||||
/ ARM7TDMI 0 ColdFire 0 V850E 0
|
|
||||||
/ Cortex-M3 0 Z80 0/1 V850ES 0/1
|
|
||||||
/ Cortex-M0 0 RX600(LE) 0/1 TLCS-870 0/1
|
|
||||||
/ AVR 0/1 RX600(BE) 0 TLCS-900 0/1
|
|
||||||
/ AVR32 0 RL78 0 R32C 0
|
|
||||||
/ PIC18 0/1 SH-2 0 M16C 0/1
|
|
||||||
/ PIC24 0 H8S 0 MSP430 0
|
|
||||||
/ PIC32 0 H8/300H 0 x86 0/1
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif /* _PFFCONF */
|
|
||||||
|
|
@ -1,290 +0,0 @@
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
/* PFF - Low level disk control module for PIC (C)ChaN, 2014 */
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "pff.h"
|
|
||||||
#include "diskio.h"
|
|
||||||
#include "uart.h"
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
/* Platform dependent macros and functions needed to be modified */
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include <p24FJ64GA002.h> /* Device include file */
|
|
||||||
#include "pic24f.h"
|
|
||||||
#include "uart.h"
|
|
||||||
|
|
||||||
#define SELECT() _LATB15 = 0 /* CS = L */
|
|
||||||
#define DESELECT() _LATB15 = 1 /* CS = H */
|
|
||||||
#define MMC_SEL !_LATB15 /* CS status (true:CS == L) */
|
|
||||||
#define FORWARD(d) uart_put(d) /* Data forwarding function (Console out in this example) */
|
|
||||||
|
|
||||||
static
|
|
||||||
void init_spi (void) /* Initialize SPI port */
|
|
||||||
{
|
|
||||||
SPI1CON1 = 0x013B;
|
|
||||||
SPI1CON2 = 0x0000;
|
|
||||||
_SPIEN = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dly_100us (void) /* Delay 100 microseconds */
|
|
||||||
{
|
|
||||||
UINT n = FCY / 100000;
|
|
||||||
do {
|
|
||||||
LATA; LATA; LATA; LATA; LATA; LATA;
|
|
||||||
} while (--n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void xmit_spi (BYTE d) /* Send a byte to the SDC/MMC */
|
|
||||||
{
|
|
||||||
SPI1BUF = d;
|
|
||||||
while (!_SPIRBF) ;
|
|
||||||
SPI1BUF;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE rcv_spi (void) /* Send a 0xFF to the SDC/MMC and get the received byte */
|
|
||||||
{
|
|
||||||
SPI1BUF = 0xFF;
|
|
||||||
while (!_SPIRBF) ;
|
|
||||||
return (BYTE)SPI1BUF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Module Private Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Definitions for MMC/SDC command */
|
|
||||||
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
|
|
||||||
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
|
|
||||||
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
|
|
||||||
#define CMD8 (0x40+8) /* SEND_IF_COND */
|
|
||||||
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
|
|
||||||
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
|
|
||||||
#define CMD24 (0x40+24) /* WRITE_BLOCK */
|
|
||||||
#define CMD55 (0x40+55) /* APP_CMD */
|
|
||||||
#define CMD58 (0x40+58) /* READ_OCR */
|
|
||||||
|
|
||||||
|
|
||||||
/* Card type flags (CardType) */
|
|
||||||
#define CT_MMC 0x01 /* MMC ver 3 */
|
|
||||||
#define CT_SD1 0x02 /* SD ver 1 */
|
|
||||||
#define CT_SD2 0x04 /* SD ver 2 */
|
|
||||||
#define CT_BLOCK 0x08 /* Block addressing */
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE CardType;
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Send a command packet to the SDC/MMC */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static
|
|
||||||
BYTE send_cmd (
|
|
||||||
BYTE cmd, /* 1st byte (Start + Index) */
|
|
||||||
DWORD arg /* Argument (32 bits) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
BYTE n, res;
|
|
||||||
|
|
||||||
|
|
||||||
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
|
|
||||||
cmd &= 0x7F;
|
|
||||||
res = send_cmd(CMD55, 0);
|
|
||||||
if (res > 1) return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the card */
|
|
||||||
DESELECT();
|
|
||||||
rcv_spi();
|
|
||||||
SELECT();
|
|
||||||
rcv_spi();
|
|
||||||
|
|
||||||
/* Send a command packet */
|
|
||||||
xmit_spi(cmd); /* Start + Command index */
|
|
||||||
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 = 0x01; /* Dummy CRC + Stop */
|
|
||||||
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
|
|
||||||
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
|
|
||||||
xmit_spi(n);
|
|
||||||
|
|
||||||
/* Receive a command response */
|
|
||||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
|
||||||
do {
|
|
||||||
res = rcv_spi();
|
|
||||||
} while ((res & 0x80) && --n);
|
|
||||||
|
|
||||||
return res; /* Return with the response value */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Public Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Initialize Disk Drive */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DSTATUS disk_initialize (void)
|
|
||||||
{
|
|
||||||
BYTE n, cmd, ty, ocr[4];
|
|
||||||
UINT tmr;
|
|
||||||
|
|
||||||
#if _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 SDC/MMC */
|
|
||||||
DESELECT();
|
|
||||||
for (n = 10; n; n--) rcv_spi(); /* 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] = 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();
|
|
||||||
|
|
||||||
return ty ? 0 : STA_NOINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Read partial sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
DRESULT disk_readp (
|
|
||||||
BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
|
|
||||||
DWORD sector, /* Sector number (LBA) */
|
|
||||||
UINT offset, /* Byte offset to read from (0..511) */
|
|
||||||
UINT count /* Number of bytes to read (ofs + cnt mus be <= 512) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
BYTE rc;
|
|
||||||
UINT bc;
|
|
||||||
|
|
||||||
|
|
||||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */
|
|
||||||
|
|
||||||
bc = 40000;
|
|
||||||
do { /* Wait for data packet */
|
|
||||||
rc = rcv_spi();
|
|
||||||
} while (rc == 0xFF && --bc);
|
|
||||||
|
|
||||||
if (rc == 0xFE) { /* A data packet arrived */
|
|
||||||
bc = 514 - offset - count;
|
|
||||||
|
|
||||||
/* Skip leading bytes */
|
|
||||||
if (offset) {
|
|
||||||
do rcv_spi(); while (--offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Receive a part of the sector */
|
|
||||||
if (buff) { /* Store data to the memory */
|
|
||||||
do {
|
|
||||||
*buff++ = rcv_spi();
|
|
||||||
} while (--count);
|
|
||||||
} else { /* Forward data to the outgoing stream (depends on the project) */
|
|
||||||
do {
|
|
||||||
FORWARD(rcv_spi());
|
|
||||||
} while (--count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip remaining bytes and CRC */
|
|
||||||
do rcv_spi(); while (--bc);
|
|
||||||
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DESELECT();
|
|
||||||
rcv_spi();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Write partial sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if _USE_WRITE
|
|
||||||
DRESULT disk_writep (
|
|
||||||
const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
|
|
||||||
DWORD sc /* Number of bytes to send, Sector number (LBA) or zero */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
UINT bc;
|
|
||||||
static WORD wc;
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
|
|
||||||
if (buff) { /* Send data bytes */
|
|
||||||
bc = (WORD)sc;
|
|
||||||
while (bc && wc) { /* Send data bytes to the card */
|
|
||||||
xmit_spi(*buff++);
|
|
||||||
wc--; bc--;
|
|
||||||
}
|
|
||||||
res = RES_OK;
|
|
||||||
} else {
|
|
||||||
if (sc) { /* Initiate sector write process */
|
|
||||||
if (!(CardType & CT_BLOCK)) sc *= 512; /* Convert to byte address if needed */
|
|
||||||
if (send_cmd(CMD24, sc) == 0) { /* WRITE_SINGLE_BLOCK */
|
|
||||||
xmit_spi(0xFF); xmit_spi(0xFE); /* Data block header */
|
|
||||||
wc = 512; /* Set byte counter */
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
} else { /* Finalize sector write process */
|
|
||||||
bc = wc + 2;
|
|
||||||
while (bc--) xmit_spi(0); /* Fill left bytes and CRC with zeros */
|
|
||||||
if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 500ms */
|
|
||||||
for (bc = 5000; rcv_spi() != 0xFF && bc; bc--) dly_100us(); /* Wait ready */
|
|
||||||
if (bc) res = RES_OK;
|
|
||||||
}
|
|
||||||
DESELECT();
|
|
||||||
rcv_spi();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Loading…
Reference in New Issue