c第二阶段:
一从Dataflash加载到SDRAM中
load_df(AT91C_SPI_PCS_DATAFLASH, IMG_ADDRESS, IMG_SIZE,JUMP_ADDR);
具体参数代表的意思:
第一个参数:表示dataflash接在那个片选信号上
#define AT91C_SPI_PCS_DATAFLASH AT91C_SPI_PCS1_DATAFLASH /BootonSPI NCS0
/* Chip Select 1 : NPCS1%1101 */
#define AT91C_SPI_PCS1_DATAFLASH 0xD
第二个参数:表示要加载的代码在DataFlash的存储的开始位置
#define IMG_ADDRESS 0x8400 /*Image Address in DataFlash */
第三个参数:表示要加载代码的具体大小,一般加载要比实际编译的代码量稍大些
#define IMG_SIZE 0x33900 /* ImageSize in DataFlash */
第二个参数:表示加载??????
#define JUMP_ADDR 0x23F00000 /*Final Jump Address */
此函数的分析中有个重要结构体:
/* Dataflash DescriptorStructure */
typedef struct_AT91S_DF
{
unsigned char bCs;
AT91S_DF_SEM bSemaphore; /* SPI semaphore */
unsigned int command[2];
AT91S_DF_DESC dfDescription;
} AT91S_DF, *AT91PS_DF;
typedef enum _AT91S_DF_SEM { //枚举类型
UNLOCKED,
LOCKED
} AT91S_DF_SEM;
/* DataflashDescription Structure */
typedef struct_AT91S_DF_DESC {
int pages_number; /* dataflash page number */
int pages_size; /*dataflash page size */
int page_offset; /* page offset in command */
int block_size; /* nb page per block */
int byte_mask; /* byte mask in command */
int binaryPageMode; /* indicate ifconfigured in power-of-2 binary */
} AT91S_DF_DESC,*AT91PS_DF_DESC;
/*------------------------------------------------------------------------------*/
/* \fn load_df */
/* \brief This functionloads dataflash content to specified address */
/*------------------------------------------------------------------------------*/
int load_df(unsignedint pcs, unsigned int img_addr, unsigned int img_size, unsigned int img_dest)
{
AT91S_DF sDF;//声明Dataflash Descriptor Structure结构体名称是sDF;
AT91PS_DF pDf = (AT91PS_DF)&sDF;//声明一个结构体指针pDF 同时指向 sDF
unsigned int rxBuffer[128];
pDf->bSemaphore = UNLOCKED;//初始化Dataflash的结构体的信号指示
df_spi_init(pcs, DF_CS_SETTINGS);//SPI初始化,配置SPI
if (!df_init(pDf))//判断DF的具体型号及大小,同时初始化Dataflash结构体
//如果异常则直接返回status=0,表示无df
return -1;//本次加载直接返回
#ifdefined(AT91SAM9260) || defined(AT91SAM9XE) || defined(AT91SAM9G20)
/* Test if a button has been pressed or not*/
/* Erase Page 0 to avoid infinite loop *//
// 测试,如果一个按钮被按下,擦除页0,以避免无限循环
df_recovery(pDf);
#endif
df_continuous_read(pDf, (char *)rxBuffer,32, img_addr);// Continuous arrayread
df_wait_ready(pDf);// wait for DataFlash to be ready
return df_download(pDf, img_addr, img_size,img_dest); //load the content of thedataflash
}
具体函数的分析:
1 ConfigureSPI
/*------------------------------------------------------------------------------*/
/* \fn df_spi_init */
/* \brief Configure SPI */
/*------------------------------------------------------------------------------*/
static intdf_spi_init(unsigned int pcs, unsigned int spi_csr)
{
unsigned int ncs = 0;
/* Open PIO for SPI0 */
df_hw_init();// 配置IO
/* Enables the SPI0 Clock */
writel((1 << AT91C_ID_SPI), PMC_PCER + AT91C_BASE_PMC);
/* Reset SPI0 */
write_spi(SPI_CR, AT91C_SPI_SWRST);
/* SPI may need two software reset */
write_spi(SPI_CR, AT91C_SPI_SWRST);
/* Configure SPI0 in Master Mode with No CS selected */
write_spi(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 */
write_spi(SPI_CSR + 4*ncs, spi_csr);
/* Choose CSx */
write_spi(SPI_MR, read_spi(SPI_MR) & 0xFFF0FFFF);
write_spi(SPI_MR, read_spi(SPI_MR) | ((pcs<<16) & AT91C_SPI_PCS));
/* SPI_Enable */
write_spi(SPI_CR, AT91C_SPI_SPIEN);
return 0;
}
2 判断DF的具体型号及大小
/*----------------------------------------------------------------------*/
/* \fn df_init */
/* \brief This functiontries 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:
case AT45DB021B:
case AT45DB041B:
case AT45DB081B:
case AT45DB161B:
case AT45DB321B:
*/
case AT45DB642:
pDf->dfDescription.pages_number = 8192;
pDf->dfDescription.pages_size = 1056;
pDf->dfDescription.page_offset = 11;
break;
/*
case AT45DB1282:
case AT45DB2562:
case AT45DB5122:
*/
default:
status =0;
break;
}
return status;
}
/*----------------------------------------------------------------------*/
/* \fn df_probe */
/* \brief ReturnsDataFlash ID */
/*----------------------------------------------------------------------*/
static intdf_probe(AT91PS_DF pDf)
{
char *pResult = (char *)(pDf->command);
df_get_status(pDf);//发送命令读取df的状态信息
// Check if DataFlash has been configuredin binary page mode
if ((pResult[1] & 0x1) == 0x1) {
pDf->dfDescription.binaryPageMode =1;
#ifdef CFG_DEBUG
dbg_print("DataFlash in binary mode\n\r");
#endif /* CFG_DEBUG */
} else {
pDf->dfDescription.binaryPageMode =0;
}
return (pResult[1] & 0x3C);//返回DF的ID号
}
3 Continuous array read
#definedf_continuous_read(pDf, pData, dDataSize, dAddress) \
df_send_command(pDf, DB_CONTINUOUS_ARRAY_READ, 8,pData, dDataSize, dAddress)
DB_CONTINUOUS_ARRAY_READ =0xE8 /* Continuous array read */
df_continuous_read(pDf, (char *)rxBuffer, 32,img_addr);
df_send_command(pDf, 0Xe8, 8, rxBuffer, 32,img_addr)
/*------------------------------------------------------------------------------*/
/* \fn df_send_command */
/* \brief Generic function to send a command tothe dataflash */
/*------------------------------------------------------------------------------*/
char df_send_command (
AT91PS_DFpDataFlash,
unsignedchar bCmd, /* Command value */ 0Xe8
unsignedchar bCmdSize, /* Command Size */ 8
char *pData, /* Data to be sent */ rxBuffer
unsignedint dDataSize, /* Data Size */ 32
unsignedint dAddress) /*Dataflash Address */ img_addr
{
unsignedint dInternalAdr;
div_t result = udiv(dAddress, AT91C_PAGE_SIZE(pDataFlash));//??????
/* Try to get the dataflash semaphore */
if((pDataFlash->bSemaphore) != UNLOCKED) //DF信号必须是UNLOCKED
return(char) 0;
pDataFlash->bSemaphore= LOCKED;//DF信号标记
/*Compute command pattern */
if(pDataFlash->dfDescription.binaryPageMode == 0) {
dInternalAdr = (result.quot << AT91C_PAGE_OFFSET(pDataFlash)) + result.rem;
} else{
dInternalAdr = dAddress;
}
// AT45DB642 pDf->dfDescription.pages_number = 8192;
if (AT91C_DF_NB_PAGE(pDataFlash) >= 16384) //地址是5个周期,5*8=40位
{
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 //地址是4个周期,4*8=32位
{
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 */
write_spi(SPI_PTCR, AT91C_PDC_RXTDIS); /* PDC Disable Rx*/
write_spi(SPI_RPR, (unsigned int)&(pDataFlash->command)); /*PDC Set Rx */
write_spi(SPI_RCR,bCmdSize);
write_spi(SPI_RNPR, (unsigned int) pData); /* PDC Set Next Rx */
write_spi(SPI_RNCR,dDataSize);
write_spi(SPI_PTCR, AT91C_PDC_TXTDIS); /* PDC Disable Tx */
write_spi(SPI_TPR, (unsigned int)&(pDataFlash->command)); /* PDC SetTx */
write_spi(SPI_TCR,bCmdSize);
write_spi(SPI_TNPR, (unsigned int) pData); /* PDC Set Next Tx */
write_spi(SPI_TNCR,dDataSize);
write_spi(SPI_PTCR, AT91C_PDC_RXTEN); /* PDC Enable Rx */
write_spi(SPI_PTCR, AT91C_PDC_TXTEN); /* PDC Enable Tx */
while (df_is_busy(pDataFlash)== LOCKED);
return1;
}
/*------------------------------------------------------------------------------*/
/* \fn df_is_busy */
/* \brief Test if SPI has received a buffer ornot */
/*------------------------------------------------------------------------------*/
static AT91S_DF_SEM df_is_busy(
AT91PS_DFpDataFlash)
{
unsignedint dStatus = read_spi(SPI_SR);//Read SPI registers
/* IfEnd of Receive Transfer interrupt occurred */
if (( dStatus & AT91C_SPI_RXBUFF))// (SPI) RXBUFF Interrupt判断是否有中断发送
{//有产生中断
write_spi(SPI_PTCR,AT91C_PDC_TXTDIS); /* PDC Disable Tx */
write_spi(SPI_PTCR,AT91C_PDC_RXTDIS); /* PDC Disable Rx */
/* Release the semaphore */
pDataFlash->bSemaphore= UNLOCKED;
returnUNLOCKED;
}
return pDataFlash->bSemaphore;
}
4 waitfor DataFlash to be ready
/*------------------------------------------------------------------------------*/
/* \fn df_wait_ready */
/* \brief wait forDataFlash to be ready */
/*------------------------------------------------------------------------------*/
static chardf_wait_ready(AT91PS_DF pDataFlash)
{
unsigned int timeout = 0;
while (timeout++ < AT91C_DF_TIMEOUT)//检查是否超时时间到
{
if (df_get_status(pDataFlash))
{
if (df_is_ready(pDataFlash))// (pDf)->command[0] & 0x8000则说明准备就绪
return 1;
}
}
return 0;
}
#define DB_STATUS 0xD7 /* StatusRegister */
#definedf_get_status(pDf) df_send_command(pDf, DB_STATUS, 2, (char *) 0,0, 0)
#definedf_is_ready(pDf) ((pDf)->command[0] & 0x8000)
5 load the content of thedataflash
load_df(0x0D,0X8400, 0X33900,0x23F00000)
load_df(pcs, img_addr,img_size, img_dest)
df_download(pDf,img_addr, img_size, img_dest);
df_download(pDf, 0X8400,0X33900, 0x23F00000)
/*----------------------------------------------------------------------*/
/* \fn df_download */
/* \brief load thecontent of the dataflash */
/*----------------------------------------------------------------------*/
static intdf_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);//等待df准备就绪
return 0;
}
/*------------------------------------------------------------------------------*/
/* \fn df_read */
/* \brief Read a blockin dataflash */
/*------------------------------------------------------------------------------*/
df_read(pDf,0X8400, ,0x23F000000X33900)
static int df_read(
AT91PS_DF pDf,
unsigned int addr, 0X8400
unsigned char *buffer, 0x23F00000
unsigned int size) 0X33900
{
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准备就绪
df_continuous_read(pDf,(char *)buffer, SizeToRead, addr); //Continuous array read
size -= SizeToRead;
addr += SizeToRead;
buffer += SizeToRead;
}
return0;
}