📄 cf.c
字号:
/*
**********************************************************************************************
* Project: TK7821
* File: cf.c
* Contents:
* The Compact Flash access module
*
* $Date: 02/25/05 Jason v0.1
* 04/21/05 Mingo v0.2 www.fameg.com
*
* Copyright (c) 2005 Fameg, Inc. All rights reserved
***********************************************************************************************
*/
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#include "Device.h"
#include "UsbDisk.h"
#include "Storage.h"
#ifdef CF
#define CF_DEVICE_READY 0x50
#define CF_DATA_READY 0x58
#define CMD_IDENTIFY_DRIVE 0xec
#define CMD_SET_FEATURE 0xef
#define CMD_ERASE_SECTOR 0xc0
#define CMD_READ_SECTOR 0x20
#define CMD_WRITE_SECTOR 0x30
// Feature Support
#define ENABLE_8BIT_MODE 0x01
#define ENABLE_PWR_LEVEL1 0x0a
#define DISABLE_READ_LOOK_AHEAD 0x55
#define DISABLE_POR 0x66
#define DISABLE_8BIT_MODE 0x81
#define DISABLE_PWR_LEVEL1 0x8a
#define SET_CURRENT_CAP 0x97
#define ENABLE_LONG_CMD 0xbb
#define ENABLE_POR 0xcc
#define ID_INFO_SIZE 512
static idata UINT32 CfNextSector;
static idata UINT16 CfSectorLeft;
static idata BYTE CfLastSector8;
static idata BYTE CfSectorCounter8;
static xdata UINT32 CfAvailableSectors = 0;
xdata BYTE CfGetFlashInfoTimer = 0;
xdata STATUS CfCmdStatus = STATUS_SUCCESS;
STATUS CfReset();
//----------------------------------------------------------------------------
#define CfCardExist() (CSRRead(CF_BASE + CF_CTRL) & CF_CARD_STS)
//----------------------------------------------------------------------------
BYTE CfReadReg(UINT16 Reg)
{
BYTE RetryCount1 = 0;
BYTE RetryCount2;
BYTE RegValue;
for( ; RetryCount1 < MAX_FLASH_RETRY_TIMES; RetryCount1++)
{
CSRRead(Reg);
for(RetryCount2 = 0; RetryCount2 < 100; RetryCount2++)
{
RegValue = CSRRead(CF_BASE + CF_IE);
if(RegValue & CF_COMPLETE)
{
CSRWrite(CF_BASE + CF_IE, ~CF_COMPLETE);
RegValue = CSRRead(CF_BASE + CF_DATA);
CfCmdStatus = STATUS_SUCCESS;
return RegValue;
}
}
}
CfCmdStatus = STATUS_FLASH_ERROR;
return 0;
}
void CfWriteReg(UINT16 Reg, BYTE Data)
{
BYTE RetryCount1 = 0;
BYTE RetryCount2;
BYTE RegValue;
for( ; RetryCount1 < MAX_FLASH_RETRY_TIMES; RetryCount1++)
{
CSRWrite(Reg, Data);
for(RetryCount2 = 0; RetryCount2 < 100; RetryCount2++)
{
RegValue = CSRRead(CF_BASE + CF_IE);
if(RegValue & CF_COMPLETE)
{
CSRWrite(CF_BASE + CF_IE, ~CF_COMPLETE);
CfCmdStatus = STATUS_SUCCESS;
return;
}
}
}
CfCmdStatus = STATUS_FLASH_ERROR;
}
//----------------------------------------------------------------------------
#define CF_STATUS_BUSY 0x80
#define CF_STATUS_RDY 0x40
#define CF_STATUS_DWF 0x20 // write fault
#define CF_STATUS_DSC 0x10 // CompactFlash is ready
#define CF_STATUS_DRQ 0x08 // Data Request
#define CF_STATUS_CORR 0x04 // Correctable data error
#define CF_STATUS_ERR 0x01
STATUS CfWaitDevRdy(BYTE WaitTime)
{
BYTE RegValue;
CmdTimer = WaitTime;
while(CmdTimer > 0)
{
RegValue = CfReadReg(CF_BASE + CF_STS_CMD);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
if( (RegValue & CF_STATUS_DWF) ||
(RegValue & CF_STATUS_ERR) )
continue;
if(RegValue & CF_STATUS_BUSY)
continue;
if( (RegValue & CF_STATUS_RDY) &&
(RegValue & CF_STATUS_DSC) )
return STATUS_SUCCESS;
}
CfReset();
return STATUS_FLASH_ERROR;
}
STATUS CfWaitDataRdy(BYTE WaitTime)
{
BYTE RegValue;
CmdTimer = WaitTime;
while(CmdTimer > 0)
{
RegValue = CfReadReg(CF_BASE + CF_STS_CMD);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
if( (RegValue & CF_STATUS_DWF) ||
(RegValue & CF_STATUS_ERR) )
continue;
if(RegValue & CF_STATUS_BUSY)
continue;
if( (RegValue & CF_STATUS_RDY) &&
(RegValue & CF_STATUS_DSC) &&
(RegValue & CF_STATUS_DRQ) )
return STATUS_SUCCESS;
}
CfReset();
return STATUS_FLASH_ERROR;
}
//----------------------------------------------------------------------------
// Power on the CF device
//----------------------------------------------------------------------------
void CfPowerOn()
{
BYTE Reg = CSRRead(CF_BASE + CF_CTRL);
CSRWrite(CF_BASE + CF_CTRL, Reg | CF_POWER);
Delay(100);
}
//----------------------------------------------------------------------------
// Power off the CF device
//----------------------------------------------------------------------------
void CfPowerOff()
{
BYTE Reg = CSRRead(CF_BASE + CF_CTRL);
CSRWrite(CF_BASE + CF_CTRL, Reg & ~CF_POWER);
}
//----------------------------------------------------------------------------
// Reset CF device
//----------------------------------------------------------------------------
STATUS CfReset()
{
BYTE RegValue;
BYTE delay;
BYTE RetryCount = 0;
for( ; RetryCount < MAX_FLASH_RETRY_TIMES; RetryCount++)
{
// Issue hardware reset
CSRWrite(CF_BASE + CF_CTRL, CF_RESET|CF_POWER|CF_BUS_WIDTH);
for(delay = 0; delay < 50; delay++);
CSRWrite(CF_BASE + CF_CTRL, CF_POWER|CF_BUS_WIDTH);
//for(delay = 0; delay < 50; delay++);
Delay(50); // 50ms
// Issue software reset
//CfWriteReg(CF_BASE + CF_ALT_STS_CTRL, 0x0E);
//for(delay = 0; delay < 50; delay++);
//CfWriteReg(CF_BASE + CF_ALT_STS_CTRL, 0x0A);
// Select Logical Block Address Mode.
CfWriteReg(CF_BASE + CF_HEADER , 0xE0);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
// Wait until CF ready
CmdTimer = CF_CMD_TIMEOUT;
while(CmdTimer > 0)
{
RegValue = CfReadReg(CF_BASE + CF_STS_CMD);
if( (CfCmdStatus == STATUS_SUCCESS) &&
(RegValue == CF_DEVICE_READY) )
return STATUS_SUCCESS;
}
}
return STATUS_FLASH_ERROR;
}
//--------------------------------------------------------------------
// Issue DMA of data transfer from CF to FIFO
//--------------------------------------------------------------------
void CfReadSectorDataCmd(UINT16 Buffer, UINT16 Size)
{
BYTE Addr0 = (BYTE)Buffer;
BYTE Addr1 = (BYTE)(Buffer >> 8);
BYTE Leng0 = (BYTE)Size;
BYTE Leng1 = (BYTE)(Size >> 8);
BYTE RegValue;
CSRWrite(CF_BASE + CF_ADDR0, Addr0);
CSRWrite(CF_BASE + CF_ADDR1, Addr1);
CSRWrite(CF_BASE + CF_LENGTH0, Leng0);
CSRWrite(CF_BASE + CF_LENGTH1, Leng1);
RegValue = CSRRead(CF_BASE + CF_CTRL);
RegValue |= CF_DMA_READ;
CSRWrite(CF_BASE + CF_CTRL, RegValue);
}
//--------------------------------------------------------------------
// Issue DMA of data transfer from FIFO to CF
//--------------------------------------------------------------------
void CfWriteSectorDataCmd(UINT16 Buffer, UINT16 Size)
{
BYTE Addr0 = (BYTE)Buffer;
BYTE Addr1 = (BYTE)(Buffer >> 8);
BYTE Leng0 = (BYTE)Size;
BYTE Leng1 = (BYTE)(Size >> 8);
BYTE RegValue;
CSRWrite(CF_BASE + CF_ADDR0, Addr0);
CSRWrite(CF_BASE + CF_ADDR1, Addr1);
CSRWrite(CF_BASE + CF_LENGTH0, Leng0);
CSRWrite(CF_BASE + CF_LENGTH1, Leng1);
RegValue = CSRRead(CF_BASE + CF_CTRL);
RegValue |= CF_DMA_WRITE;
CSRWrite(CF_BASE + CF_CTRL, RegValue);
}
//--------------------------------------------------------------------
// Read one sector of data from the CF device
// Drive/Head Register:
// D7 D6 D5 D4 D3 D2 D1 D0
// 1 LBA 1 DRV HS3 HS2 HS1 HS0
// LBA = 1 (LBA MODE) , DRV = 0 (MASTER)
// LBA07-LBA00 : Sector Number Register D7-D0
// LBA15-LBA08 : Cylinder Low Register D7-D0
// LBA23-LBA16 : Cylinder High Register D7-D0
// LBA27-LBA24 : Drive/Head Register HS3-HS0
//--------------------------------------------------------------------
STATUS CfReadOneSector()
{
STATUS Status;
BYTE LBA0 = (BYTE)SectorStart;
BYTE LBA1 = (BYTE)(SectorStart >> 8);
BYTE LBA2 = (BYTE)(SectorStart >> 16);
BYTE LBA3 = (BYTE)(SectorStart >> 24);
BYTE RetryCount = 0;
BYTE RegValue;
for( ; RetryCount < MAX_FLASH_RETRY_TIMES; RetryCount++)
{
Status = CfWaitDevRdy(10); // 100ms
if(Status != STATUS_SUCCESS)
continue;
CfWriteReg(CF_BASE + CF_HEADER , (LBA3 & 0x0F) | 0xE0);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
CfWriteReg(CF_BASE + CF_CYLINDER_HI, LBA2);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
CfWriteReg(CF_BASE + CF_CYLINDER_LO, LBA1);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
CfWriteReg(CF_BASE + CF_SECTOR , LBA0);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
CfWriteReg(CF_BASE + CF_SECTOR_CNT , 1);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
CfWriteReg(CF_BASE + CF_STS_CMD, CMD_READ_SECTOR);
if(CfCmdStatus != STATUS_SUCCESS)
continue;
Status = CfWaitDataRdy(CF_CMD_TIMEOUT);
if(Status != STATUS_SUCCESS)
continue;
CfReadSectorDataCmd(CurrentBuffer, BYTES_PER_SECTOR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -