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 $
//------------------------------------------------------------------------------
//
//! @}
//
//! @}