原创 AT91SAM9261 firstboot 分析 main.c

2010-3-29 21:03 2607 3 3 分类: MCU/ 嵌入式

firstboot的startup.s 函数执行之后就会跳到main.c函数继续执行。main.c函数的功能是继续初始化硬件,如调试串口和SDRAM。调试串口用于输出调试信息,初始化SDRAM主要是为载入EBOOT做准备。main.c文件中引用了很多头文件,我把这些头文件的所在目录注释以便查找,如果按照默认路径安装WINCE600和BSP的话,这些头文件后面的注释都是可用的。


--------------------------------------------------------------------------------------------


//-----------------------------------------------------------------------------
//! \addtogroup BOOTLOADER
//! @{
//!
//  All rights reserved ADENEO SAS 2005
//-----------------------------------------------------------------------------
//! \file  AT91SAM9261EK/SRC/BOOTLOADER/FirstBoot/main.c
//!
//! \brief  The boot following ROM boot, permitting to copy eboot
//!    from a flash support to the SDRAM
//!
//! \if subversion
///   @URL: $URL: http://centaure/svn/interne-ce_bsp_atmel/TAGS/TAGS60/SAM9261EK_v103_rc3/PLATFORM/AT91SAM9261EK/SRC/BOOTLOADER/FirstBoot/main.c $
//!   @author $Author: jjhiblot $
//!   @version $Revision: 860 $
//!   @date $Date: 2007-05-22 10:33:20 +0200 (mar., 22 mai 2007) $
//! \endif
//-----------------------------------------------------------------------------
//! \addtogroup FIRSTBOOT
//! @{
//!


//------------------------------------------------------------------------------
//                                                                      Includes
//------------------------------------------------------------------------------
// Standard includes
#include <windows.h>


// Atmel includes
#include "at91sam9261.h" // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\AT91SAM9261\INC
#include "AT91SAM9261EK.h" // C:\WINCE600\PLATFORM\AT91SAM9261EK\SRC\INC
#include "at91_pio.h"  // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\COMMON\INC\CONTROLLER
#include "at91_usart.h"  // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\COMMON\INC\CONTROLLER
#include "at91_dbgu.h"  // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\COMMON\INC\CONTROLLER
#include "at91_pdc.h"  // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\COMMON\INC\CONTROLLER
#include "at91_pmc.h"  // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\COMMON\INC\CONTROLLER
#include "at91_pitc.h"  // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\COMMON\INC\CONTROLLER


// Configuration includes
#include "firstboot_cfg.h" // Firstboot configuration (here for boot type choice)
       // C:\WINCE600\PLATFORM\AT91SAM9261EK\SRC\BOOTLOADER\FirstBoot
#include "bootloader_cfg.h" // General bootloader settings
       // C:\WINCE600\PLATFORM\AT91SAM9261EK\SRC\INC
#include "bootloader_struct.h"  // General bootloader settings
        // C:\WINCE600\PLATFORM\COMMON\SRC\SOC\ATMEL\COMMON\INC
// Local includes
#include "sdram.h"    // Sdram include
#include "dbgu.h"    // Seriel debug include


// Select correct flash support api, according to definition in firstboot_cfg.h
#include "SPIDataFlash.h"


//------------------------------------------------------------------------------
//                                                            Imported functions
//------------------------------------------------------------------------------
extern void Jump(UINT32 addr); // Function import from startup.s file


//-----------------------------------------------------------------------------
//! \fn   unsigned long ComputeCRC32(unsigned char *buffer, int len)
//!
//! \brief  This function compute a crc 32 from a pointer for a certain length
//!
//! \param buffer Pointer on memory you want compute a crc
//!
//! \param  len Length of zone which you want compute a crc
//!
//! \return  The CRC32 value
//-----------------------------------------------------------------------------
unsigned long ComputeCRC32(unsigned char *buffer, int len)
{
  unsigned long crc; 
  unsigned long temp;
  int j;
 
  crc = 0xFFFFFFFF;
 
  while (len--)
  {
    temp = (unsigned long)((crc & 0xFF) ^ *buffer++);
    for (j = 0; j < 8; j++)
    {
      if (temp & 0x1)
        temp = (temp >> 1) ^ 0xEDB88320;
      else
        temp >>= 1;
    }
    crc = (crc >> 8) ^ temp;
  }
  return crc ^ 0xFFFFFFFF;
}



