📄 serialflashdriver.c
字号:
/*
**********************************************************************
* Micrium, Inc.
* 949 Crestview Circle
* Weston, FL 33327-1848
*
* uC/FS
*
* (c) Copyright 2001 - 2003, Micrium, Inc.
* All rights reserved.
*
***********************************************************************
----------------------------------------------------------------------
File : mmc_drv.c
Purpose : File system generic MMC/SD driver
---------------------------END-OF-HEADER------------------------------
*/
/*********************************************************************
*
* #include Section
*
**********************************************************************
*/
#include "FS_ConfDefaults.h" /* FS Configuration */
#include "fs_api.h"
#include "FS_Debug.h"
#include "fs_clib.h"
#if FS_USE_SFLASH_DRIVER
#include "SerialFlash_X_HW.h"
/*********************************************************************
*
* Configuration check
*
**********************************************************************
*/
#if (FS_USE_SFLASH_DRIVER != 45)
#error "Please define FS_USE_SFLASH_DRIVER to 45. The driver currently supports ATMEL's DataFlash only."
#endif
/*********************************************************************
*
* defines non configurable
*
**********************************************************************
*/
/******* Commands *********************************************/
#define READ_STATUS 0xd7
#define READ_PAGE 0xd2
#define WRITE2BUFFER 0x84
#define PAGE_PROGRAM 0x82
/******* Serial Flash Types ********************************/
#define FLASH_1MBIT 0x03
#define FLASH_2MBIT 0x05
#define FLASH_4MBIT 0x07
#define FLASH_8MBIT 0x09
#define FLASH_16MBIT 0x0b
#define FLASH_32MBIT 0x0d
/******* Serial Flash specific data **************************/
#define MAX_EXTRABYTES 0x10
#define COMMAND_LENGTH 0x04
#define DUMMY_DATA 0xff
/******* Serial Flash size definitions *********************/
#define PAGE_SIZE_256 256
#define PAGE_SIZE_512 512
#define EXTRABYTES_08 8
#define EXTRABYTES_16 16
#define SF_SECTOR_SIZE FS_SEC_SIZE
/*********************************************************************
*
* Local data types
*
**********************************************************************
*/
typedef struct {
FS_U16 BytesPerPage;
FS_U16 ldBytesPerPage;
FS_U8 ExtraBytes;
FS_U32 MaxNumSectors;
} SFLASH_PARATYPE;
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
static int _IsInited;
static SFLASH_PARATYPE _aSerialFlashPara[FS_SFLASH_MAXUNIT];
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
/*********************************************************************
*
* _ld
*/
static FS_U16 _ld(FS_U32 Value) {
FS_U16 i;
for (i = 0; i < 16; i++) {
if ((1UL << i) == Value) {
break;
}
}
return i;
}
/*********************************************************************
*
* _SendDummyClocks
*/
static void _SendDummyClocks(FS_U8 Unit, int NumClocks) {
int NumBytes;
FS_U8 DummyData;
DummyData = 0xff;
NumBytes = NumClocks >> 3;
do {
FS_SF_HW_X_Write(Unit, &DummyData, 1);
} while(--NumBytes);
}
/*********************************************************************
*
* _SendCommandPara
*/
static void _SendCommandPara(FS_U8 Unit, FS_U8 Command, FS_U32 Para, int CSHandling) {
FS_U8 aData[COMMAND_LENGTH];
aData[0] = Command;
aData[1] = (FS_U8)((Para >> 16) & 0xff);
aData[2] = (FS_U8)((Para >> 8) & 0xff);
aData[3] = (FS_U8)( Para & 0xff);
if (CSHandling) {
FS_SF_HW_X_EnableCS(Unit);
}
FS_SF_HW_X_Write(Unit, aData, COMMAND_LENGTH);
if (CSHandling) {
FS_SF_HW_X_DisableCS(Unit);
}
}
/*********************************************************************
*
* _GetNumSectors
*/
static FS_U8 _SendCommand(FS_U8 Unit, FS_U8 Command, int CSHandling) {
FS_U8 r;
if (CSHandling) {
FS_SF_HW_X_EnableCS(Unit);
}
FS_SF_HW_X_Write(Unit, &Command, 1);
FS_SF_HW_X_Read(Unit, &r, 1);
if (CSHandling) {
FS_SF_HW_X_DisableCS(Unit);
}
return r;
}
/*********************************************************************
*
* _WaitUntilReady
*/
static void _WaitUntilReady(FS_U8 Unit) {
FS_U8 Status;
do {
Status = _SendCommand(Unit, READ_STATUS, 1);
if ((Status & (1 << 7)) == (1 << 7)) {
break;
}
} while(1);
}
/*********************************************************************
*
* _GetNumSectors
*/
static FS_U32 _GetNumSectors(FS_U8 Unit) {
FS_U32 r;
SFLASH_PARATYPE * pCardPara;
pCardPara = &_aSerialFlashPara[Unit];
r = pCardPara->MaxNumSectors;
if (pCardPara->BytesPerPage == PAGE_SIZE_256) {
r >>= 1;
}
return r;
}
/*********************************************************************
*
* _Write
*/
static void _Write(FS_U8 Unit, FS_U32 PageAddr, FS_U8 * pBuffer, FS_U16 BytesPerPage, FS_U8 NumExtraBytes) {
FS_U8 acDummyData[MAX_EXTRABYTES];
FS_MEMSET(acDummyData, 0xff, sizeof(acDummyData));
FS_SF_HW_X_EnableCS(Unit);
_SendCommandPara(Unit, PAGE_PROGRAM, PageAddr, 0);
FS_SF_HW_X_Write(Unit, pBuffer, BytesPerPage);
FS_SF_HW_X_Write(Unit, acDummyData, NumExtraBytes);
FS_SF_HW_X_DisableCS(Unit);
_WaitUntilReady(Unit);
}
/*********************************************************************
*
* _Read
*/
static void _Read(FS_U8 Unit, FS_U32 PageAddr, FS_U8 * pBuffer, FS_U16 BytesPerPage, FS_U8 NumExtraBytes) {
FS_U8 acDummyData[MAX_EXTRABYTES];
FS_SF_HW_X_EnableCS(Unit);
_SendCommandPara(Unit, READ_PAGE, PageAddr , 0);
_SendDummyClocks(Unit, 32);
FS_SF_HW_X_Read(Unit, pBuffer, BytesPerPage);
FS_SF_HW_X_Read(Unit, acDummyData, NumExtraBytes);
FS_SF_HW_X_DisableCS(Unit);
_WaitUntilReady(Unit);
}
/*********************************************************************
*
* _WritePage
*/
static int _WritePage(FS_U8 Unit, FS_U32 Sector, FS_U8 * pBuffer) {
FS_U8 ExtraBytes;
FS_U16 BytesPerPage;
FS_U16 ShiftCount;
int NumLoops;
SFLASH_PARATYPE * pCardPara;
pCardPara = &_aSerialFlashPara[Unit];
BytesPerPage = pCardPara->BytesPerPage;
ExtraBytes = pCardPara->ExtraBytes;
ShiftCount = pCardPara->ldBytesPerPage + 1;
NumLoops = SF_SECTOR_SIZE / BytesPerPage;
if (BytesPerPage == PAGE_SIZE_256) {
Sector <<= 1;
}
do {
_Write(Unit, Sector++ << ShiftCount, pBuffer, BytesPerPage, ExtraBytes);
pBuffer += BytesPerPage;
} while(--NumLoops);
return 0;
}
/*********************************************************************
*
* _ReadPage
*/
static int _ReadPage(FS_U8 Unit, FS_U32 Sector, FS_U8 * pBuffer) {
FS_U8 ExtraBytes;
FS_U16 BytesPerPage;
FS_U16 ShiftCount;
int NumLoops;
SFLASH_PARATYPE * pCardPara;
pCardPara = &_aSerialFlashPara[Unit];
BytesPerPage = pCardPara->BytesPerPage;
ExtraBytes = pCardPara->ExtraBytes;
ShiftCount = pCardPara->ldBytesPerPage + 1;
NumLoops = SF_SECTOR_SIZE / BytesPerPage;
if (BytesPerPage == PAGE_SIZE_256) {
Sector <<= 1;
}
do {
_Read(Unit, Sector++ << ShiftCount, pBuffer, BytesPerPage, ExtraBytes);
pBuffer += BytesPerPage;
} while(--NumLoops);
return 0;
}
/*********************************************************************
*
* _InitFlashPara
*/
static int _InitFlashPara(FS_U8 Unit, FS_U8 Id) {
FS_U16 BytesPerPage;
FS_U8 ExtraBytes;
FS_U32 MaxNumSectors;
SFLASH_PARATYPE * pCardPara;
pCardPara = &_aSerialFlashPara[Unit];
switch (Id) {
case FLASH_1MBIT:
BytesPerPage = PAGE_SIZE_256;
ExtraBytes = EXTRABYTES_08;
MaxNumSectors = 512;
break;
case FLASH_2MBIT:
BytesPerPage = PAGE_SIZE_256;
ExtraBytes = EXTRABYTES_08;
MaxNumSectors = 1024;
break;
case FLASH_4MBIT:
BytesPerPage = PAGE_SIZE_256;
ExtraBytes = EXTRABYTES_08;
MaxNumSectors = 2048;
break;
case FLASH_8MBIT:
BytesPerPage = PAGE_SIZE_256;
ExtraBytes = EXTRABYTES_08;
MaxNumSectors = 4096;
break;
case FLASH_16MBIT:
BytesPerPage = PAGE_SIZE_512;
ExtraBytes = EXTRABYTES_16;
MaxNumSectors = 4096;
break;
case FLASH_32MBIT:
BytesPerPage = PAGE_SIZE_512;
ExtraBytes = EXTRABYTES_16;
MaxNumSectors = 8192;
break;
default:
return 1;
}
pCardPara->BytesPerPage = BytesPerPage;
pCardPara->ExtraBytes = ExtraBytes;
pCardPara->MaxNumSectors = MaxNumSectors;
pCardPara->ldBytesPerPage = _ld(BytesPerPage);
return 0;
}
/*********************************************************************
*
* _SF_GetStatus
*
* Description:
* FS driver function. Get status of the media,
* Initialize the card if necassary.
*
* Parameters:
* Unit - Unit number.
*
* Return value:
* FS_MEDIA_STATEUNKNOWN if the state of the media is unknown.
* FS_MEDIA_ISNOTPRESENT if no card is present.
* FS_MEDIA_ISPRESENT if a card is present.
*/
static int _SF_GetStatus(FS_U8 Unit) {
int r;
if (_IsInited) {
r = FS_MEDIA_ISPRESENT;
} else {
r = FS_MEDIA_ISNOTPRESENT;
}
return r;
}
/*********************************************************************
*
* _FS_MMC_ReadBurst
*
* Description:
* FS driver function. Read a sector from the media.
*
* Parameters:
* Unit - Device index number
* Sector - Sector to be read from the device.
* pBuffer - Pointer to buffer for storing the data.
*
* Return value:
* ==0 - Sector has been read and copied to pBuffer.
* <0 - An error has occured.
*/
#if SUPPORT_BURST
static int _SF_ReadBurst(FS_U8 Unit, FS_U32 SectorNo, FS_U32 NumSectors, void *pBuffer) {
return 0;
}
#endif
/*********************************************************************
*
* _SF_ReadSector
*
* Description:
* Read a sector from the Serial flash.
*
* Parameters:
* Unit - Unit number.
* Sector - Sector to be read from the device.
* pBuffer - Pointer to buffer for storing the data.
*
* Return value:
* ==0 - Sector has been read and copied to pBuffer.
* <0 - An error has occured.
*/
static int _SF_ReadSector(FS_U8 Unit, FS_U32 Sector, void *pBuffer) {
SFLASH_PARATYPE * pCardPara;
FS_U8 * p;
pCardPara = &_aSerialFlashPara[Unit];
p = (FS_U8 *)pBuffer;
if (Sector > pCardPara->MaxNumSectors) {
return -1;
}
return _ReadPage(Unit, Sector, p);
}
/*********************************************************************
*
* _SF_WriteSector
*
* Description:
* Write sector to the serial flash.
*
* Parameters:
* Unit - Unit number.
* Sector - Sector to be written to the device.
* pBuffer - Pointer to data to be stored.
*
* Return value:
* ==0 - Sector has been written to the device.
* <0 - An error has occured.
*/
static int _SF_WriteSector(FS_U8 Unit, FS_U32 Sector, void *pBuffer) {
SFLASH_PARATYPE * pCardPara;
FS_U8 * p;
pCardPara = &_aSerialFlashPara[Unit];
p = (FS_U8 *)pBuffer;
if (Sector > pCardPara->MaxNumSectors) {
return -1;
}
return _WritePage(Unit, Sector, p);
}
/*********************************************************************
*
* _FS_MMC_IoCtl
*
* Description:
* FS driver function. Execute device command.
*
* Parameters:
* Unit - Device Index.
* Cmd - Command to be executed.
* Aux - Parameter depending on command.
* pBuffer - Pointer to a buffer used for the command.
*
* Return value:
* Command specific. In general a negative value means an error.
*/
static int _SF_IoCtl(FS_U8 Unit, FS_I32 Cmd, FS_I32 Aux, void *pBuffer) {
FS_DEV_INFO * pDevInfo;
FS_USE_PARA(Aux);
switch (Cmd) {
case FS_CMD_INC_BUSYCNT: /* enter busy state */
FS_SF_HW_X_BusyLedOn(Unit);
break;
case FS_CMD_DEC_BUSYCNT: /* leave busy state */
FS_SF_HW_X_BusyLedOff(Unit);
break;
case FS_CMD_CHK_DSKCHANGE: /* check for disk change */
return 0;
case FS_CMD_GET_DEVINFO: /* Get general device information */
pDevInfo = (FS_DEV_INFO *)pBuffer;
pDevInfo->BytesPerSector = 512;
pDevInfo->NumSectors = _GetNumSectors(Unit);
break;
default:
break;
}
return 0;
}
/*********************************************************************
*
* _FS_MMC_InitMedium
*
* Description:
* FS driver function.
* Initialize the card.
*
* Parameters:
* Unit - Unit number.
*/
static void _SF_InitMedium(FS_U8 Unit) {
if (_IsInited == 0) {
if (FS_SF_HW_X_Init(Unit) == 0) {
FS_U8 Id;
/*
* Read Status Byte to get the ID of device
*/
Id = _SendCommand(Unit, READ_STATUS, 1);
Id = (Id >> 2) & 0x0f;
if (_InitFlashPara(Unit, Id) == 0) {
_IsInited = 1;
}
} else {
/* init failed */
FS_DEBUG_WARN("SerialFlash: Init failure.");
}
}
}
/*********************************************************************
*
* _FS_MMC_InitMedium
*
* Description:
* FS driver function.
* Initialize the card.
*
* Parameters:
* Unit - Unit number.
*/
static int _SF_InitDevice(FS_U8 Unit) {
_SF_InitMedium(Unit);
return 1;
}
/*********************************************************************
*
* Global variables
*
**********************************************************************
*/
const FS_DEVICE_TYPE FS__SFlash_Driver = {
"sflash",
FS_SFLASH_MAXUNIT,
_SF_GetStatus,
_SF_ReadSector,
_SF_WriteSector,
_SF_IoCtl,
#if 0 /* not yet released FS_SUPPORT_BURST for SerialFlash */
_SF_ReadBurst,
_SF_WriteBurst,
#else
NULL,
NULL,
#endif
_SF_InitDevice,
_SF_InitMedium
};
#endif /* FS_USE_SFLASH_DRIVER */
/*************************** End of file ****************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -