@@ -1,7 +1,5 @@
# include "flashmem.h"
# define address_length 3
/* here: use NCPS2 @ PA10: */
# define SPI_CSR_NUM 2 // Chip Select register[] 0,1,2,3 (at91samv512 has 4)
@@ -11,7 +9,7 @@
# define PCS_2 ((1<<0)|(1<<1)|(0<<2)|(1<<3)) // 0xB - 1011
# define PCS_3 ((1<<0)|(1<<1)|(1<<2)|(0<<3)) // 0x7 - 0111
/* TODO: ## */
// TODO
# if (SPI_CSR_NUM == 0)
# define SPI_MR_PCS PCS_0
# elif (SPI_CSR_NUM == 1)
@@ -33,10 +31,7 @@
擦除指令, 擦除指令后必须将CS拉高, 否则不会执行
*/
// 初始化Flash
void FlashSetup ( )
{
void FlashSetup ( void ) {
// PA1 -> SPI_NCS3 chip select (MEM)
// PA10 -> SPI_NCS2 chip select (LCD)
// PA11 -> SPI_NCS0 chip select (FPGA)
@@ -83,14 +78,10 @@ void FlashSetup()
( 0 < < 0 ) ; // Clock Polarity inactive state is logic 0
// read first, empty buffer
if ( AT91C_BASE_SPI - > SPI_RDR = = 0 )
;
if ( AT91C_BASE_SPI - > SPI_RDR = = 0 ) { } ;
}
// end up SPI
void FlashStop ( void )
{
void FlashStop ( void ) {
//* Reset all the Chip Select register
AT91C_BASE_SPI - > SPI_CSR [ 0 ] = 0 ;
AT91C_BASE_SPI - > SPI_CSR [ 1 ] = 0 ;
@@ -106,12 +97,13 @@ void FlashStop(void)
// SPI disable
AT91C_BASE_SPI - > SPI_CR = AT91C_SPI_SPIDIS ;
Dbprintf ( " FlashStop " ) ;
if ( MF_DBGLEVEL > 3 ) Dbprintf ( " FlashStop " ) ;
StopTicks ( ) ;
}
// 发送一个字节 send one byte
uint16_t FlashSendByte ( uint32_t data )
{
// send one byte over SPI
uint16_t FlashSendByte ( uint32_t data ) {
uint16_t incoming = 0 ;
WDT_HIT ( ) ;
@@ -132,239 +124,249 @@ uint16_t FlashSendByte(uint32_t data)
return incoming ;
}
// send last one byte
// send last byte over SPI
uint16_t FlashSendLastByte ( uint32_t data ) {
return FlashSendByte ( data | AT91C_SPI_LASTXFER ) ;
}
// R ead state register 1
// r ead state register 1
uint8_t Flash_ReadStat1 ( void ) {
FlashSendByte ( READSTAT1 ) ;
uint8_t stat1 = FlashSendLastByte ( 0xFF ) ;
Dbprintf ( " stat1 [%02x] " , stat1 ) ;
if ( MF_DBGLEVEL > 3 ) Dbprintf ( " stat1 [%02x] " , stat1 ) ;
return stat1 ;
}
// R ead state register 2
// r ead state register 2
uint8_t Flash_ReadStat2 ( void ) {
FlashSendByte ( READSTAT2 ) ;
uint8_t stat2 = FlashSendLastByte ( 0xFF ) ;
Dbprintf ( " stat2 [%02x] " , stat2 ) ;
if ( MF_DBGLEVEL > 3 ) Dbprintf ( " stat2 [%02x] " , stat2 ) ;
return stat2 ;
}
// D etermine whether FLASHMEM is busy
// d etermine whether FLASHMEM is busy
bool Flash_CheckBusy ( uint16_t times ) {
bool bR et = ( Flash_ReadStat1 ( ) & BUSY ) ;
bool r et = ( Flash_ReadStat1 ( ) & BUSY ) ;
if ( ! bR et | | ! times | | ! ( times - - ) )
return bR et;
if ( ! r et | | ! times | | ! ( times - - ) )
return r et;
while ( times )
{
while ( times ) {
WDT_HIT ( ) ;
SpinDelayUs ( 1000 ) ; // wait 1ms
bR et = ( Flash_ReadStat1 ( ) & BUSY ) ;
if ( ! bR et)
WaitMS ( 1 ) ;
r et = ( Flash_ReadStat1 ( ) & BUSY ) ;
if ( ! r et)
break ;
times - - ;
}
return bR et;
return r et;
}
// read ID out
uint8_t Flash_ReadID ( void ) {
if ( Flash_CheckBusy ( 1000 ) )
return 0 ;
if ( Flash_CheckBusy ( 1000 ) ) return 0 ;
// Manufacture ID / device ID
uint8_t t0 = FlashSendByte ( ID ) ;
uint8_t t1 = FlashSendByte ( 0x00 ) ;
uint8_t t2 = FlashSendByte ( 0x00 ) ;
uint8_t t3 = FlashSendByte ( 0x00 ) ;
FlashSendByte ( ID ) ;
FlashSendByte ( 0x00 ) ;
FlashSendByte ( 0x00 ) ;
FlashSendByte ( 0x00 ) ;
uint8_t man_id = FlashSendByte ( 0xFF ) ;
uint8_t dev_id = FlashSendLastByte ( 0xFF ) ;
Dbprintf ( " [%02x] %02x %02x %02x | %02x %02x " , t0 , t1 , t2 , t3 , man_id , dev_id ) ;
if ( MF_DBGLEVEL > 3 ) Dbprintf ( " Flash ReadID | Man ID %02x | Device ID %02x " , man_id , dev_id ) ;
if ( ( man_id = = WINBOND_MANID ) & & ( dev_id = = WINBOND_DEVID ) )
return dev_id ;
//WINBOND_MANID
if ( man_id = = WINBOND_MANID ) {
Dbprintf ( " Correct read of Manucaturer ID [%02x] == %02x " , man_id , WINBOND_MANID ) ;
}
if ( man_id ! = WINBOND_MANID )
dev_id = 0 ;
return dev_id ;
return 0 ;
}
// 读取数据 address buffer length
uint8_t Flash_ReadDate ( uint32_t Address , uint8_t * Buffer , uint16_t len )
{
// read unique id for chip.
void Flash_UniqueID ( uint8_t * uid ) {
if ( Flash_CheckBusy ( 1000 ) ) return ;
// reading unique serial number
FlashSendByte ( UNIQUE_ID ) ;
FlashSendByte ( 0x00 ) ;
FlashSendByte ( 0x00 ) ;
FlashSendByte ( 0x00 ) ;
FlashSendByte ( 0x00 ) ;
uid [ 3 ] = FlashSendByte ( 0xFF ) ;
uid [ 2 ] = FlashSendByte ( 0xFF ) ;
uid [ 1 ] = FlashSendByte ( 0xFF ) ;
uid [ 0 ] = FlashSendLastByte ( 0xFF ) ;
}
uint8_t Flash_ReadData ( uint32_t address , uint8_t * out , uint16_t len ) {
// length should never be zero
if ( ! len | | Flash_CheckBusy ( 1000 ) )
return 0 ;
if ( ! len | | Flash_CheckBusy ( 1000 ) ) return 0 ;
FlashSendByte ( READDATA ) ;
FlashSendByte ( ( A ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( A ddress > > 8 ) & 0xFF ) ;
FlashSendByte ( ( A ddress > > 0 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 8 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 0 ) & 0xFF ) ;
uint16_t i = 0 ;
for ( ; i < ( len - 1 ) ; i + + )
Buffer [ i ] = FlashSendByte ( 0xFF ) ;
out [ i ] = FlashSendByte ( 0xFF ) ;
Buffer [ i ] = FlashSendLastByte ( 0xFF ) ;
out [ i ] = FlashSendLastByte ( 0xFF ) ;
return len ;
}
// 写入数据 地址 address 缓冲区 buffer 长度length
uint8_t Flash_WriteDate ( uint32_t A ddress, uint8_t * Buffer , uint16_t len )
{
// Write data
uint8_t Flash_WriteData ( uint32_t a ddress, uint8_t * in , uint16_t len ) {
// length should never be zero
if ( ! len | | Flash_CheckBusy ( 1000 ) )
return 0 ;
if ( ! len | | Flash_CheckBusy ( 1000 ) ) return 0 ;
// 不能跨越 256 字节边界
if ( ( ( A ddress & 255 ) + len ) > 256 )
return 0 ;
if ( ( ( a ddress & 255 ) + len ) > 256 ) return 0 ;
FlashSendByte ( PAGEPROG ) ;
FlashSendByte ( ( A ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( A ddress > > 8 ) & 0xFF ) ;
FlashSendByte ( ( A ddress > > 0 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 8 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 0 ) & 0xFF ) ;
uint16_t i = 0 ;
for ( ; i < ( len - 1 ) ; i + + )
FlashSendByte ( Buffer [ i ] ) ;
FlashSendByte ( in [ i ] ) ;
FlashSendLastByte ( Buffer [ i ] ) ;
FlashSendLastByte ( in [ i ] ) ;
return len ;
}
// enable the flash write
void Flash_WriteEnable ( )
{
void Flash_WriteEnable ( ) {
FlashSendLastByte ( WRITEENABLE ) ;
Dbprintf ( " Flash WriteE nabled " ) ;
if ( MF_DBGLEVEL > 3 ) Dbprintf ( " Flash Write e nabled " ) ;
}
// erase 4K at one time
bool Flash_Erase4k ( uint32_t A ddress)
{
if ( Address & ( 4096 - 1 ) )
{
Dbprintf ( " Flash_Erase4k : Address is not align at 4096 " ) ;
bool Flash_Erase4k ( uint32_t a ddress) {
if ( address & ( 4096 - 1 ) ) {
if ( MF_DBGLEVEL > 1 ) Dbprintf ( " Flash_Erase4k : Address is not align at 4096 " ) ;
return false ;
}
FlashSendByte ( SECTORERASE ) ;
FlashSendByte ( ( A ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( A ddress > > 8 ) & 0xFF ) ;
FlashSendLastByte ( ( A ddress > > 0 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 8 ) & 0xFF ) ;
FlashSendLastByte ( ( a ddress > > 0 ) & 0xFF ) ;
return true ;
}
// erase 32K at one time
bool Flash_Erase32k ( uint32_t A ddress)
{
if ( Address & ( 32 * 1024 - 1 ) )
{
Dbprintf ( " Flash_Erase4k : Address is not align at 4096 " ) ;
bool Flash_Erase32k ( uint32_t a ddress) {
if ( address & ( 32 * 1024 - 1 ) ) {
if ( MF_DBGLEVEL > 1 ) Dbprintf ( " Flash_Erase4k : Address is not align at 4096 " ) ;
return false ;
}
FlashSendByte ( BLOCK32ERASE ) ;
FlashSendByte ( ( A ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( A ddress > > 8 ) & 0xFF ) ;
FlashSendLastByte ( ( A ddress > > 0 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 8 ) & 0xFF ) ;
FlashSendLastByte ( ( a ddress > > 0 ) & 0xFF ) ;
return true ;
}
// erase 64k at one time
bool Flash_Erase64k ( uint32_t A ddress)
{
if ( A ddress & ( 64 * 1024 - 1 ) )
{
Dbprintf ( " Flash_Erase4k : Address is not align at 4096 " ) ;
bool Flash_Erase64k ( uint32_t a ddress) {
if ( a ddress & ( 64 * 1024 - 1 ) ) {
if ( MF_DBGLEVEL > 1 ) Dbprintf ( " Flash_Erase4k : Address is not align at 4096 " ) ;
return false ;
}
FlashSendByte ( BLOCK64ERASE ) ;
FlashSendByte ( ( A ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( A ddress > > 8 ) & 0xFF ) ;
FlashSendLastByte ( ( A ddress > > 0 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 16 ) & 0xFF ) ;
FlashSendByte ( ( a ddress > > 8 ) & 0xFF ) ;
FlashSendLastByte ( ( a ddress > > 0 ) & 0xFF ) ;
return true ;
}
// e rase all
void Flash_EraseChip ( void )
{
// E rase chip
void Flash_EraseChip ( void ) {
FlashSendLastByte ( CHIPERASE ) ;
}
// initialize
bool FlashInit ( void )
{
bool FlashInit ( void ) {
FlashSetup ( ) ;
if ( Flash_CheckBusy ( 1000 ) )
StartTicks ( ) ;
if ( Flash_CheckBusy ( 1000 ) ) {
StopTicks ( ) ;
return false ;
}
Dbprintf ( " FlashInit " ) ;
if ( MF_DBGLEVEL > 3 ) Dbprintf ( " FlashInit OK " ) ;
return true ;
}
void EXFLASH_TEST ( void )
{
uint8_t D ata [ 256 ] = { 0x00 , 0x01 , 0x02 } ;
uint8_t Data2 [ 256 ] = { 0x00 } ;
uint32_t FlashSize = 0 ;
void EXFLASH_TEST ( void ) {
uint8_t data [ 256 ] = { 0x00 , 0x01 , 0x02 } ;
uint8_t d ata2 [ 256 ] = { 0x00 } ;
if ( ! FlashInit ( ) ) return ;
Flash_ReadStat1 ( ) ;
switch ( Flash_ReadID ( ) )
{
case 0x11 : // W25X20CL
FlashSize = 2048 * 1024 ;
break ;
case 0x10 : // W25X10CL
FlashSize = 1024 * 1024 ;
break ;
case 0x05 : // W25X05CL
FlashSize = 512 * 1024 ;
break ;
}
Dbprintf ( " Flash Size = %dk " , FlashSize / 1024 ) ;
if ( FlashSize ! = 2048 * 1024 )
return ;
Dbprintf ( " Flash test write: 012 to 0x00 0x01 0x02 " ) ;
Flash_WriteEnable ( ) ;
Flash_Erase4k ( 0x00 ) ;
if ( Flash_CheckBusy ( 1000 ) )
{
if ( Flash_CheckBusy ( 1000 ) ) {
Dbprintf ( " Flash_Erase4k CheckBusy Error. " ) ;
return ;
}
Flash_ReadDate ( 0 , Data2 , 256 ) ;
Flash_ReadData ( 0 , data2 , 256 ) ;
Flash_WriteEnable ( ) ;
Flash_WriteDate ( 0x12 , D ata, sizeof ( D ata) ) ; // this will never run, cuz out of 256byte boundary
Flash_WriteDate ( 0x12 , D ata, 3 ) ;
if ( Flash_CheckBusy ( 1000 ) )
{
Flash_WriteData ( 0x12 , d ata, sizeof ( d ata) ) ; // this will never run, cuz out of 256byte boundary
Flash_WriteData ( 0x12 , d ata, 3 ) ;
if ( Flash_CheckBusy ( 1000 ) ) {
Dbprintf ( " Flash_WriteDate CheckBusy Error. " ) ;
return ;
}
Flash_ReadDate ( 0 , D ata2, 256 ) ;
Flash_ReadData ( 0 , d ata2, 256 ) ;
FlashStop ( ) ;
}
void Flashmem_print_status ( void ) {
DbpString ( " Flash memory " ) ;
if ( ! FlashInit ( ) ) {
DbpString ( " init....................FAIL " ) ;
return ;
}
DbpString ( " init....................OK " ) ;
uint8_t dev_id = Flash_ReadID ( ) ;
switch ( dev_id ) {
case 0x11 :
DbpString ( " Memory size.............2 mbits / 256kb " ) ;
break ;
case 0x10 :
DbpString ( " Memory size..... .......1 mbits / 128kb " ) ;
break ;
case 0x05 :
DbpString ( " Memory size.............512 kbits / 64kb " ) ;
break ;
default :
DbpString ( " Device ID............... --> Unknown <-- " ) ;
break ;
}
uint8_t uid [ 4 ] = { 0 , 0 , 0 , 0 } ;
Flash_UniqueID ( uid ) ;
Dbprintf ( " Unique ID...............0x%02x%02x%02x%02x % " , uid [ 3 ] , uid [ 2 ] , uid [ 1 ] , uid [ 0 ] ) ;
FlashStop ( ) ;
}