//-----------------------------------------------------------------------------
//! \fn   void FRISTBOOT_LowLevelInit(void)
//! \brief  This function performs very low level HW initialization
//! \这个函数执行非常低级的硬件初始化
//-----------------------------------------------------------------------------
void FRISTBOOT_LowLevelInit(void)
{
 DWORD dwMasterClock; 
 AT91PS_DBGU pDBGU = (AT91PS_DBGU) AT91C_BASE_DBGU;
 AT91PS_PDC pPDC = (AT91PS_PDC) &(pDBGU->DBGU_RPR);
 AT91PS_PIO pPioA = (AT91PS_PIO) AT91C_BASE_PIOA;


 dwMasterClock = AT91C_MASTER_CLOCK;  // 定义在firstboot_cfg.h


 // Init the DBGU
 // Configure PIO controllers to periph mode 
 pPioA->PIO_PDR = (AT91C_PA10_DTXD | AT91C_PA9_DRXD);
 pPioA->PIO_ASR = (AT91C_PA10_DTXD | AT91C_PA9_DRXD);


 // Configure USART
 // Disable interrupts
 pDBGU->DBGU_IDR = (unsigned int) -1;   //ffffffff禁能所有DBGU中断


 // Reset receiver and transmitter 复位和禁能接收器与发送器
 pDBGU->DBGU_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS ;


 // Define the baud rate divisor register DBGU_BAUDRATE = 115200
 
 unsigned int baud_value = ((dwMasterClock*10)/(DBGU_BAUDRATE * 16));
 if ((baud_value % 10) >= 5)
  baud_value = (baud_value / 10) + 1;
 else
  baud_value /= 10;
 pDBGU->DBGU_BRGR = baud_value;


 // Write the Timeguard Register
 //pDBGU->US_TTGR = 0;   //这个语句没有用


 // Clear Transmit and Receive Counters


 // Disable the RX and TX PDC transfer requests 禁止接收和发送PDC传输请求
 pPDC->PDC_PTCR = AT91C_PDC_RXTDIS;
 pPDC->PDC_PTCR = AT91C_PDC_TXTDIS;


 // Reset all Counter register Next buffer first
 pPDC->PDC_TNPR = 0;
 pPDC->PDC_TNCR = 0;
 pPDC->PDC_RPR = 0;
 pPDC->PDC_RCR = 0;
 pPDC->PDC_RPR = 0;
 pPDC->PDC_RCR = 0;
 pPDC->PDC_TPR = 0;
 pPDC->PDC_TCR = 0;


 // Enable the RX and TX PDC transfer requests
 pPDC->PDC_PTCR = AT91C_PDC_RXTEN;
 pPDC->PDC_PTCR = AT91C_PDC_TXTEN;


 // Define the USART mode
 pDBGU->DBGU_MR = AT91C_US_ASYNC_MODE;  // 定义在firstboot_cfg.h


 // Enable Transmitter
 pDBGU->DBGU_CR = AT91C_US_RXEN;
 pDBGU->DBGU_CR = AT91C_US_TXEN;


 DbgPrint("\r\nINFO : Low Level Init : OK\r\n");  //在dbgu.c中定义


 // Init SDRAM 初始化SDRAM
 AT91F_InitSdram();     //在sdram.c中定义
}


