📄 lh79524_lpd_cf_driver.c
字号:
/***********************************************************************
* $Workfile: lh79524_lpd_cf_driver.c $
* $Revision: 1.0 $
* $Author: ZhangJ $
* $Date: Oct 20 2004 09:38:42 $
*
* Project: CF card memory mode interface driver
*
* Description:
* This driver is based on the compact flash driver.
* This driver supports a CF card and it is on memory mode.
*
* Notes:
* The LH79520_cf_driver header file is included in the this file, as
* some CF specific data is defined there.
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh79524/bsps/sdk79524/source/lh79524_lpd_cf_driver.c-arc $
*
* Rev 1.0 Oct 20 2004 09:38:42 ZhangJ
* Initial revision.
*
*
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
* COPYRIGHT (C) 2003 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
**********************************************************************/
#include "abl_types.h"
#include "LH79524_lpd_cf_driver.h"
static void cfmem_get_chs (void);
static void cfmem_dummy_write (void);
static void cfmem_dummy_read (void);
static void cfmem_delay_loop (INT_32 delay);
// CHS mapping values
static UNS_16 max_cyl, max_heads, max_sectors_track;
/***********************************************************************
* Function: cfmem_get_chs
*
* Purpose: Sets up the device specific CHS values.
*
* Processing: Issues the CF identification command and reads the CF
* status. The CHS sizing from the CF card is used by the
* driver.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
static void cfmem_get_chs (void)
{
UNS_16 data [256];
UNS_16 value;
// Issue a read attributes command to the CF device
value = (CFMEM_STAT->sel_card) & 0xff;
CFMEM_STAT->sel_card = value | (CFC_IDENT<<8);
// Wait for command to complete
while (cfmem_is_card_busy () == 1);
// Move data into the buffer
cfmem_read_data (data, sizeof(data));
// Save the 3 needed values
max_cyl = (UNS_16) data [54];
max_heads = (UNS_16) data [55];
max_sectors_track = (UNS_16) data [56];
}
/***********************************************************************
* Function: cfmem_init
*
* Purpose: Initialize the CF interface and return the card detection
* status.
*
* Processing: The pointers used in this driver are initialized.
*
* Parameters: None
*
* Outputs: None
*
* Returns: '1' if a CF card has been detected, '0' otherwise.
*
* Notes: None
*
**********************************************************************/
INT_32 cfmem_init (void)
{
INT_32 inserted;
inserted = cfmem_is_card_inserted ();
if (inserted == 1)
{
// Get CHS mappings (used for absolute sector conversion)
cfmem_get_chs ();
}
return inserted;
}
/***********************************************************************
* Function: cfmem_shutdown
*
* Purpose: Shutdown the CF interface driver.
*
* Processing: This function does nothing and is a placeholder.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void cfmem_shutdown (void)
{
/* Do nothing */
;
}
/***********************************************************************
* Function: cfmem_is_card_inserted
*
* Purpose: Determine if a card is inserted
*
* Processing: TBD
*
* Parameters: None
*
* Outputs: None
*
* Returns: '1' if a card is inserted, '0' otherwise.
*
* Notes: None
*
**********************************************************************/
INT_32 cfmem_is_card_inserted (void)
{
UNS_8 value;
value = (CFMEM_STAT->sel_card)>>8;
if ((value & CF_DETECT_MASK) == CF_DETECT_VALUE)
return 1;
else
return 0;
}
/***********************************************************************
* Function: cfmem_is_card_ready
*
* Purpose: Determines if the card is ready for a new command.
*
* Processing: If the CF_RDY bit in the CF status register is set,
* return '1', else return a '0'.
*
* Parameters: None
*
* Outputs: None
*
* Returns: '1' if the card is ready for a new command, otherwise '0'.
*
* Notes: None
*
**********************************************************************/
INT_32 cfmem_is_card_ready (void)
{
UNS_8 value;
value = (CFMEM_STAT->sel_card)>>8;
return ((value & CF_RDY) != 0);
}
/***********************************************************************
* Function: cfmem_is_card_busy
*
* Purpose: Determine if a card is busy (processing a command).
*
* Processing: If the CF_BUSY bit in the CF status register is set,
* return '1', else return a '0'.
*
* Parameters: None
*
* Outputs: None
*
* Returns: '1' if the card is busy, '0' otherwise.
*
* Notes: None
*
**********************************************************************/
INT_32 cfmem_is_card_busy (void)
{
UNS_8 value;
value = (CFMEM_STAT->sel_card)>>8;
return ((value & CF_BUSY) != 0);
}
/***********************************************************************
* Function: cfmem_set_sector
*
* Purpose: Set the cylinder, head, and sector for the next operation
* (using the absolute sector number).
*
* Processing: The sector passed from the caller update the CHS
* device pointers that will be used for the next
* operation.
*
* Parameters: sectorno : Sector number
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: The convention is Cylinder/Head/Sector (CHS). The function
* will convert the CHS values to a value that works with the
* CF card.
*
**********************************************************************/
void cfmem_set_sector (UNS_32 sectorno)
{
UNS_16 sector, head, cylinder;
UNS_32 csector;
UNS_16 value;
// Compute real sector number
csector = sectorno / (UNS_32) max_sectors_track;
csector = (UNS_32) max_sectors_track * csector;
sector = (UNS_8) (sectorno - csector + 1);
// Compute cylinder
cylinder = (UNS_16) (sectorno /
((UNS_32) max_sectors_track * (UNS_32) max_heads));
// Compute head
head = (UNS_8) (sectorno / (UNS_32) max_sectors_track -
((UNS_32) cylinder * (UNS_32) max_heads));
// Setup the IDE controller with the CHS mappings
while (cfmem_is_card_busy () == 1);
// Write cylinder value
CFMEM_STAT->cyl_low = cylinder;
while (cfmem_is_card_busy () == 1);
//Write head
CFMEM_STAT->sel_card = (head|0xa0);
//CFMEM_STAT->sel_card = (UNS_8)(head|0xa0);
// Wait for command to complete
while (cfmem_is_card_busy () == 1);
// Write sector count and number (sector count fixed as 1)
value = 1 | (sector)<<8;
CFMEM_STAT->sector_count = value;
}
/***********************************************************************
* Function: cfmem_send_command
*
* Purpose: Send command to CF card
*
* Processing:
*
* Parameters: Command to send to CF card
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void cfmem_send_command (UNS_32 command)
{
UNS_16 value;
while(cfmem_is_card_ready() == 0);
//read the register back
value = (CFMEM_STAT->sel_card) & 0xff;
//Write the new command
CFMEM_STAT->sel_card = value | (command<<8);
// Wait for command to complete
while (cfmem_is_card_busy () == 1);
}
/***********************************************************************
* Function: cfmem_start_sector_read
*
* Purpose: Starts the read of a sector.
*
* Processing: Set the sector size to '1' and issue the sector read command.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void cfmem_start_sector_read (void)
{
//CFMEM_STAT->sector_count = 1;
cfmem_send_command(CFC_R_SECT);
}
/***********************************************************************
* Function: cfmem_start_sector_write
*
* Purpose: Starts the write of a sector.
*
* Processing: Set the sector size to '1' and issue the sector write command.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void cfmem_start_sector_write (void)
{
//CFMEM_STAT->sector_count = 1;
cfmem_send_command(CFC_W_SECT);
}
/***********************************************************************
* Function: cfmem_read_data
*
* Purpose: Read a block of data from the CF card.
*
* Processing: Copy a block of data of from the CF card buffer to the
* destination address.
*
* Parameters:
* data : Pointer to where to put read data from the CF card
* bytes : Number of bytes to read
*
* Outputs: The data pointed to by data will be updated.
*
* Returns: The number of bytes read from the card.
*
* Notes: Data is read AFTER a read command.
*
**********************************************************************/
INT_32 cfmem_read_data (void *data, INT_32 bytes)
{
INT_32 i;
UNS_16 *cf_data = (UNS_16 *) data;
for (i = 0; i < bytes/2; i++)
{
*cf_data = CFMEM_STAT->data_NN;
cf_data++;
// sma
//cfmem_dummy_read();
//if (CFMEM_STAT->status_command & CF_DWF)
//return 0;
}
return bytes;
}
/***********************************************************************
* Function: cfmem_write_data
*
* Purpose: Write data to the CF card.
*
* Processing: Copy a block of data of from the source address to the
* CF card buffer.
*
* Parameters:
* data : Pointer to where to get data to write to the CF card
* bytes : Number of bytes to write
*
* Outputs: None
*
* Returns: The number of bytes written to the card.
*
* Notes: Data is written after a write command.
*
**********************************************************************/
INT_32 cfmem_write_data (void *data, INT_32 bytes)
{
INT_32 i;
UNS_16 *cf_data = (UNS_16 *) data;
for (i = 0; i < bytes/2; i++)
{
// Fill write buffer
CFMEM_STAT->data_NN = *cf_data;
cf_data++;
//if (CFMEM_STAT->status_command & CF_DWF)
//return 0;
}
return bytes;
}
/***********************************************************************
* Function: cfmem_erase_sector
*
* Purpose: Erase CF card sectors.
*
* Processing: Erase requested number of card sectors starting with
* specified sector number
*
* Parameters:
* start: Starting sector number
* bytes : Number of sectors to erase
*
* Outputs: None
*
* Returns: Success or fail
*
* Notes: None
*
**********************************************************************/
INT_32 cfmem_erase_sector (INT_32 sectorno)
{
cfmem_set_sector (sectorno);
//CFMEM_STAT->sector_count = 1;
cfmem_send_command (CFC_E_SECT);
//if (CFMEM_STAT->status_command & CF_DWF)
//return 1;
return 0;
}
void cfmem_dummy_write(void)
{
*(UNS_32 *)(0x40000000) = 0;
}
void cfmem_dummy_read(void)
{
volatile int i;
i = *(UNS_32 *)(0x40000000);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -