⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dataflash.c

📁 ucOS_9263_Source ucOS-ii for 9263 port,from Micrium.com
💻 C
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support  -  ROUSSET  -
 * ----------------------------------------------------------------------------
 * Copyright (c) 2006, Atmel Corporation

 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaiimer below.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the disclaimer below in the documentation and/or
 * other materials provided with the distribution.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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.
 * ----------------------------------------------------------------------------
 * File Name           : dataflash.c
 * Object              : ATMEL DataFlash High level functions
 * Creation            : NLe Jul 12th 2006
 *---------------------------------------------------------------------------
*/

#include <includes.h>

/*------------------------------------------------------------------------------*/
/* \fn    df_spi_init								*/
/* \brief Configure SPI								*/
/*------------------------------------------------------------------------------*/
static int df_spi_init(unsigned int pcs, unsigned int spi_csr)
{
	unsigned int ncs = 0;

	/* Open PIO for SPI0 */
	df_hw_init();

	/* Enables the SPI0 Clock */
	AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI0);

	/* Reset SPI0 */
	AT91C_BASE_SPI0->SPI_CR  =  AT91C_SPI_SWRST;

    /* Configure SPI0 in Master Mode with No CS selected */
    AT91C_BASE_SPI0->SPI_MR  =  AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;

	switch (pcs)
	{
		case AT91C_SPI_PCS0_DATAFLASH:	ncs = 0;	break;
		case AT91C_SPI_PCS1_DATAFLASH:	ncs = 1;	break;
		case AT91C_SPI_PCS2_DATAFLASH:	ncs = 2;	break;
		case AT91C_SPI_PCS3_DATAFLASH:	ncs = 3;	break;
	}
	/* Configure CSx */
	AT91C_BASE_SPI0->SPI_CSR[ncs] = spi_csr;

	/* Choose CSx */
	AT91C_BASE_SPI0->SPI_MR &= ~(0x0F << 16);
    AT91C_BASE_SPI0->SPI_MR |= ((pcs<<16) & AT91C_SPI_PCS);

	/* SPI_Enable */
    AT91C_BASE_SPI0->SPI_CR  =   AT91C_SPI_SPIEN;

	return 0;
}

/*------------------------------------------------------------------------------*/
/* \fn    df_is_busy								*/
/* \brief Test if SPI has received a buffer or not				*/
/*------------------------------------------------------------------------------*/
static AT91S_DF_SEM df_is_busy(
	AT91PS_DF pDataFlash)
{
	unsigned int dStatus = AT91C_BASE_SPI0->SPI_SR;

	/* If End of Receive Transfer interrupt occurred */
 	if (( dStatus & AT91C_SPI_RXBUFF))
 	{
        AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_TXTDIS;  /* PDC Disable Tx */
        AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_RXTDIS;  /* PDC Disable Rx */

 		/* Release the semaphore */
		pDataFlash->bSemaphore = UNLOCKED;
		return UNLOCKED;
	}
	return  pDataFlash->bSemaphore;
}