//-----------------------------------------------------------------------------
//! \fn   void FRISTBOOT_StartBoot(void)
//!
//! \brief  This function load sthe second level bootloader (Eboot) to SDRAM
//-----------------------------------------------------------------------------
void FRISTBOOT_StartBoot(void)
{
 UINT32 SizeToDownload = 0;
 UINT32 i = 0;


//-------------------------------------------------------------------
 volatile T_BOOTLOADER_FLASH_CONFIG *pBootFlashConfig = (T_BOOTLOADER_FLASH_CONFIG*)(BOOTLOADER_FLASH_CONFIG_ADDR);


 // 在内部SRAM中定义T_BOOTLOADER_FLASH_CONFIG的结构体指针
 // T_BOOTLOADER_FLASH_CONFIG在bootloader_struct.h中定义
 // typedef struct
 // {
 //   DWORD dwSize;
 //   DWORD dwEbootCodeFlashAddr;
 //   DWORD dwEbootSettingsFlashAddr;
 //  DWORD dwCrc32;
 // } T_BOOTLOADER_FLASH_CONFIG; 
 
 // BOOTLOADER_FLASH_CONFIG_ADDR在bootloader_cfg.h中定义
 // #define BOOTLOADER_FLASH_CONFIG_ADDR (AT91C_IRAM + 0x0)
 // This address where is wrote the bootloader type (communication between Firstboot and eboot)
 // 这个地址被写入bootloader的类型(用于Firstboot 和 eboot之间通讯,传递数据)
 // AT91C_IRAM是9261芯片内部SRAM的基地址,9261芯片内SRAM的容量为160 Kbyte
 // AT91C_IRAM在at91sam9261.h中定义
 // #define AT91C_IRAM   ((char *)  0x00300000) // Maximum Internal SRAM base address
//-------------------------------------------------------------------
 // Set flash configuration 这些信息会共享给EBOOT(暂时还不明白地址的含义)
 pBootFlashConfig->dwEbootCodeFlashAddr = EBOOT_FLASH_CODE_ADDR;  //0xC0005000
 pBootFlashConfig->dwEbootSettingsFlashAddr = EBOOT_FLASH_SETTINGS_ADDR; //0xC0025000
 pBootFlashConfig->dwSize = sizeof(T_BOOTLOADER_FLASH_CONFIG);   //结构体自身的尺寸
 pBootFlashConfig->dwCrc32 = ComputeCRC32((UCHAR*)pBootFlashConfig, sizeof(T_BOOTLOADER_FLASH_CONFIG)-sizeof(DWORD));


 // EBOOT_FLASH_CODE_ADDR在firstboot_cfg.h中定义
 // #define EBOOT_FLASH_CODE_ADDR  DATAFLASH_CS0_LOGIC_BASE_ADDR | DATAFLASH_BOOTLOADER_CODE_LOGICAL_OFFSET
 // 而上面定义中的DATAFLASH_CS0_LOGIC_BASE_ADDR
 // 和DATAFLASH_BOOTLOADER_CODE_LOGICAL_OFFSET又在bootloader_cfg.h中定义


//-------------------------------------------------------------------
 //Power up PIOA for checking the level of PIOA 31
 //JJH : need to enable PIOC's clock to power up PIOA ???? it seems so
 //使能ID号为PID2的外设时钟,AT91C_ID_PIOC的值为4,正好对应PID2这一位,只是借用了这个数值
 AT91C_BASE_PMC->PMC_PCER =  AT91C_ID_PIOC;  
 // and configure it...
 AT91C_BASE_PIOA->PIO_PPUER = (1<<31);
 AT91C_BASE_PIOA->PIO_ODR = (1<<31);
 AT91C_BASE_PIOA->PIO_PER = (1<<31);
//------------------------------------------------------------------- 
 //从DATAFLASH中拷贝EBOOT代码到SDRAM中
 if (read_dataflash(EBOOT_FLASH_CODE_ADDR, EBOOT_MAX_SIZE, EBOOT_SDRAM_ADDR) <= 0)
 {
  //DbgPrint("ERROR : Reading Eboot from DATAFLASH");
  while(1);
 }
 
 //判断EBOOT代码镜像是否存在
 if(*(EBOOT_SDRAM_ADDR) == 0xFFFFFFFF)
 {
  DbgPrint("ERROR : Eboot Image is not valid");
  while(1); 
 }


}


 


void main(void)
{
 AT91PS_PITC  pPITC   = AT91C_BASE_PITC;  //Periodic Interval Timer


 // Init low level 这个函数执行非常低级的硬件初始化
  FRISTBOOT_LowLevelInit();


 // Enable PIT for tempo
 pPITC->PITC_PIMR=0x010FFFFF;


 //DbgPrint("Starting firstboot ...\r\n");  //调试串口输出信息


#if (FIRSTBOOT_SUPPORT_TYPE == DATAFLASH_CS0_BOOT || FIRSTBOOT_SUPPORT_TYPE == DATAFLASH_CS1_BOOT)
 //Init Data flash
 AT91F_DataflashInit();
 DbgPrint("Dataflash init OK\r\n");    //调试串口输出信息
#endif
 
 //填充FIRSTBOOT与EBOOT之间的数据交换区,由T_BOOTLOADER_FLASH_CONFIG指向SRAM
 //Load EBoot 把EBOOT的执行代码从DATAFLASH中导入到SDRAM中
 FRISTBOOT_StartBoot();


 DbgPrint("Starting eboot ...\r\n");  //调试串口输出信息


 //Jump at start of EBoot 跳转到EBOOT代码去执行
 //在bootloader_cfg.h中EBOOT_SDRAM_ADDR是这样定义的
 //#define  EBOOT_SDRAM_ADDR  AT91C_EBI_SDRAM
 //而AT91C_EBI_SDRAM的定义在at91sam9261.h文件中
 //#define AT91C_EBI_SDRAM  ((char *)  0x20000000)
 // 0x20000000 是SDRAM的基地址(SDRAM on EBI Chip Select 1 base address)
 Jump((UINT32)EBOOT_SDRAM_ADDR);


 //ComputeCRC32(BOOTLOADER_TYPE_ADDR


 while(1);
}


//------------------------------------------------------------------------------
//! End of $URL: http://centaure/svn/interne-ce_bsp_atmel/TAGS/TAGS60/SAM9261EK_v103_rc3/PLATFORM/AT91SAM9261EK/SRC/BOOTLOADER/FirstBoot/main.c $
//------------------------------------------------------------------------------


//
//! @}
//


//! @}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
3
关闭 站长推荐上一条 /3 下一条