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

📄 dataflash.c

📁 1、程序目的:介绍AT91SAM7A3 SPI0的基本用法: 2、 功能说明: 利用SPI0接口读写外部DATAFLASH的数据
💻 C
字号:
//*----------------------------------------------------------------------------
//* File Name           : dataflash.c
//* Object              : Flash routine
//* 创建人              : 张正锋  2005-11-3 embed_tech@126.com
//*----------------------------------------------------------------------------
// Include Standard files
#include "Dataflash.h"
#include "dbgu.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////
//*------------------ Global Variables------------------------------------
AT91S_DataflashFeatures		DeviceAT45DCB008;                 //定义一个数据结构为 AT45DCB008
AT91S_DataflashDesc		DataflashDesc;                    //定义一个数据结构为 DataflashDesc
AT91S_DataFlash			DataFlash;                        //定义一个数据结构为 DataFlash
unsigned char  Buffer_Dataflash[BUFFER_SIZE_DATAFLASH];           //定义一个缓冲区为   DataFlash
//////////////////////////////////////////////////////////////////////////////////////////////////////
//*----------------------------------------------------------------------------
//* \fn    AT91F_SPI0_CfgSPI
//* \brief Config SPI IP
//*----------------------------------------------------------------------------
static void  AT91F_SPI0_CfgSPI(void)
{
    //* Reset the SPI0
	AT91F_SPI_Reset(AT91C_BASE_SPI0);

    //* Configure SPI0 in Master Mode--Fixed peripher----Mode detection disenable---NPCS3
	AT91F_SPI_CfgMode(AT91C_BASE_SPI0, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (0x7<<16));

    //* Configure SPI0 CS3 for DataFlash AT45DCB321C 8 bite
	AT91F_SPI_CfgCs(AT91C_BASE_SPI0,3, AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & 0x100000) |((MCK/ (DATAFLASH_CLK)) << 8));

    //* Enable the SPI
       AT91F_SPI_Enable(AT91C_BASE_SPI0);
}
 //*----------------------------------------------------------------------------
//* \fn    AT91F_CfgDataFlash_AT45DCB008
//* \brief Config DataFlash Structures
//*----------------------------------------------------------------------------
static void AT91F_CfgDataFlash_AT45DCB008(void)
{
       // Init AT91S_DataflashFeatures Structure for AT45DCB008   <<=>> AT45DB642
	DeviceAT45DCB008.pages_number = 8192;
	DeviceAT45DCB008.pages_size   = 1056;
	DeviceAT45DCB008.page_offset  = 11;
	DeviceAT45DCB008.byte_mask    = 0x700;
	
	// Init AT91S_DataflashDesc Structure
	DataflashDesc.state             = IDLE;
	DataflashDesc.DataFlash_state   = IDLE;

	// Init AT91S_DataFlash Global Structure, by default AT45DCB008  choosen !!!
	DataFlash.pDataFlashDesc = &DataflashDesc;
	DataFlash.pDevice 	 = &DeviceAT45DCB008;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_DataFlashHandler
//* \brief SPI Fixed Peripheral C interrupt handler.
//*----------------------------------------------------------------------------
static 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;
               //* Enable PDC sent and receive --PDC Transfer Control Register
        	AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
        	return;
    	   }	
    }
        //state  error
	pDesc->state = ERROR;
       // Disenable PDC send  and  receive
	AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
      //disenable other (except RXBUFF) interrupt
       AT91C_BASE_SPI0->SPI_IDR = status;
}

 //*----------------------------------------------------------------------------
