AT91Bootstrap1.16第二阶段C程序详解之二

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;

}

你可能感兴趣的:(AT91Bootstrap1.16第二阶段C程序详解之二)