/*------------------------------------------------------------------------------*/
/* \fn    df_send_command							*/
/* \brief Generic function to send a command to the dataflash			*/
/*------------------------------------------------------------------------------*/
char 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;
 	div_t result = div(dAddress, AT91C_PAGE_SIZE(pDataFlash));

 	/* Try to get the dataflash semaphore */
	if ((pDataFlash->bSemaphore) != UNLOCKED)
		return (char) 0;
	pDataFlash->bSemaphore = LOCKED;

	/* Compute command pattern */
	dInternalAdr = (result.quot << AT91C_PAGE_OFFSET(pDataFlash)) + result.rem;

 	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 */
    AT91C_BASE_SPI0->SPI_PTCR  =   AT91C_PDC_RXTDIS;                     /* PDC Disable Rx*/
    AT91C_BASE_SPI0->SPI_RPR   =  (unsigned int) &(pDataFlash->command); /* PDC Set Rx */
    AT91C_BASE_SPI0->SPI_RCR   =   bCmdSize;
    AT91C_BASE_SPI0->SPI_RNPR  =  (unsigned int) pData;                  /* PDC Set Next	Rx */
    AT91C_BASE_SPI0->SPI_RNCR  =   dDataSize;

    AT91C_BASE_SPI0->SPI_PTCR  =   AT91C_PDC_TXTDIS;                     /* PDC Disable Tx */
    AT91C_BASE_SPI0->SPI_TPR   =  (unsigned int) &(pDataFlash->command); /* PDC Set Tx */
    AT91C_BASE_SPI0->SPI_TCR   =   bCmdSize;
    AT91C_BASE_SPI0->SPI_TNPR  =  (unsigned int) pData;                  /* PDC Set Next Tx */
    AT91C_BASE_SPI0->SPI_TNCR  =   dDataSize;

    AT91C_BASE_SPI0->SPI_PTCR  =   AT91C_PDC_RXTEN;                      /* PDC Enable Rx */
    AT91C_BASE_SPI0->SPI_PTCR  =   AT91C_PDC_TXTEN;                      /* PDC Enable Tx */

    while (df_is_busy(pDataFlash) == LOCKED);

	return 1;
}

/*------------------------------------------------------------------------------*/
/* \fn    df_wait_ready								*/
/* \brief wait for DataFlash to be ready					*/
/*------------------------------------------------------------------------------*/
static char df_wait_ready(AT91PS_DF pDataFlash)
{
	unsigned int timeout = 0;

	while (timeout++ < AT91C_DF_TIMEOUT)
	{
		if (df_get_status(pDataFlash))
		{
			if (df_is_ready(pDataFlash))
				return 1;
		}
	}

	return 0;
}

/*------------------------------------------------------------------------------*/
/* \fn    df_read								*/
/* \brief Read a block in dataflash						*/
/*------------------------------------------------------------------------------*/
static int df_read(
	AT91PS_DF pDf,
	unsigned int addr,
	unsigned char *buffer,
	unsigned int size)
{
	unsigned int SizeToRead;

	while (size)
	{
		SizeToRead = (size < AT91C_MAX_PDC_SIZE)? size : AT91C_MAX_PDC_SIZE;

		/* wait the dataflash ready status */
		df_wait_ready(pDf);
	    	df_continuous_read(pDf, (char *)buffer, SizeToRead, addr);

		size -= SizeToRead;
		addr += SizeToRead;
		buffer += SizeToRead;
	}

   	return 0;
}

/*----------------------------------------------------------------------*/
/* \fn    df_download							*/
/* \brief load the content of the dataflash				*/
/*----------------------------------------------------------------------*/
static int df_download(AT91PS_DF pDf, unsigned int img_addr, unsigned int img_size, unsigned int img_dest)
{
	/* read bytes in the dataflash */
	df_read(pDf, img_addr,(unsigned char *)img_dest, img_size);

	/* wait the dataflash ready status */
	df_wait_ready(pDf);

    return 0;
}

/*----------------------------------------------------------------------*/
/* \fn    df_probe							*/
/* \brief Returns DataFlash ID						*/
/*----------------------------------------------------------------------*/
static int df_probe(AT91PS_DF pDf)
{
    char *pResult = (char *)(pDf->command);

    df_get_status(pDf);
    return (pResult[1] & 0x3C);
}

