Attic: tar up 'original-pff' for less clutter on grep'ing.

This commit is contained in:
Markus Hitter 2016-06-12 19:18:47 +02:00
parent c79dc3206e
commit 4c4f2603f5
11 changed files with 0 additions and 2099 deletions

BIN
attic/original-pff.tar.gz Normal file

Binary file not shown.

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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