?? flash.c
字號:
#include "Board.h"
#include "flash.h"
#include <string.h>
#include "datatype.h"
char lock;// lock=1 : write flash ; lock=2 :read flash ; lock=3:unlock.
unsigned char read_flash_timer; //定時器
AT91S_DataflashDesc flashDesc;
unsigned char flash_writebuf[528]; //用于PDC發送數據時的緩存
unsigned char command_arry[8];
//unsigned short file_index[264];
//unsigned short file_index2[264];
//unsigned char flash_readbuf[528];
extern void memcpy_(unsigned char *pd, unsigned char *ps, unsigned short len);
//* Global Variables
AT91S_DataflashFeatures DeviceAT45DB;
AT91S_DataflashFeatures DeviceAT45DCB;
AT91S_DataflashDesc DataflashDesc;
AT91S_DataFlash DataFlash;
//char Buffer_Dataflash[BUFFER_SIZE_DATAFLASH];
//*----------------------------------------------------------------------------
//* \fn AT91F_SpiWrite
//* \brief set the PDC registers for a transfert
//*----------------------------------------------------------------------------
static void AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc )
{
AT91PS_PDC pdc;
pDesc->state = BUSY;
pdc =(AT91PS_PDC) &AT91C_BASE_SPI0->SPI_RPR;
////////////////////////////////////////////////////////////////////////
// AT91F_PDC_DisableRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR));
// AT91F_PDC_SetRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR), 0, 0);
// AT91F_PDC_SetNextRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR), 0, 0);
// AT91F_PDC_EnableRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR));
/////////////////////////////////////////////////////////////////////////////
pdc->PDC_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
//* Initialize the Transmit and Receive Pointer
pdc->PDC_RPR = (unsigned int)pDesc->rx_cmd_pt ;
pdc->PDC_TPR = (unsigned int)pDesc->tx_cmd_pt ;
//* Intialize the Transmit and Receive Counters
// pdc->PDC_RCR = pDesc->rx_cmd_size ;//closed by ChengDong Lu at 04/12/2006
// pdc->PDC_TCR = pDesc->tx_cmd_size ;//closed by ChengDong Lu at 04/12/2006
AT91C_BASE_SPI0->SPI_RCR = pDesc->tx_cmd_size ;//added by ChengDong Lu
AT91C_BASE_SPI0->SPI_TCR = pDesc->tx_cmd_size ;//added by ChengDong Lu
if ( pDesc->tx_data_size != 0 )
{
//* Initialize the Next Transmit and Next Receive Pointer
pdc->PDC_RNPR = (unsigned int)pDesc->rx_data_pt ;
pdc->PDC_TNPR = (unsigned int)pDesc->tx_data_pt ;
//* Intialize the Next Transmit and Next Receive Counters
pdc->PDC_RNCR = pDesc->rx_data_size ;
pdc->PDC_TNCR = pDesc->tx_data_size ;
}
//* Enable RXBUFF Interrupt
AT91C_BASE_SPI0->SPI_IER = AT91C_SPI_RXBUFF;
pdc->PDC_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashGetStatus
//* \brief Read the status register of the dataflash
//*----------------------------------------------------------------------------
AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc)
{
//* if a transfert is in progress ==> return 0
if( (pDesc->state) != IDLE)
return DATAFLASH_BUSY;
//* first send the read status command (D7H)
pDesc->command[0] = DB_STATUS;
pDesc->command[1] = 0;
pDesc->DataFlash_state = GET_STATUS;
pDesc->tx_data_size = 0 ; //* Transmit the command and receive response
pDesc->tx_cmd_pt = pDesc->command ;
pDesc->rx_cmd_pt = pDesc->command ;
pDesc->rx_cmd_size = 2 ;
pDesc->tx_cmd_size = 2 ;
AT91F_SpiWrite (pDesc);
return DATAFLASH_OK;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashHandler
//* \brief SPI Fixed Peripheral C interrupt handler.
//*----------------------------------------------------------------------------
void AT91F_DataFlashHandler(
AT91PS_DataflashDesc pDesc,
unsigned int status)
{
//* If End of Receive Transfer interrupt occurred
if (( status & AT91C_SPI_RXBUFF))
{
if( pDesc->state == BUSY)
{
//* Next State
pDesc->state = IDLE;
if (pDesc->DataFlash_state == GET_STATUS)
pDesc->DataFlash_state = *( (unsigned char *) (pDesc->rx_cmd_pt) +1);
//* Disable the Transmit Interrupt
AT91C_BASE_SPI0->SPI_IDR = AT91C_SPI_RXBUFF;
AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
return;
}
}
pDesc->state = ERROR;
AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
AT91C_BASE_SPI0->SPI_IDR = status;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashSendCommand
//* \brief Generic function to send a command to the dataflash
//*----------------------------------------------------------------------------
AT91S_DataFlashStatus AT91F_DataFlashSendCommand (
AT91PS_DataFlash pDataFlash,
unsigned char OpCode,
unsigned int CmdSize,
unsigned int DataflashAddress)
{
unsigned int adr;
if ( (pDataFlash->pDataFlashDesc->state) != IDLE)
return DATAFLASH_BUSY;
//* process the address to obtain page address and byte address
adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) << pDataFlash->pDevice->page_offset) + (DataflashAddress % (pDataFlash->pDevice->pages_size));
//* fill the command buffer */
pDataFlash->pDataFlashDesc->command[0] = OpCode;
pDataFlash->pDataFlashDesc->command[1] = (unsigned char)((adr & 0x00FF0000) >> 16);
pDataFlash->pDataFlashDesc->command[2] = (unsigned char)((adr & 0x0000FF00) >> 8);
pDataFlash->pDataFlashDesc->command[3] = (unsigned char)(adr & 0x000000FF) ;
pDataFlash->pDataFlashDesc->command[4] = 0;
pDataFlash->pDataFlashDesc->command[5] = 0;
pDataFlash->pDataFlashDesc->command[6] = 0;
pDataFlash->pDataFlashDesc->command[7] = 0;
/* Initialize the SpiData structure for the spi write fuction */
pDataFlash->pDataFlashDesc->tx_cmd_pt = pDataFlash->pDataFlashDesc->command ;
pDataFlash->pDataFlashDesc->tx_cmd_size = CmdSize ;
pDataFlash->pDataFlashDesc->rx_cmd_pt = pDataFlash->pDataFlashDesc->command ;
pDataFlash->pDataFlashDesc->rx_cmd_size = CmdSize ;
/* send the command and read the data */
AT91F_SpiWrite (pDataFlash->pDataFlashDesc);
return DATAFLASH_OK;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashPageRead
//* \brief Main memory page read
//*----------------------------------------------------------------------------
AT91S_DataFlashStatus AT91F_DataFlashPageRead (
AT91PS_DataFlash pDataFlash,
unsigned int src,
unsigned char *dataBuffer,
int sizeToRead )
{
pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer ; //* buffer for the read operation
pDataFlash->pDataFlashDesc->rx_data_size = sizeToRead; //* Number of byte to read
pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer ;
pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead;
//* Send the command to the dataflash
return (AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_READ, 8, src));
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashPagePgmBuf
//* \brief Main memory page program through buffer 1 or buffer 2
//*----------------------------------------------------------------------------
AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(
AT91PS_DataFlash pDataFlash,
unsigned char *src,
unsigned int dest,
unsigned int SizeToWrite)
{
pDataFlash->pDataFlashDesc->tx_data_pt = src ;
pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite ;
pDataFlash->pDataFlashDesc->rx_data_pt = src;
pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
/* Send the command to the dataflash */
return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1, 4, dest));
}
//*----------------------------------------------------------------------------
//* \fn AT91F_SPI_Handler
//* \brief SPI Handler
//*----------------------------------------------------------------------------
void AT91F_SPI_Handler(void)
{
int status;
status =(AT91C_BASE_SPI0->SPI_SR & AT91C_BASE_SPI0->SPI_IMR);
AT91F_DataFlashHandler(DataFlash.pDataFlashDesc, status);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_CfgDataFlash
//* \brief Config DataFlash Structures
//*----------------------------------------------------------------------------
void AT91F_CfgDataFlash (void)
{
// Init AT91S_DataflashFeatures Structure for AT45DB642
DeviceAT45DB.pages_number = 8192;
DeviceAT45DB.pages_size = 1056;
DeviceAT45DB.page_offset = 11;
DeviceAT45DB.byte_mask = 0x700;
// Init AT91S_DataflashFeatures Structure for AT45DCB004 <=> AT45DB321B
DeviceAT45DCB.pages_number = 8192;
DeviceAT45DCB.pages_size = 528;
DeviceAT45DCB.page_offset = 10;
DeviceAT45DCB.byte_mask = 0x300;
// Init AT91S_DataflashDesc Structure
DataflashDesc.state = IDLE;
DataflashDesc.DataFlash_state = IDLE;
// Init AT91S_DataFlash Global Structure, by default AT45DB choosen !!!
DataFlash.pDataFlashDesc = &DataflashDesc;
DataFlash.pDevice = &DeviceAT45DCB;
}
/**********************************************************/
//初始化spi
/**********************************************************/
void spi_init(void)
{
//char temp[528];
unsigned int peripha;
unsigned int scbr0;
unsigned int delaybs0;
peripha = AT91C_PIO_PA11 | AT91C_PIO_PA12 |AT91C_PIO_PA15 | AT91C_PIO_PA16 | AT91C_PIO_PA17 ; // Configure in Output
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA , peripha,0);
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_SPI0) ;
AT91F_SPI_Reset(AT91C_BASE_SPI0);
AT91F_SPI_CfgMode ( AT91C_BASE_SPI0, AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED | AT91C_SPI_MODFDIS | AT91C_SPI_PCS | AT91C_SPI_DLYBCS);
//scbr0 = (unsigned int)0xff << 8 ;
scbr0 = (MCK / SPI_BAUD)<< 8 ;
delaybs0 = (unsigned int) 4 << 16;
//AT91C_BASE_SPI0->SPI_CSR[0] = AT91C_SPI_CPOL | AT91C_SPI_NCPHA | AT91C_SPI_BITS_8 | scbr0 | delaybs0;
AT91C_BASE_SPI0->SPI_CSR[0] = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | scbr0 | delaybs0;
AT91F_SPI_CfgPCS (AT91C_BASE_SPI0,0);
AT91F_SPI_Enable (AT91C_BASE_SPI0);
//初始化PDC:接收
AT91F_PDC_DisableRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR));
AT91F_PDC_SetRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR), 0, 0);
AT91F_PDC_SetNextRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR), 0, 0);
AT91F_PDC_EnableRx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR));
//初始化PDC:發送
AT91F_PDC_DisableTx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR));
AT91F_PDC_SetTx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR), 0,0);//close by ChengDong Lu at 04/12/2006
// AT91F_PDC_SetTx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR),temp,0);//added by ChengDong Lu at 04/12/2006
AT91F_PDC_SetNextTx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR),0,0);
AT91F_PDC_EnableTx((AT91PS_PDC) &(AT91C_BASE_SPI0->SPI_RPR));
AT91F_CfgDataFlash();
AT91C_BASE_SPI0->SPI_IER = AT91C_SPI_RXBUFF;
// Configure SPI interrupt
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SPI0, AT91C_AIC_PRIOR_HIGHEST, AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, AT91F_SPI_Handler);
//AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SPI0, AT91C_AIC_PRIOR_HIGHEST, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, AT91F_SPI_Handler);
// Enable SPI interrupt
//scbr0 = AT91C_BASE_SPI0->SPI_SR;
//delaybs0 = AT91C_BASE_SPI0->SPI_SR;
AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_SPI0);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashWaitReady
//* \brief wait for dataflash ready (bit7 of the status register == 1)
//*----------------------------------------------------------------------------
AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc pDataFlashDesc, unsigned int timeout)
{
unsigned int i;
pDataFlashDesc->DataFlash_state = IDLE;
do
{
AT91F_DataFlashGetStatus(pDataFlashDesc);
timeout--;
// dummy waiting time
for(i=0;i<10;i++);
}
while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && (timeout>0) );
if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
return DATAFLASH_ERROR;
return DATAFLASH_OK;
}
/*********************************************************************/
//讀flash的一個扇區
//成功則返回DATAFLASH_OK (0x1)
//否則返回0x0 或 0x2
/*********************************************************************/
unsigned int read_flash_block(unsigned char *buf, unsigned int block_number)
{
AT91S_DataFlashStatus flashstate;
flashstate = AT91F_DataFlashWaitReady(DataFlash.pDataFlashDesc,AT91C_DATAFLASH_TIMEOUT);
if(DATAFLASH_OK != flashstate)
{
return flashstate;
}
flashstate = AT91F_DataFlashPageRead(&DataFlash,(block_number * DataFlash.pDevice->pages_size), buf, DataFlash.pDevice->pages_size);
if(DATAFLASH_OK != flashstate)
{
return flashstate;
}
flashstate = AT91F_DataFlashWaitReady(DataFlash.pDataFlashDesc,AT91C_DATAFLASH_TIMEOUT);
return flashstate;
}
/*********************************************************************/
//寫flash的一個扇區
//成功則返回DATAFLASH_OK (0x1)
//否則返回DATAFLASH_BUSY(0x0) 或 DATAFLASH_ERROR(0x2) 或 0x3(寫時校驗出錯)
/*********************************************************************/
unsigned int write_flash_block(unsigned char *buf, unsigned int block_number)
{
AT91S_DataFlashStatus flashstate;
flashstate = AT91F_DataFlashWaitReady(DataFlash.pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
if(DATAFLASH_OK != flashstate)
{
return flashstate;
}
flashstate = AT91F_DataFlashPagePgmBuf(&DataFlash, buf, block_number * DataFlash.pDevice->pages_size, DataFlash.pDevice->pages_size);
if(DATAFLASH_OK != flashstate)
{
return flashstate;
}
flashstate = AT91F_DataFlashWaitReady(DataFlash.pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
if(DATAFLASH_OK != flashstate)
{
return flashstate;
}
//發一個命令,校驗一下寫進去的東西是否正確
flashstate = AT91F_DataFlashSendCommand (&DataFlash, 0x60, 4, block_number * DataFlash.pDevice->pages_size);
if(DATAFLASH_OK != flashstate)
{
return flashstate;
}
flashstate = AT91F_DataFlashWaitReady(DataFlash.pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
if(DataFlash.pDataFlashDesc->DataFlash_state & 0x40)
{
return (0x3);
}
return flashstate;
}
/*********************************************************************/
//寫flash的一個扇區(擴展函數)
//成功則返回DATAFLASH_OK (0x1)
//否則返回0x0 或 0x2
/*********************************************************************/
unsigned int write_flash_block_ext(unsigned char *buf, unsigned int block_number, unsigned int start_addr, unsigned int len)
{
AT91S_DataFlashStatus flashstate;
if(start_addr >= 512)
{
return (0);
}
if(len > (512 - start_addr))
{
return(0);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -