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

📄 cf.c

📁 Hardware and firmware for a DSP based digital audio MP3 player with USB pen drive funtionality, usin
💻 C
字号:
/*
 * DSPdap-bootloader - DSP based Digital Audio Player, Bootloader
 * Copyright (C) 2004-2007 Roger Quadros <rogerquads @ yahoo . com>
 * http://dspdap.sourceforge.net
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: CF.c,v 1.2 2007/06/03 08:54:03 Roger Exp $
 */

#include "CF.h"
#include "types.h"
#include "IO.h"	//for read_mem() and write_mem()

#define CF_DET 6		//CF detect on A6 pin
                                                           
#define CF_BUSY_TIMEOUT 100		//Count time to wait for CF to be not busy
#define CF_READY_TIMEOUT 100    //Count time to wait for CF to be ready
#define CF_DRQ_TIMEOUT 100      //Count time to wait for CF to request data

                                                           
static void delay()
{
	int i;
	for(i=0; i<0x7fff; i++)
	{
		asm("	nop");
	}
}   

int CF_IsPresent()
{
	int word;
	word = get_AGPIO();
	
	if(word & (1<<CF_DET))
		return 0;	//CF not present as CF_DET line is high
	else
		return 1;	
}

//provides a hardware reset to the CF card
void CF_HardReset()
{
	asm("	BCLR	XF");	//make XF low
	delay();		//wait for at least 25us

	asm("	BSET	XF");	//make XF high	
	delay();		//wait for at least 25us
	delay();		//wait for at least 25us
}


enum BUSY_STATUS CF_CheckBusyStatus()
{
	int timeout;

	for(timeout = 0; timeout < CF_BUSY_TIMEOUT; timeout++)
	{
		if(read_mem(STATUS_REG) & 0x80)
		{
			//CF still busy
			delay();				//wait in loop till timeout
		}
		else
		{
			return CF_NOT_BUSY;		//CF is not busy.. return immediately
		}
	}
	return CF_BUSY;
}

enum READY_STATUS CF_CheckReadyStatus()
{                  
	int timeout;

	for(timeout = 0; timeout < CF_READY_TIMEOUT; timeout++)
	{
		if(read_mem(STATUS_REG) & 0x40)
		{                            
			return CF_READY;	//CF is ready... return immediately
		}
		else
		{
			//CF not yet ready
			delay();				//wait in loop till timeout
		}
	}
	return CF_NOT_READY;
}

enum DRQ_STATUS CF_CheckDrqStatus()
{
	int timeout;

	for(timeout = 0; timeout < CF_DRQ_TIMEOUT; timeout++)
	{
		if(read_mem(STATUS_REG) & 0x08)
		{                            
			return CF_DRQ_SET;	//DRQ is set... return immediately
		}
		else
		{
			//DRQ not yet set
			delay();				//wait in loop till timeout
		}
	}
	return CF_DRQ_RESET;
}

//Following variables are used to issue ATA commands
//unsigned short Command_Value;
unsigned short Drive_Head_Val;      //LBA(27-24)
unsigned short Cyl_High_Val;		//LBA(23-16)
unsigned short Cyl_Low_Val;         //LBA(15-8)
unsigned short Sector_Num_Val;		//LBA(7-0)
//unsigned short Sector_Count_Val;
unsigned short Feature_Val;     

//Fills the ATA registers appropriately with the given physical sector addres
//and sector count and issues the command.
void CF_IssueCommand(unsigned long physicalSector, unsigned short sectorCount, unsigned short command)
{
	//Set ATA registers based on given Physical/LBA address
	Sector_Num_Val = physicalSector & 0xFF;	//get bits 7-0
	physicalSector >>= 8;
	Cyl_Low_Val = physicalSector & 0xFF;	//get bits 15-8
	physicalSector >>= 8;
	Cyl_High_Val = physicalSector & 0xFF;	//get bits 23-16
	physicalSector >>= 8;
	Drive_Head_Val = 0xE0;		//set LBA = 1, DRV = 0
	Drive_Head_Val |= physicalSector & 0xF;	//get bits 27-24
	
	//write into the ATA registers
	write_mem(SECTOR_NO_REG, Sector_Num_Val);
	write_mem(CYL_LOW_REG, Cyl_Low_Val);
	write_mem(CYL_HIGH_REG, Cyl_High_Val);
	write_mem(DRIVE_HEAD_REG, Drive_Head_Val);                        
	//sector count
	write_mem(SECTOR_CNT_REG, sectorCount);
	//command
	write_mem(COMMAND_REG, command);	
}


//executes the identify drive command. the data returned by compact flash 
//is stored in buffer.
int CF_IdentifyDrive(UI buffer[256])
{          
	int i;
	//check is CF is Not Busy
	if(CF_CheckBusyStatus() == CF_BUSY)
		return -1;	//error
	
	//check if CF is Ready
	if(CF_CheckReadyStatus() == CF_NOT_READY)
		return -1;	//error
				
	//CF is not Busy and is Ready so issue command
	CF_IssueCommand(0, 0, IDENTIFY_DRIVE_CMD);
	
	//check to see if CF DRQ is set	
	if(CF_CheckDrqStatus() == CF_DRQ_SET)
	{
		//yes. so read data (256 words) into buffer
		for(i=0; i<256; i++)
			buffer[i] = read_mem(DATA_REG);
			
		return 0;	//success
	}             
	else
		return -1;	//error
}

//reads the contents (256 words) of the given sector into buffer
int CF_ReadSector(unsigned long LBA_address, void* buffer)
{           
	//check is CF is Not Busy
	if(CF_CheckBusyStatus() == CF_BUSY)
		return -1;	//error
	
	//check if CF is Ready
	if(CF_CheckReadyStatus() == CF_NOT_READY)
		return -2;	//error
	
	//CF is not Busy and is Ready so issue command	
	CF_IssueCommand(LBA_address, 1, READ_SECTORS_CMD);

	//check to see if CF DRQ is set		
	if(CF_CheckDrqStatus() == CF_DRQ_SET)
	{
		//yes. so read data (256 words) into buffer
		read_sector(DATA_REG, buffer);		
		
		return 0;	//success
	}
	else
		return -3;	//error
}
 
//prepares for reading given number of sectors
int CF_ReadSectors(unsigned long LBA_address, unsigned short num_sectors)
{           
	//check is CF is Not Busy
	if(CF_CheckBusyStatus() == CF_BUSY)
		return -1;	//error
	
	//check if CF is Ready
	if(CF_CheckReadyStatus() == CF_NOT_READY)
		return -2;	//error
	
	//CF is not Busy and is Ready so issue command	
	CF_IssueCommand(LBA_address, num_sectors, READ_SECTORS_CMD);

	//actual reading of data will be performed by application if success
	//is returned by this function
	//waiting for DRQ will be done in read_sector()
	return 0; //success
}
 
//prepares for writing the given number of sectors
int CF_WriteSectors(unsigned long LBA_address, unsigned short num_sectors)
{           
	//check is CF is Not Busy
	if(CF_CheckBusyStatus() == CF_BUSY)
		return -1;	//error
	
	//check if CF is Ready
	if(CF_CheckReadyStatus() == CF_NOT_READY)
		return -2;	//error
	
	//CF is not Busy and is Ready so issue command	
	CF_IssueCommand(LBA_address, num_sectors, WRITE_SECTORS_CMD);


	//actual writing of data will be performed by application if success
	//is returned by this function		
	//waiting for DRQ will be done in write_sector()
	return 0; //success
}                                           

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -