⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cf.c

📁 增强型51单片机fs7821cf卡读写程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**********************************************************************************************
* 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 + -