www.pudn.com > at91rm9200_test.rar > obj_svcdataflash.c
//*---------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*---------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*-----------------------------------------------------------------------------
//* File Name : obj_svcdataflash.c
//* Object : Atmel AT45DBxxx DataFlash service.
//*
//* 1.0 14/01/02 HI : Creation
//* 1.2 08/10/02 FB HI : New structure
//*---------------------------------------------------------------------------
#include "services\obj_romboot.h"
#include "services\obj_svcdataflash.h"
#define AT91C_SPI_RXBUFF ((unsigned int) 0x1 << 6)
#define AT91C_SPI_TXBUFE ((unsigned int) 0x1 << 7)
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_SpiWrite
//* Object : set the PDC registers for a transfert
//* Input Parameters : DataFlash Descriptor
//* Output Parameters : none
//* Functions called : none
//*-----------------------------------------------------------------------------
static void AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc )
{
pDesc->state = BUSY;
//* Initialize the Transmit and Receive Pointer
SPI_BASE->SP_RPR = (u_int)pDesc->rx_cmd_pt ;
SPI_BASE->SP_TPR = (u_int)pDesc->tx_cmd_pt ;
//* Intialize the Transmit and Receive Counters
SPI_BASE->SP_RCR = pDesc->rx_cmd_size ;
SPI_BASE->SP_TCR = pDesc->tx_cmd_size ;
if ( pDesc->tx_data_size != 0 )
{
//* Initialize the Next Transmit and Next Receive Pointer
SPI_BASE->SP_RNPR = (u_int)pDesc->rx_data_pt ;
SPI_BASE->SP_TNPR = (u_int)pDesc->tx_data_pt ;
//* Intialize the Next Transmit and Next Receive Counters
SPI_BASE->SP_RNCR = pDesc->rx_data_size ;
SPI_BASE->SP_TNCR = pDesc->tx_data_size ;
}
//* Enable RXBUFF Interrupt
SPI_BASE->SP_IER = AT91C_SPI_RXBUFF;
SPI_BASE->SP_PTCR = PDC_TXTEN + PDC_RXTEN;
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashHandler
//* Object : SPI Fixed Peripheral C interrupt handler.
//* Input Parameters : DataFlash Service, status parameter
//* Output Parameters : none
//* Functions called : none
//*-----------------------------------------------------------------------------
void AT91F_DataFlashHandler(
AT91PS_SvcDataFlash pSvcDataFlash,
u_int status)
{
AT91PS_DataflashDesc pDesc = (AT91PS_DataflashDesc) &(pSvcDataFlash->DataFlashDesc) ;
//* 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 = *( (u_char *) (pDesc->rx_cmd_pt) +1);
//* Disable the Transmit Interrupt
SPI_BASE->SP_IDR = AT91C_SPI_RXBUFF;
SPI_BASE->SP_PTCR = PDC_TXTDIS + PDC_RXTDIS;
return;
}
}
pDesc->state = ERROR;
SPI_BASE->SP_PTCR = PDC_TXTDIS + PDC_RXTDIS;
SPI_BASE->SP_IDR = status;
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_OpenSvcDataFlash
//* Object : Open the DataFlash service
//* Input Parameters : DataFlash Service , APMC Base
//* Output Parameters : The service structure initialized
//* Functions called : none
//*-----------------------------------------------------------------------------
AT91PS_SvcDataFlash AT91F_OpenSvcDataFlash (
const AT91PS_APMC pApmc,
AT91PS_SvcDataFlash pSvcDataFlash)
{
pSvcDataFlash->Handler = AT91F_DataFlashHandler;
pSvcDataFlash->Status = AT91F_DataFlashGetStatus;
pSvcDataFlash->AbortCommand = AT91F_DataFlashAbortCommand;
pSvcDataFlash->PageRead = AT91F_DataFlashPageRead;
pSvcDataFlash->ContinuousRead = AT91F_DataFlashContinuousRead;
pSvcDataFlash->ReadBuffer = AT91F_DataFlashReadBuffer;
pSvcDataFlash->MainMemoryToBufferTransfert = AT91F_MainMemoryToBufferTransfert;
pSvcDataFlash->PagePgmBuf = AT91F_DataFlashPagePgmBuf;
pSvcDataFlash->WriteBuffer = AT91F_DataFlashWriteBuffer;
pSvcDataFlash->WriteBufferToMain = AT91F_WriteBufferToMain;
pSvcDataFlash->PageErase = AT91F_PageErase;
pSvcDataFlash->BlockErase = AT91F_BlockErase;
pSvcDataFlash->MainMemoryToBufferCompare = AT91F_MainMemoryToBufferCompare;
return pSvcDataFlash;
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashAbortCommand
//* Object : Allows to reset PDC & Interrupts
//* Input Parameters : DataFlash Descriptor
//* Return value : none
//*-----------------------------------------------------------------------------
void AT91F_DataFlashAbortCommand(AT91PS_DataflashDesc pDesc)
{
int status;
status = ( SPI_BASE->SP_SR & SPI_BASE->SP_IMR );
pDesc->state = IDLE;
SPI_BASE->SP_PTCR = PDC_TXTDIS + PDC_RXTDIS;
SPI_BASE->SP_IDR = status;
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashGetStatus
//* Object : Read the status register of the dataflash
//* Input Parameters : DataFlash Descriptor
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus 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;
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashSendCommand
//* Object : Generic function to send a command to the dataflash
//* Input Parameters : DataFlash Service
//* : = command operation code
//* : = size of the command
//* : = address associate to the command
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_DataFlashSendCommand (
AT91PS_SvcDataFlash pSvcDataFlash,
u_char OpCode,
u_int CmdSize,
u_int DataflashAddress)
{
u_int adr;
if ( (pSvcDataFlash->DataFlashDesc.state) != IDLE)
return DATAFLASH_BUSY;
//* process the address to obtain page address and byte address
adr = ((DataflashAddress / (pSvcDataFlash->pDevice->pages_size)) << pSvcDataFlash->pDevice->page_offset) + (DataflashAddress % (pSvcDataFlash->pDevice->pages_size));
//* fill the command buffer */
pSvcDataFlash->DataFlashDesc.command[0] = OpCode;
pSvcDataFlash->DataFlashDesc.command[1] = (u_char)((adr & 0x00FF0000) >> 16);
pSvcDataFlash->DataFlashDesc.command[2] = (u_char)((adr & 0x0000FF00) >> 8);
pSvcDataFlash->DataFlashDesc.command[3] = (u_char)(adr & 0x000000FF) ;
pSvcDataFlash->DataFlashDesc.command[4] = 0;
pSvcDataFlash->DataFlashDesc.command[5] = 0;
pSvcDataFlash->DataFlashDesc.command[6] = 0;
pSvcDataFlash->DataFlashDesc.command[7] = 0;
/* Initialize the SpiData structure for the spi write fuction */
pSvcDataFlash->DataFlashDesc.tx_cmd_pt = pSvcDataFlash->DataFlashDesc.command ;
pSvcDataFlash->DataFlashDesc.tx_cmd_size = CmdSize ;
pSvcDataFlash->DataFlashDesc.rx_cmd_pt = pSvcDataFlash->DataFlashDesc.command ;
pSvcDataFlash->DataFlashDesc.rx_cmd_size = CmdSize ;
/* send the command and read the data */
AT91F_SpiWrite (&(pSvcDataFlash->DataFlashDesc));
return DATAFLASH_OK;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Read Functions
///////////////////////////////////////////////////////////////////////////////////////////
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashPageRead
//* Object : Main memory page read
//* Input Parameters : DataFlash Service
//* : = dataflash address
//* : <*dataBuffer> = data buffer pointer
//* : = Number of bytes to read
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_DataFlashPageRead (
AT91PS_SvcDataFlash pSvcDataFlash,
u_int src,
u_char *dataBuffer,
int sizeToRead )
{
pSvcDataFlash->DataFlashDesc.rx_data_pt = dataBuffer ; /* buffer for the read operation*/
pSvcDataFlash->DataFlashDesc.rx_data_size = sizeToRead; /* Number of byte to read */
pSvcDataFlash->DataFlashDesc.tx_data_pt = dataBuffer ;
pSvcDataFlash->DataFlashDesc.tx_data_size = sizeToRead;
/* Send the command to the dataflash */
return (AT91F_DataFlashSendCommand (pSvcDataFlash, DB_PAGE_READ, 8, src));
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashContinuousRead
//* Object : Continuous stream Read
//* Input Parameters : DataFlash Service
//* : = dataflash address
//* : <*dataBuffer> = data buffer pointer
//* : = data buffer size
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_DataFlashContinuousRead (
AT91PS_SvcDataFlash pSvcDataFlash,
int src,
u_char *dataBuffer,
int sizeToRead )
{
//* Test the size to read in the device
if ( (src + sizeToRead) > (pSvcDataFlash->pDevice->pages_size * (pSvcDataFlash->pDevice->pages_number)))
return DATAFLASH_MEMORY_OVERFLOW;
pSvcDataFlash->DataFlashDesc.rx_data_pt = dataBuffer;
pSvcDataFlash->DataFlashDesc.rx_data_size = sizeToRead;
pSvcDataFlash->DataFlashDesc.tx_data_pt = dataBuffer;
pSvcDataFlash->DataFlashDesc.tx_data_size = sizeToRead;
/* Send the command to the dataflash */
return(AT91F_DataFlashSendCommand (pSvcDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src));
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashReadBuffer
//* Object : Read the dataflash SRAM Buffer 1 or 2
//* Input Parameters : DataFlash Service
//* : = Buffer 1 or 2
//* : <*dataBuffer> = data buffer pointer
//* : = data buffer size
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_DataFlashReadBuffer (
AT91PS_SvcDataFlash pSvcDataFlash,
u_char BufferCommand,
u_int bufferAddress,
u_char *dataBuffer,
int sizeToRead )
{
//* Test if the buffer command is legal
if ((BufferCommand != DB_BUF1_READ) && (BufferCommand != DB_BUF2_READ))
return DATAFLASH_BAD_COMMAND;
//* buffer address must be lower than page size
if (bufferAddress > pSvcDataFlash->pDevice->pages_size)
return DATAFLASH_BAD_ADDRESS;
if ( (pSvcDataFlash->DataFlashDesc.state) != IDLE)
return DATAFLASH_BUSY;
/*Format the buffer read command */
pSvcDataFlash->DataFlashDesc.command[0] = BufferCommand;
pSvcDataFlash->DataFlashDesc.command[1] = 0;
pSvcDataFlash->DataFlashDesc.command[2] = (u_char)(((u_int)(bufferAddress & pSvcDataFlash->pDevice->byte_mask)) >> 8) ;
pSvcDataFlash->DataFlashDesc.command[3] = (u_char)((u_int)bufferAddress & 0x00FF) ;
pSvcDataFlash->DataFlashDesc.command[4] = 0;
pSvcDataFlash->DataFlashDesc.tx_cmd_pt = pSvcDataFlash->DataFlashDesc.command ;
pSvcDataFlash->DataFlashDesc.tx_cmd_size = 5 ;
pSvcDataFlash->DataFlashDesc.rx_cmd_pt = pSvcDataFlash->DataFlashDesc.command ;
pSvcDataFlash->DataFlashDesc.rx_cmd_size = 5 ;
pSvcDataFlash->DataFlashDesc.rx_data_pt = dataBuffer ;
pSvcDataFlash->DataFlashDesc.tx_data_pt = dataBuffer ;
pSvcDataFlash->DataFlashDesc.rx_data_size = sizeToRead ;
pSvcDataFlash->DataFlashDesc.tx_data_size = sizeToRead ;
AT91F_SpiWrite(&(pSvcDataFlash->DataFlashDesc)) ;
return DATAFLASH_OK;
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_MainMemoryToBufferTransfert
//* Object : Read a page in the SRAM Buffer 1 or 2
//* Input Parameters : DataFlash Service
//* : Page concerned
//* :
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_MainMemoryToBufferTransfert(
AT91PS_SvcDataFlash pSvcDataFlash,
u_char BufferCommand,
u_int page)
{
//* Test if the buffer command is legal
if ((BufferCommand != DB_PAGE_2_BUF1_TRF) && (BufferCommand != DB_PAGE_2_BUF2_TRF))
return DATAFLASH_BAD_COMMAND;
//* no data to transmit or receive
pSvcDataFlash->DataFlashDesc.tx_data_size = 0;
return(AT91F_DataFlashSendCommand (pSvcDataFlash, BufferCommand, 4, page*pSvcDataFlash->pDevice->pages_size));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Write Functions
///////////////////////////////////////////////////////////////////////////////////////////
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashPagePgmBuf
//* Object : Main memory page program through buffer 1 or buffer 2
//* Input Parameters : DataFlash Service
//* : <*src> = Source buffer
//* : = dataflash destination address
//* : = data buffer size
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_DataFlashPagePgmBuf(
AT91PS_SvcDataFlash pSvcDataFlash,
u_char BufferCommand,
u_char *src,
u_int dest,
u_int SizeToWrite)
{
//* Test if the buffer command is legal
if ((BufferCommand != DB_PAGE_PGM_BUF1) && (BufferCommand != DB_PAGE_PGM_BUF2))
return DATAFLASH_BAD_COMMAND;
pSvcDataFlash->DataFlashDesc.tx_data_pt = src ;
pSvcDataFlash->DataFlashDesc.tx_data_size = SizeToWrite ;
pSvcDataFlash->DataFlashDesc.rx_data_pt = src;
pSvcDataFlash->DataFlashDesc.rx_data_size = SizeToWrite;
/* Send the command to the dataflash */
return(AT91F_DataFlashSendCommand (pSvcDataFlash, BufferCommand, 4, dest));
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_DataFlashWriteBuffer
//* Object : Write data to the internal sram buffer 1 or 2
//* Input Parameters : DataFlash Service
//* : = command to write buffer1 or buffer2
//* : <*dataBuffer> = data buffer to write
//* : = address in the internal buffer
//* : = data buffer size
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_DataFlashWriteBuffer (
AT91PS_SvcDataFlash pSvcDataFlash,
u_char BufferCommand,
u_char *dataBuffer,
u_int bufferAddress,
int SizeToWrite )
{
//* Test if the buffer command is legal
if ((BufferCommand != DB_BUF1_WRITE) && (BufferCommand != DB_BUF2_WRITE))
return DATAFLASH_BAD_COMMAND;
//* buffer address must be lower than page size
if (bufferAddress > pSvcDataFlash->pDevice->pages_size)
return DATAFLASH_BAD_ADDRESS;
if ( (pSvcDataFlash->DataFlashDesc.state) != IDLE)
return DATAFLASH_BUSY;
//* Send first Write Command
pSvcDataFlash->DataFlashDesc.command[0] = BufferCommand;
pSvcDataFlash->DataFlashDesc.command[1] = 0;
pSvcDataFlash->DataFlashDesc.command[2] = (u_char)(((u_int)(bufferAddress & pSvcDataFlash->pDevice->byte_mask)) >> 8) ;
pSvcDataFlash->DataFlashDesc.command[3] = (u_char)((u_int)bufferAddress & 0x00FF) ;
pSvcDataFlash->DataFlashDesc.tx_cmd_pt = pSvcDataFlash->DataFlashDesc.command ;
pSvcDataFlash->DataFlashDesc.tx_cmd_size = 4 ;
pSvcDataFlash->DataFlashDesc.rx_cmd_pt = pSvcDataFlash->DataFlashDesc.command ;
pSvcDataFlash->DataFlashDesc.rx_cmd_size = 4 ;
pSvcDataFlash->DataFlashDesc.rx_data_pt = dataBuffer ;
pSvcDataFlash->DataFlashDesc.tx_data_pt = dataBuffer ;
pSvcDataFlash->DataFlashDesc.rx_data_size = SizeToWrite ;
pSvcDataFlash->DataFlashDesc.tx_data_size = SizeToWrite ;
AT91F_SpiWrite( &pSvcDataFlash->DataFlashDesc );
return DATAFLASH_OK;
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_WriteBufferToMain
//* Object : Write buffer to the main memory
//* Input Parameters : DataFlash Service
//* : = command to send to buffer1 or buffer2
//* : = main memory address
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_WriteBufferToMain (
AT91PS_SvcDataFlash pSvcDataFlash,
u_char BufferCommand,
u_int dest )
{
//* Test if the buffer command is correct
if ((BufferCommand != DB_BUF1_PAGE_PGM) &&
(BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
(BufferCommand != DB_BUF2_PAGE_PGM) &&
(BufferCommand != DB_BUF2_PAGE_ERASE_PGM) )
return DATAFLASH_BAD_COMMAND;
//* no data to transmit or receive
pSvcDataFlash->DataFlashDesc.tx_data_size = 0;
/* Send the command to the dataflash */
return(AT91F_DataFlashSendCommand (pSvcDataFlash, BufferCommand, 4, dest));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Erase Functions
///////////////////////////////////////////////////////////////////////////////////////////
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_PageErase
//* Object : Erase a page in dataflash
//* Input Parameters : DataFlash Service
//* : = Number of the page to erase
//* :
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_PageErase (
AT91PS_SvcDataFlash pSvcDataFlash,
u_int PageNumber)
{
pSvcDataFlash->DataFlashDesc.tx_data_size = 0;
/* Send the command to the dataflash */
return(AT91F_DataFlashSendCommand (pSvcDataFlash, DB_PAGE_ERASE, 4, PageNumber*pSvcDataFlash->pDevice->pages_size));
}
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_BlockErase
//* Object : Erase a block of 8 pages
//* Input Parameters : DataFlash Service
//* : = number of the block to erase
//* :
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_BlockErase (
AT91PS_SvcDataFlash pSvcDataFlash,
u_int BlockNumber )
{
pSvcDataFlash->DataFlashDesc.tx_data_size = 0;
/* Send the command to the dataflash */
return(AT91F_DataFlashSendCommand (pSvcDataFlash, DB_BLOCK_ERASE, 4, BlockNumber*8*pSvcDataFlash->pDevice->pages_size));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Compare Functions
///////////////////////////////////////////////////////////////////////////////////////////
//*-----------------------------------------------------------------------------
//* Function Name : AT91F_MainMemoryToBufferCompare
//* Object : Compare the contents of a page and one of the sram buffer
//* Input Parameters : DataFlash Service
//* : :specify the sram buffer to compare
//* : : specify the page to compare
//* : then after that operation, check the 6th bit of the status register
//* Return value : State of the dataflash
//*-----------------------------------------------------------------------------
AT91S_SvcDataFlashStatus AT91F_MainMemoryToBufferCompare(
AT91PS_SvcDataFlash pSvcDataFlash,
u_char BufferCommand,
u_int page)
{
//* Test if the buffer command is legal
if ((BufferCommand != DB_PAGE_2_BUF1_CMP ) && (BufferCommand != DB_PAGE_2_BUF2_CMP ))
return DATAFLASH_BAD_COMMAND;
//* no data to transmit or receive
pSvcDataFlash->DataFlashDesc.tx_data_size = 0;
return(AT91F_DataFlashSendCommand (pSvcDataFlash, BufferCommand, 4, page*pSvcDataFlash->pDevice->pages_size));
}