//* \fn    AT91F_SPI_Handler
//* \brief SPI Handler
//*----------------------------------------------------------------------------
void AT91F_SPI0_Handler(void)
{
   unsigned int status;
   //disenable DBGU interrupt
   AT91F_AIC_DisableIt(AT91C_BASE_AIC,AT91C_ID_SPI0);
  //--------------------------------------------------------------------------
   //get SPI_SR and SPI_IMR ----Status AND Interrupt Mask Status
   status=(AT91F_SPI_GetStatus (AT91C_BASE_SPI0)&AT91F_SPI_GetInterruptMaskStatus(AT91C_BASE_SPI0));
   AT91F_DataFlashHandler(DataFlash.pDataFlashDesc, status);
   //---------------------------------------------------------------------
   // Enable SPI interrupt
   AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_SPI0);
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_CfgSPIForDataFlash
//* \brief This function initialize SPI for Two ranges of DataFlash:
//* \brief SeriAl DataFlash AT45DB on CS0 AND DataFlash Card AT45DCB on CS3
//*----------------------------------------------------------------------------
void AT91F_CfgSPIForDataFlash(void )
{
  // ============================= Init SPI Interface =============================
  // AT91F_DBGU_Printk("\n\rInit SPI Interface\n\r");
   // Init SPI for DataFlash interface
   AT91F_SPI0_CfgPIO();	 //in lib_AT91SAM7A3.H
   //SPI PMC
   AT91F_SPI0_CfgPMC();  //in lib_AT91SAM7A3.H
   // receive  buffer full interrupt  ---RXBUFF
   AT91F_SPI_EnableIt(AT91C_BASE_SPI0,0x1<<6); //in lib_AT91SAM7A3.H
   //Config SPI speciality
   AT91F_SPI0_CfgSPI();
   //open  PDC
   AT91F_PDC_Open(AT91C_BASE_PDC_SPI0);
  //configure AT45DCB008 and struct
   AT91F_CfgDataFlash_AT45DCB008();
   // Configure SPI interrupt
   AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
			  AT91C_ID_SPI0,
	                  AT91C_AIC_PRIOR_HIGHEST, //Highest 0x7  in AT91SAM7A3.H
			  AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, //0x05  in AT91SAM7A3.H
			  AT91F_SPI0_Handler);		
    // Enable SPI interrupt
    AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_SPI0);
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_SpiWrite
//* \brief set the PDC registers for a transfert
//*----------------------------------------------------------------------------
static void AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc )
{ 	
   	pDesc->state = BUSY;
   	
   	AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
   	
   	//* Initialize the Transmit and Receive Pointer
        AT91C_BASE_SPI0->SPI_RPR = (unsigned int)pDesc->rx_cmd_pt ;
        AT91C_BASE_SPI0->SPI_TPR = (unsigned int)pDesc->tx_cmd_pt ;

        //* Intialize the Transmit and Receive Counters
        AT91C_BASE_SPI0->SPI_RCR = pDesc->rx_cmd_size ;
        AT91C_BASE_SPI0->SPI_TCR = pDesc->tx_cmd_size ;

	if ( pDesc->tx_data_size != 0 )
   	{
	 //* Initialize the Next Transmit and Next Receive Pointer
    	AT91C_BASE_SPI0->SPI_RNPR = (unsigned int)pDesc->rx_data_pt ;
        AT91C_BASE_SPI0->SPI_TNPR = (unsigned int)pDesc->tx_data_pt ;

	//* Intialize the Next Transmit and Next Receive Counters
	 AT91C_BASE_SPI0->SPI_RNCR = pDesc->rx_data_size ;
	 AT91C_BASE_SPI0->SPI_TNCR = pDesc->tx_data_size ;
   	}
   	//* Enable RXBUFF Interrupt
        AT91C_BASE_SPI0->SPI_IER = AT91C_SPI_RXBUFF;
        //* pdc transfer control----- Enable  PDC sent and receive
   	AT91C_BASE_SPI0->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;

}

//*----------------------------------------------------------------------------
//* \fn    AT91F_DataFlashGetStatus
//* \brief Read the status register of the dataflash
//*----------------------------------------------------------------------------
static 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_DataFlashSendCommand
//* \brief Generic function to send a command to the dataflash
//*----------------------------------------------------------------------------
static 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));
   //return(AT91F_DataFlashSendCommand (pDataFlash,DB_PAGE_FASTPGM_BUF1, 4, dest)); //用此命令会出错
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_DataFlashPageErase
//* \brief Main memory page program through buffer 1 or buffer 2
//*----------------------------------------------------------------------------
AT91S_DataFlashStatus AT91F_DataFlashPageErase(
	AT91PS_DataFlash pDataFlash,
	unsigned char *src,
	unsigned int address,
	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_ERASE, 4, address));
}

//*----------------------------------------------------------------------------
//* \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;
}
//dataflash.c  over

/*
//##########################附注:供外部调用的函数####################################
extern  void AT91F_CfgSPIForDataFlash(void);  //dataflash 初始化
extern  AT91S_DataFlashStatus AT91F_DataFlashPageRead ( //读FLASH的一页
	AT91PS_DataFlash pDataFlash,
	unsigned int src,
	unsigned char *dataBuffer,
	int sizeToRead );
extern  AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf( //写一页
	AT91PS_DataFlash pDataFlash,
	unsigned char *src,
	unsigned int dest,
	unsigned int SizeToWrite);
extern  AT91S_DataFlashStatus AT91F_DataFlashPageErase( //擦除一页
	AT91PS_DataFlash pDataFlash,
	unsigned char *src,
	unsigned int address,
	unsigned int SizeToWrite);
extern  AT91S_DataFlashStatus AT91F_DataFlashWaitReady( //取得DATAFLASH的状态
        AT91PS_DataflashDesc pDataFlashDesc,
        unsigned int timeout);
//###################################################################################
*/




⌨️ 快捷键说明

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