📄 flashloader.c
字号:
{
#pragma ST_device( ReadAddr08 )
#pragma ST_device( ReadAddr16 )
#pragma ST_device( ReadAddr32 )
stflash_Inst_t *ThisElem;
U32 LastReadP1; /* last address to be read plus one */
U32 LeftToRead; /* number of bytes left to read */
U32 OperaWidth; /* Operation Width (in bytes) */
U8 *TmpAddress; /* for recasting */
U8 *AccessAddr; /* BaseAddress + Offset */
U8 *DestBuff08; /* Buffer */
U16 *DestBuff16; /* (U16*)Buffer */
U32 *DestBuff32; /* (U32*)Buffer */
volatile U8 *ReadAddr08; /* 8 bit read access address */
volatile U16 *ReadAddr16; /* 16 bit read access address */
volatile U32 *ReadAddr32; /* 32 bit read access address */
ST_ErrorCode_t RetValue = ST_NO_ERROR; /* Default return code */
/* Perform necessary validity checks */
ThisElem = (stflash_Inst_t *)Handle;
if( ThisElem->MagicNumber != MAGIC_NUMBER ) /* rogue Handle value? */
{
*NumberActuallyRead = 0;
return( ST_ERROR_INVALID_HANDLE );
}
if( NumberToRead == 0 ) /* no bytes to read? */
{
*NumberActuallyRead = 0;
return( ST_NO_ERROR ); /* nothing to do, OK */
}
LastReadP1 = Offset + NumberToRead; /* last read addr+1 */
if( ( LastReadP1 > ThisElem->LastOffsP1 ) || /* Past end of device? */
( Buffer == NULL ) ) /* no buffer address? */
{
*NumberActuallyRead = 0;
return( ST_ERROR_BAD_PARAMETER );
}
TmpAddress = (U8*)ThisElem->BaseAddress; /* cast for addition */
AccessAddr = TmpAddress + Offset; /* first read addr */
/* Check addresses and length for MIN alignment.
Takes no action for byte minimum,
but will kick-in if minimum access width is bigger than a byte. */
if( ( ( (U32)AccessAddr &
ThisElem->MinAccessMask ) != 0 ) || /* source off MIN align? */
( ( (U32)Buffer &
ThisElem->MinAccessMask ) != 0 ) || /* dest. off MIN align? */
( ( NumberToRead &
ThisElem->MinAccessMask ) != 0 ) ) /* length off MIN align? */
{
*NumberActuallyRead = 0;
return( ST_ERROR_BAD_PARAMETER ); /* sorry, can't do */
}
TmpAddress = (U8*)ThisElem->BaseAddress; /* cast for computation */
AccessAddr = TmpAddress + Offset; /* form first read addr */
/* determine the (initial) access width to be used */
if( ( ( (U32)AccessAddr &
ThisElem->MaxAccessMask ) == 0 ) && /* source on MAX boundary? */
( ( (U32)Buffer &
ThisElem->MaxAccessMask ) == 0 ) && /* dest. on MAX boundary? */
( NumberToRead >=
ThisElem->MaxAccessWidth ) ) /* enough bytes for MAX? */
{
OperaWidth = ThisElem->MaxAccessWidth; /* high speed operation */
}
else
{
OperaWidth = ThisElem->MinAccessWidth; /* lower speed operation */
}
/* set up destination buffer and read pointers for all widths */
DestBuff08 = Buffer;
DestBuff16 = (U16*)Buffer;
DestBuff32 = (U32*)Buffer;
ReadAddr08 = AccessAddr;
ReadAddr16 = (U16*)AccessAddr;
ReadAddr32 = (U32*)AccessAddr;
/* Clear Status Register (precautionary) */
/* and commence Read Memory Array Command Sequence */
switch( ThisElem->MaxAccessWidth ) /* use maximum access width */
{
case STFLASH_ACCESS_08_BITS:
*ReadAddr08 = CLEAR_SR08;
*ReadAddr08 = READ_MA08;
break;
case STFLASH_ACCESS_16_BITS:
*ReadAddr16 = CLEAR_SR16;
*ReadAddr16 = READ_MA16;
break;
case STFLASH_ACCESS_32_BITS:
*ReadAddr32 = CLEAR_SR32;
*ReadAddr32 = READ_MA32;
break;
default:
break;
}
LeftToRead = NumberToRead; /* initialize counter */
while( LeftToRead > 0 ) /* whilst more bytes to read */
{
switch( OperaWidth ) /* choose appropriate size */
{
case STFLASH_ACCESS_08_BITS:
*DestBuff08++ = *ReadAddr08++; /* read from Flash */
LeftToRead -= OperaWidth;
break;
case STFLASH_ACCESS_16_BITS:
while( LeftToRead >= OperaWidth )
{
/*
* 数据取反
*/
*DestBuff16++ = ~(*ReadAddr16++); /* read from Flash */
LeftToRead -= OperaWidth;
}
if( LeftToRead > 0 ) /* any left to read? */
{
OperaWidth = /* drop down to MIN */
ThisElem-> MinAccessWidth;
/* transfer ptrs */
ReadAddr08 = (U8*)ReadAddr16;
DestBuff08 = (U8*)DestBuff16;
}
break;
case STFLASH_ACCESS_32_BITS:
while( LeftToRead >= OperaWidth )
{
*DestBuff32++ = *ReadAddr32++; /* read from Flash */
LeftToRead -= OperaWidth;
}
if( LeftToRead > 0 ) /* any left to read? */
{
OperaWidth = /* drop down to MIN */
ThisElem-> MinAccessWidth;
/* transfer ptrs */
ReadAddr08 = (U8*)ReadAddr32;
ReadAddr16 = (U16*)ReadAddr32;
DestBuff08 = (U8*)DestBuff32;
DestBuff16 = (U16*)DestBuff32;
}
break;
default:
*NumberActuallyRead = /* this SHOULDN'T happen */
NumberToRead - LeftToRead;
return( ST_ERROR_BAD_PARAMETER );
}
}
/* write back to caller number of bytes read */
*NumberActuallyRead = NumberToRead - LeftToRead;
return RetValue;
}
/****************************************************************************
Name : STFLASH_Erase()
Description : Performs a direct erase of a whole block. For the ST
device supported, the Offset specified MUST fall on one
of the declared block boundaries, and the NumberToErase
MUST also match the Length declared for that block.
The call will FAIL if these pre-conditions are not met.
Parameters : STFLASH_Handle_t Handle identifies the Flash bank,
U32 Offset (from device BaseAddress), and
U32 NumberToErase (bytes to erase).
Return Value : ST_ErrorCode_t specified as
ST_NO_ERROR No errors occurred
ST_ERROR_INVALID_HANDLE Rogue Handle value
ST_ERROR_BAD_PARAMETER Invalid parameter(s)
ST_ERROR_TIMEOUT Erase Timeout limit reached
STFLASH_ERROR_ERASE Error during Erase sequence
STFLASH_ERROR_VPP_LOW Vpp below minimum
See Also : STFLASH_Init()
STFLASH_Write()
****************************************************************************/
/* HCX 修改8M/16M FLASH 块擦除操作的驱动 2002。12。27 */
ST_ErrorCode_t STFLASH_Erase( STFLASH_Handle_t Handle,
U32 Offset[],
U32 NumberToErase,
U32 iTotalBlockNum )
{
#pragma ST_device( EraseAddr32 )
#pragma ST_device( EraseAddr16 )
#pragma ST_device( EraseAddr08 )
#pragma ST_device( Code1Addr )
#pragma ST_device( Code2Addr )
#pragma ST_device( Code1Addr16 )
#pragma ST_device( Code2Addr16 )
int i;
stflash_Inst_t *ThisElem;
ST_ErrorCode_t RetValue = ST_NO_ERROR;
BOOL DoingErase = TRUE; /* until completion or time-out */
BOOL EraseLow = FALSE;
BOOL EraseHigh = FALSE;
BOOL ParamsValid = FALSE; /* initial assumption */
U32 CurrOffset = 0; /* start at BaseAddress */
U8 *TempAddress; /* for recasting */
U8 *Access_Addr; /* BaseAddress + Offset */
volatile U32 *EraseAddr32; /* 32 bit erase access address */
volatile U16 *EraseAddr16; /* 16 bit erase access address */
volatile U8 *EraseAddr08; /* 8 bit erase access address */
volatile U32 *Code1Addr;
volatile U32 *Code2Addr;
volatile U16 *Code1Addr16;
volatile U16 *Code2Addr16;
U32 Code1Data;
U32 Code2Data;
U16 Code1Data16;
U16 Code2Data16;
clock_t StartTime; /* time at which erase started */
clock_t Curr_Time; /* current (low-priority) time */
const clock_t ClocksPerSecond = ST_GetClocksPerSecond();
/* Delay used to avoid busy wait */
U32 Data1, Data2;
/* Perform necessary validity checks */
ThisElem = (stflash_Inst_t *)Handle;
if( ThisElem->MagicNumber != MAGIC_NUMBER ) /* rogue Handle value? */
{
return( ST_ERROR_INVALID_HANDLE );
}
/* walk through STFLASH_Block_t array checking
that both Offset and NumberToErase are legal */
for( i = 0; i < ThisElem->NumberOfBlocks; i++ )
{
if( ( CurrOffset == Offset[0] ) && /* start match? */
( ThisElem->Blocks[i].Length ==
NumberToErase ) ) /* length match? */
{
ParamsValid = TRUE;
break; /* stop searching */
}
CurrOffset += ThisElem->Blocks[i].Length; /* next block */
}
if( !ParamsValid ) /* start/length mismatch block? */
{
return( ST_ERROR_BAD_PARAMETER );
}
if( ThisElem->DeviceType == STFLASH_M29W800T || ThisElem->DeviceType == STFLASH_M29W800B ||\
ThisElem->DeviceType == STFLASH_M29W1600T || ThisElem->DeviceType == STFLASH_M29W1600B )
{
switch( ThisElem->MaxAccessWidth )
{
case STFLASH_ACCESS_32_BITS:
/* Setup access pointers */
Code1Addr = (U32*)ThisElem->BaseAddress +
M29W800T_CODED_ADDR1;
Code2Addr = (U32*)ThisElem->BaseAddress +
M29W800T_CODED_ADDR2;
Code1Data = M29W800T_CODED_DATA1;
Code2Data = M29W800T_CODED_DATA2;
EraseAddr32 = (U32*)( (U32)ThisElem->BaseAddress + Offset[0] );
/* Start Erase */
StartTime = time_now(); /* ticks at Erase start */
/* Cycle 1 - Coded cycle 1 */
*Code1Addr = Code1Data;
/* Cycle 2 - Coded cycle 2 */
*Code2Addr = Code2Data;
/* Cycle 3 - Block Erase Command */
*Code1Addr = M29W800T_BLOCK_ERASE;
/* Cycle 4 - Coded cycle 1 */
*Code1Addr = Code1Data;
/* Cycle 5 - Coded cycle 2 */
*Code2Addr = Code2Data;
/* Cycle 6 - Erase Confirm */
*EraseAddr32 = M29W800T_ERASE_CONFIRM;
/* Read DQ2, DQ5 & DQ6 */
Data1 = *EraseAddr32 & M29W800T_DQ256_MASK;
while( ( ( EraseLow == FALSE ) ||
( EraseHigh == FALSE ) ) && \
RetValue != ST_NO_ERROR )
{
/* It typically takes 2 to 3 seconds to erase a block
(depending on size) so deschedule to avoid busy wait */
task_delay( ClocksPerSecond );
/* Read DQ2, DQ5 & DQ6 on all chips */
Data2 = *EraseAddr32 & M29W800T_DQ256_MASK;
/* Are DQ2 and DQ6 toggling? */
if( Data1 == Data2 )
{
EraseLow = EraseHigh = TRUE; /* Erase was successful */
}
/* High or Low DQ5 = 1? */
else if( ( Data2 & M29W800T_DQ5_MASK ) != 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -