// ----------------------------------------------------------------------------
// ATMEL Microcontroller Software Support - ROUSSET -
// ----------------------------------------------------------------------------
// DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
// DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------
#include "project.h"
#include "dataflash.h"
#include <stdio.h>
#define AT91C_DF_PAGE_SIZE 1056/4
unsigned int Source [AT91C_DF_PAGE_SIZE];
unsigned int Data[AT91C_DF_PAGE_SIZE];
extern void AT91F_DBGU_Printk( char *buffer);
//*----------------------------------------------------------------------------
//* \fn AT91F_SpiInit
//* \brief
//*----------------------------------------------------------------------------
void AT91F_SpiInit(unsigned int uPCS)
{
volatile unsigned int uDummy;
// Configure PIO
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOA, // PIO controller base address
((unsigned int) AT91C_PA13_MOSI) |
((unsigned int) AT91C_PA12_MISO) |
((unsigned int) AT91C_PA11_NPCS0) |
((unsigned int) AT91C_PA14_SPCK), // Peripheral A
0); // Peripheral B
// Enables the SPI0 Clock
AT91F_SPI_CfgPMC();
// Reset SPI0
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
// Configure SPI0 in Master Mode with No CS selected
AT91C_BASE_SPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
// Configure CSx
if (uPCS == AT91C_SPI_PCS0_DATAFLASH)
*(AT91C_SPI_CSR + 0) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) | (AT91C_SPI_DLYBCT & DATAFLASH_TCHS) | ((AT91B_MASTER_CLOCK / AT91C_SPI_CLK) << 8);
else // if (uPCS == AT91C_SPI_PCS1_DATAFLASH)
*(AT91C_SPI_CSR + 1) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) | (AT91C_SPI_DLYBCT & DATAFLASH_TCHS) | ((AT91B_MASTER_CLOCK / AT91C_SPI_CLK) << 8);
// Choose CSx
AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
AT91C_BASE_SPI->SPI_MR |= ((uPCS << 16) & AT91C_SPI_PCS);
// SPI_Enable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
for (uDummy=0; uDummy<100000; uDummy++);
uDummy = AT91C_BASE_SPI->SPI_SR;
uDummy = AT91C_BASE_SPI->SPI_RDR;
}
//*-----------------------------------------------------------------------------
//* \fn : AT91F_DF_wait_ready
//* \brief
//*-----------------------------------------------------------------------------
char AT91F_DF_wait_ready(AT91PS_DF pDataFlash)
{
unsigned int timeout = 0;
while (timeout++ < AT91C_DF_TIMEOUT)
{
if (AT91F_DF_get_status(pDataFlash))
{
if (AT91F_DF_is_ready(pDataFlash))
return 1;
}
}
return 0;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashSendCommand
//* \brief Generic function to send a command to the dataflash
//*----------------------------------------------------------------------------
char AT91F_DF_send_command (
AT91PS_DF pDataFlash,
unsigned char bCmd, // Command value
unsigned char bCmdSize, // Command Size
char *pData, // Data to be sent
unsigned int dDataSize, // Data Size
unsigned int dAddress) // Dataflash Address
{
unsigned int dInternalAdr;
AT91PS_PDC pPdc;
// Try to get the dataflash semaphore
if ( (pDataFlash->bSemaphore) != UNLOCKED)
return (char) 0;
pDataFlash->bSemaphore = LOCKED;
// Compute command pattern
dInternalAdr = ((dAddress / AT91C_PAGE_SIZE(pDataFlash)) << AT91C_PAGE_OFFSET(pDataFlash)) \
+ (dAddress % AT91C_PAGE_SIZE(pDataFlash));
if (AT91C_DF_NB_PAGE(pDataFlash) >= 16384)
{
pDataFlash->command[0] = (bCmd & 0x000000FF) | \
((dInternalAdr & 0x0F000000) >> 16) | \
((dInternalAdr & 0x00FF0000) >> 0) | \
((dInternalAdr & 0x0000FF00) << 16);
pDataFlash->command[1] = (dInternalAdr & 0x000000FF);
if ((bCmd != DB_CONTINUOUS_ARRAY_READ) && (bCmd != DB_PAGE_READ))
bCmdSize++;
}
else
{
pDataFlash->command[0] = (bCmd & 0x000000FF) | \
((dInternalAdr & 0x00FF0000) >> 8) | \
((dInternalAdr & 0x0000FF00) << 8) | \
((dInternalAdr & 0x000000FF) << 24);
pDataFlash->command[1] = 0;
}
// Send Command and data through the SPI
pPdc = (AT91PS_PDC) &(pDataFlash->pSpi->SPI_RPR);
AT91F_PDC_DisableRx(pPdc);
AT91F_PDC_SetRx(pPdc, (char *) &(pDataFlash->command), bCmdSize);
AT91F_PDC_SetNextRx(pPdc, pData, dDataSize);
AT91F_PDC_DisableTx(pPdc);
AT91F_PDC_SetTx(pPdc, (char *) &(pDataFlash->command), bCmdSize);
AT91F_PDC_SetNextTx(pPdc, pData, dDataSize);
AT91F_PDC_EnableRx(pPdc);
AT91F_PDC_EnableTx(pPdc);
while (AT91F_DF_is_busy(pDataFlash) == LOCKED);
return 1;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlashHandler
//* \brief SPI Fixed Peripheral C interrupt handler.
//*----------------------------------------------------------------------------
AT91S_DF_SEM AT91F_DF_is_busy(
AT91PS_DF pDataFlash)
{
AT91PS_PDC pPdc;
AT91PS_SPI pSpi = pDataFlash->pSpi;
unsigned int dStatus = pSpi->SPI_SR;
//* If End of Receive Transfer interrupt occurred
if (( dStatus & AT91C_SPI_RXBUFF))
{
pPdc = (AT91PS_PDC) &(pDataFlash->pSpi->SPI_RPR);
AT91F_PDC_DisableTx(pPdc);
AT91F_PDC_DisableRx(pPdc);
// Release the semaphore
pDataFlash->bSemaphore = UNLOCKED;
return UNLOCKED;
}
return pDataFlash->bSemaphore;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlash_Write_Page
//* \brief Copy Flash content in First DataFlash page
//*----------------------------------------------------------------------------
void AT91F_DataFlash_Write_Page(AT91PS_DF pDf,char* psrc ,unsigned int dAddress)
{
// Write a page
AT91F_DF_write_buf1(pDf, psrc, AT91C_PAGE_SIZE(pDf), dAddress);
AT91F_DF_wait_ready(pDf);
AT91F_DF_page_erase(pDf, dAddress);
AT91F_DF_wait_ready(pDf);
AT91F_DF_pgm_buf1(pDf, psrc, AT91C_PAGE_SIZE(pDf), dAddress);
AT91F_DF_wait_ready(pDf);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataFlash_Read_Page
//* \brief Read First DataFlash page
//*----------------------------------------------------------------------------
void AT91F_DataFlash_Read_Page(AT91PS_DF pDf, char *pData,unsigned int dAddress)
{
AT91F_DF_continuous_read(pDf, pData, AT91C_PAGE_SIZE(pDf), dAddress);
AT91F_DF_wait_ready(pDf);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DataflashProbe
//* \brief Done
//*----------------------------------------------------------------------------
int AT91F_DataflashProbe(AT91PS_DF pDf)
{
char *pResult = (char *)(pDf->command);
AT91F_DF_get_status(pDf);
//$$$ JPP why return (pResult[1] & 0x3C);
return (pResult[1] & 0x3F);
;
}
//*------------------------------------------------------------------------------
//* Function Name : AT91F_DataflashInit
//* \brief Done