/*----------------------------------------------------------------------*/
/* \fn    df_init							*/
/* \brief This function tries to identify the DataFlash connected	*/
/*----------------------------------------------------------------------*/
static int df_init (AT91PS_DF pDf)
{
	int dfcode = 0;
	int status = 1;

	/* Default: AT45DB321B */
	pDf->dfDescription.pages_number = 8192;
	pDf->dfDescription.pages_size = 528;
	pDf->dfDescription.page_offset = 10;

	dfcode = df_probe (pDf);

	switch (dfcode)
	{
/*		case AT45DB011B:
			pDf->dfDescription.pages_number = 512;
			pDf->dfDescription.pages_size = 264;
			pDf->dfDescription.page_offset = 9;
			break;

		case AT45DB021B:
			pDf->dfDescription.pages_number = 1024;
			pDf->dfDescription.pages_size = 264;
			pDf->dfDescription.page_offset = 9;
			break;

		case AT45DB041B:
			pDf->dfDescription.pages_number = 2048;
			pDf->dfDescription.pages_size = 264;
			pDf->dfDescription.page_offset = 9;
			break;

		case AT45DB081B:
			pDf->dfDescription.pages_number = 4096;
			pDf->dfDescription.pages_size = 264;
			pDf->dfDescription.page_offset = 9;
			break;
*/
		case AT45DB161B:
			pDf->dfDescription.pages_number = 4096;
			pDf->dfDescription.pages_size = 528;
			pDf->dfDescription.page_offset = 10;
			break;

		case AT45DB321B:
			pDf->dfDescription.pages_number = 8192;
			pDf->dfDescription.pages_size = 528;
			pDf->dfDescription.page_offset = 10;
			break;

		case AT45DB642:
			pDf->dfDescription.pages_number = 8192;
			pDf->dfDescription.pages_size = 1056;
			pDf->dfDescription.page_offset = 11;
			break;
/*
		case AT45DB1282:
			pDf->dfDescription.pages_number = 16384;
			pDf->dfDescription.pages_size = 1056;
			pDf->dfDescription.page_offset = 11;
			break;

		case AT45DB2562:
			pDf->dfDescription.pages_number = 16384;
			pDf->dfDescription.pages_size = 2112;
			pDf->dfDescription.page_offset = 12;
			break;

		case AT45DB5122:
			pDf->dfDescription.pages_number = 32768;
			pDf->dfDescription.pages_size = 2112;
			pDf->dfDescription.page_offset = 12;
			break;
*/
		default:
		        status = 0;
			break;
	}

	return status;
}

/*------------------------------------------------------------------------------*/
/* \fn    df_is_boot_valid							*/
/* \brief Check that the first bytes of the buffer are valid ARM vectors	*/
/*------------------------------------------------------------------------------*/
static signed int df_is_boot_valid(unsigned char *buffer)
{
	int i = 3;

 	/* Verify if the 28 first bytes of the sram correspond to ARM vectors
	   The sixth ARM vector contain the size of the code */
    	while(i < 28)
    	{
		if (i != 23)
		{
			if ((buffer[i] != 0xEA) && (buffer[i] != 0xE5) )
				return -1;
		}
		i+=4;
    	}

    	return 0;
}

/*------------------------------------------------------------------------------*/
/* \fn    load_df								*/
/* \brief This function loads dataflash content to specified address		*/
/*------------------------------------------------------------------------------*/	
int load_df(unsigned int pcs, unsigned int img_addr, unsigned int img_size, unsigned int img_dest)
{
    	AT91S_DF sDF;
    	AT91PS_DF pDf = (AT91PS_DF)&sDF;
    	unsigned int rxBuffer[128];

    	pDf->bSemaphore = UNLOCKED;

    	df_spi_init(pcs, DF_CS_SETTINGS);

    	if (!df_init(pDf)) {
        	return -1;
        }

#ifdef AT91SAM9260
	/* Test if a button has been pressed or not */
	/* Erase Page 0 to avoid infinite loop */
	df_recovery(pDf);
#endif

    	df_continuous_read(pDf, (char *)rxBuffer, 32, img_addr);
	df_wait_ready(pDf);

	if (df_is_boot_valid((unsigned char*)rxBuffer)) {
//		return -2;
    }

	return df_download(pDf, img_addr, img_size, img_dest);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -