📄 bfsa_internal.c
字号:
// ----------------------------------------------------------------------------
// ATMEL Microcontroller Software Support - ROUSSET -
// ----------------------------------------------------------------------------
// DISCLAIMER: CONDITIONS AS PER SIGNED LIMITED LICENSE AGREEMENT (AT91
// SOFTWARE AND USER DOCUMENTATION)
// ALL SOFTWARE IS PROVIDED AS IS, WITH ALL FAULTS, AND WITH NO WARRANTY
// WHATSOEVER. ATMEL EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS, IMPLIED,
// OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.
// ----------------------------------------------------------------------------
// File Name : bfsa_internal.c
// Object : Internal functions to perfom basic IO on disk sectors
// Creation : FB 10/feb/2005
// Modif : JCB 15/apr/2005
// --------------------------------------------------------------------------
#include "po_types.h"
#include "po_kernel.h"
#include "trace.h"
#include "flash.h"
#include "bfsa_flash.h"
#include "bfsa_api.h"
#include "bfsa_internal.h"
#include "board.h"
#ifdef NANDFLASH
#include <stdlib.h>
#include "nand.h"
#include "nand_ids.h"
#include "jffs2.h"
#include "NandFlash.h"
extern unsigned char bBlock[SIZEONESECTOR];
#endif
// **************************************************
// Global
// **************************************************
UCHAR* FlashBaseAdd = FILE_MGR_BEGIN_ADDRESS; // Flash base address, only for read operations
/*****************************************************************
*
*
* S U B - R O U T I N E : readBPB
*
*-----------------------------------------------------------------
*
* int readBPB(UCHAR *pucBuff, USHORT uSize)
*
* Object :
* This function read BPB from Flash.
*
* Argument:
* pucBuff :[OUT] pointer to buffer that will receive the BPB,
* allocated by caller.
* uSize :[IN] size of pucBuff.
*
* Return value : 0 if success,
* on error : NO_MEDIA_FOUND
* FLASH_ACCESS_ERROR
*
*****************************************************************/
ULONG readBPB(UCHAR *pucBuff, USHORT uSize)
{
ULONG _status = BFSA_SUCCESS;
if (uSize > BPB_SIZE)
{
_status = FLASH_ACCESS_ERROR;
}
else
{
// Copy first bytes from FLASH
AT91F_ReadMedia((unsigned int)FlashBaseAdd, uSize, pucBuff);
}
return _status;
}
/*****************************************************************
*
*
* S U B - R O U T I N E : readFAT
*
*-----------------------------------------------------------------
*
* void readFAT(void)
*
* Object :
* This function copy the FAT from disk to global buffer.
*
* Argument:
* none.
*
*****************************************************************/
void readFAT(void)
{
ULONG _fatSizeFromDisk = BFSA_media.SectPerFAT*BFSA_media.bytesPerSector;
#ifdef NANDFLASH
size_t total;
#endif
#ifndef NANDFLASH
po_memcpy((void*)BFSABuffer.BFSA_fatBuff,
(void*)(BFSA_media.FATSectStart*BFSA_media.bytesPerSector + (ULONG)FlashBaseAdd),
min(_fatSizeFromDisk,sizeofBFSA_fatBuff));
#else
nand_rw(nand_dev_desc + curr_device,
NANDRW_READ,
BFSA_media.FATSectStart*BFSA_media.bytesPerSector + (ULONG)FlashBaseAdd - AT91_SMARTMEDIA_BASE,
sizeofBFSA_fatBuff,
&total,
BFSA_fatBuff);
#endif
}
/*****************************************************************
*
*
* S U B - R O U T I N E : writeFAT
*
*-----------------------------------------------------------------
*
* ULONG writeFAT(void)
*
* Object :
* This function writes back the FAT from global buffer to disk.
*
* Argument:
* none.
*
* Return value :
* BFSA_SUCCESS on success
* FLASH_ACCESS_ERROR on error
*
*****************************************************************/
ULONG writeFAT(void)
{
UCHAR _i;
ULONG status = BFSA_SUCCESS;
for (_i=0; _i<BFSA_media.numFAT; _i++)
{
if( FALSE == AT91F_Flash_Write_Address(BFSA_media.FATSectStart*BFSA_media.bytesPerSector // Destination
+ (ULONG) FlashBaseAdd
+ (_i*BFSA_media.SectPerFAT*BFSA_media.bytesPerSector),
min(sizeofBFSA_fatBuff, BFSA_media.SectPerFAT*BFSA_media.bytesPerSector), // Size
(unsigned char*)BFSABuffer.BFSA_fatBuff, FALSE)) // Source
{
status = FLASH_ACCESS_ERROR;
break;
}
}
return status;
}
/*****************************************************************
*
*
* S U B - R O U T I N E : readFatEntry
*
*-----------------------------------------------------------------
*
* USHORT readFatEntry(USHORT cluster)
*
* Object :
* This function returns the value of the FAT entry for the cluster number.
*
* Argument:
* cluster [IN] : cluster number.
*
* Return value :
* the value of the FAT entry for this cluster,
* 0x0FF7 if the cluster is over the max cluster number.
*
*****************************************************************/
USHORT readFatEntry( USHORT cluster )
{
USHORT fatOffset;
USHORT fatEntry = (BFSA_media.FATtype == BFSA_FAT12?BAD12:BAD16); // Bad Cluster
if (cluster > BFSA_media.MaxCluster)
{
TRACE_DEBUG_H( "dbg:PBcluster:0x%X\n\r",cluster);
}
else
{
if (BFSA_media.FATtype == BFSA_FAT12)
{
// Divide the cluster number by 2, resulting in an integer quotient
// Add the same cluster number to this quotient, producing the offset of the cluster's entry in the FAT.
fatOffset = cluster + (cluster / 2);
// Pb with FAT > buffer of FAT
/* if( fatOffset > sizeofBFSA_fatBuff )
{
// Read next of FAT
po_memcpy( BFSA_fatBuff,
(void*)(BFSA_media.FATSectStart*BFSA_media.bytesPerSector + (ULONG)FlashBaseAdd+sizeof( BFSA_fatBuff ) ),
sizeofBFSA_fatBuff );
fatOffset -= sizeof( BFSA_fatBuff );
}
*/
/*
if( fatOffset > sizeofBFSA_fatBuff )
{
AT91F_ReadMedia( (void*)(BFSA_media.FATSectStart*BFSA_media.bytesPerSector + (ULONG)FlashBaseAdd+sizeof( BFSA_fatBuff ),
sizeofBFSA_fatBuff ),
BFSA_fatBuff ) );
fatOffset -= sizeofBFSA_fatBuff );
}
*/
if( fatOffset < sizeofBFSA_fatBuff )
{
fatEntry = BFSABuffer.BFSA_fatBuff[fatOffset]+BFSABuffer.BFSA_fatBuff[fatOffset+1]*0x100;
// Cluster is ODD or EVEN ?
if (cluster & 0x0001)
{
// If the current cluster number is odd, keep the highest 12 bits of the 16-bit word.
fatEntry = fatEntry >> 4;
}
else
{
// If the current cluster number is even, keep the lowest 12 bits of the 16-bit word.
fatEntry = fatEntry & 0x0FFF;
}
}
}
else
{
TRACE_DEBUG_L( "dbg:NO FAT 12\n\r");
if( (cluster*2) < sizeofBFSA_fatBuff )
{
// In a 16-bit FAT, cluster n is represented by the entry at offset n * 2 in the table.
fatEntry = *((USHORT*) &BFSABuffer.BFSA_fatBuff[cluster*2]);
}
}
}
return( fatEntry );
}
/*****************************************************************
*
*
* S U B - R O U T I N E : writeFatEntry
*
*-----------------------------------------------------------------
*
* USHORT writeFatEntry(USHORT cluster,USHORT value)
*
* Object :
* This function write a value to FAT entry for cluster
*
* Argument:
* cluster [IN] : cluster number.
* value [IN] : value.
*
* Return value :
* 0 on success,
* 0x0FF7 if the cluster is over the max cluster number.
*
*****************************************************************/
ULONG writeFatEntry( USHORT cluster, USHORT value )
{
USHORT fatOffset;
ULONG status = (BFSA_media.FATtype == BFSA_FAT12?BAD12:BAD16); // Bad Cluster
if (cluster > BFSA_media.MaxCluster)
{
}
else
{
if (BFSA_media.FATtype == BFSA_FAT12)
{
USHORT valueForFATBuff;
// Divide the cluster number by 2, resulting in an integer quotient
// Add the same cluster number to this quotient, producing the offset of the cluster's entry in the FAT.
fatOffset = cluster + (cluster / 2);
// Pb with FAT > buffer of FAT
/* if( fatOffset > sizeofBFSA_fatBuff )
{
// Read next of FAT
po_memcpy( BFSA_fatBuff,
(void*)(BFSA_media.FATSectStart*BFSA_media.bytesPerSector + (ULONG)FlashBaseAdd+sizeofBFSA_fatBuff ),
sizeofBFSA_fatBuff );
fatOffset -= sizeofBFSA_fatBuff;
}
*/
if( fatOffset < sizeofBFSA_fatBuff )
{
// Cluster is ODD or EVEN ?
if (cluster & 0x0001)
{
valueForFATBuff = BFSABuffer.BFSA_fatBuff[fatOffset] + BFSABuffer.BFSA_fatBuff[fatOffset+1]*0x100;
valueForFATBuff &= 0x000F;
value = value << 4;
}
else
{
valueForFATBuff = BFSABuffer.BFSA_fatBuff[fatOffset] + BFSABuffer.BFSA_fatBuff[fatOffset+1]*0x100;
valueForFATBuff &= 0xF000;
value = value & 0x0FFF;
}
BFSABuffer.BFSA_fatBuff[fatOffset] = (value&0x000000FF) | (valueForFATBuff&0x000000FF);
BFSABuffer.BFSA_fatBuff[fatOffset+1] =(char)((value&0x0000FF00)>>8) |((valueForFATBuff&0x0000FF00)>>8);
}
}
else
{
if( (cluster*2) < sizeofBFSA_fatBuff )
{
// In a 16-bit FAT, cluster n is represented by the entry at offset n * 2 in the table.
*((USHORT*) &BFSABuffer.BFSA_fatBuff[cluster*2]) = value;
}
}
status = BFSA_SUCCESS;
}
return( status );
}
/*****************************************************************
*
*
* S U B - R O U T I N E : findFreeCluster
*
*-----------------------------------------------------------------
*
* int findFreeCluster(void)
*
* Object :
* This function returns the next free cluster from the FAT ,
* marks it EOF (0x0FF8 or 0xFFFF8) and fill it with 0.
*
* Argument:
* none.
*
* Return value :
* free cluster if any,
* 0 if there is no more free cluster
*
*****************************************************************/
USHORT findFreeCluster(void)
{
USHORT _currentCluster;
USHORT _freeCluster = 0;
USHORT _numberFatEntries;
UCHAR *_pucCluster = NULL;
// Compute the number of FAT entries = Number of clusters
_numberFatEntries = (BFSA_media.MaxCluster - BFSA_media.ClusterStart);
// Find a free cluster in FAT
for (_currentCluster = 2; // the 2 first clusters are reserved
_currentCluster < _numberFatEntries + 2;
_currentCluster++)
{
if (readFatEntry(_currentCluster) == FREE)
{
unsigned int value;
value = 0;
_freeCluster = _currentCluster;
// Mark it EOC (0x0FF8 for FAT12 0xFFF8 for FAT16)
if( BFSA_SUCCESS != writeFatEntry(_freeCluster,BFSA_media.FATtype == BFSA_FAT12?EOC12:EOC16) )
{
// Problem
_freeCluster = 0;
break;
}
// Fill it by 0
_pucCluster = (UCHAR*) (FIRST_SECTOR_DATACLUSTER(_currentCluster) * BFSA_media.bytesPerSector);
if (!AT91F_Flash_Write_Address((unsigned int)FlashBaseAdd + (unsigned int)_pucCluster, // Add
BFSA_media.bytesPerSector*BFSA_media.SectPerCluster, // Size
(unsigned char*) &value, // data
TRUE)) // MemSet
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -