加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-17 21:18:22 所属栏目:安全 来源:网络整理
导读:Main函数的主要流程: 硬件初始化——》从Dataflash中加载uboot——》返回指定的地址JUMP_ADDR ?本文主要分析:?硬件初始化hw_init() #include "include/part.h" #include "include/main.h" #include "include/debug.h" #include "include/dataflash.h" #inc

Main函数的主要流程:

硬件初始化——》从Dataflash中加载uboot——》返回指定的地址JUMP_ADDR

?本文主要分析:?硬件初始化hw_init()

#include "include/part.h"

#include "include/main.h"

#include "include/debug.h"

#include "include/dataflash.h"

#include "include/nandflash.h"

#include "include/norflash.h"

/*------------------------------------------------------------------------------*/

/* Function Name?????? : main??????????????????????????????????????????? */

/* Object????????????? : Main function?????????????????????????????????????? */

/* Input Parameters??? : none??????????????????????????????????????????????? */

/* Output Parameters?? : True?????????????????????????????????????????????? */

/*------------------------------------------------------------------------------*/

int main(void)

{

/* ================== 1st step: HardwareInitialization ================= */

?????? /* Performs the hardware initialization*/

#ifdef CFG_HW_INIT

?????? hw_init();硬件初始化执行(WDT.PLLA.MCK.PLLB.CP15.PIO.EBI.MATRIX.SDRAM)

#endif

/* ==================== 2nd step: Load frommedia ==================== */

?????? /* Load from Dataflash in RAM */

#ifdef CFG_DATAFLASH? //Dataflash加载到SDRAM中

?????? load_df(AT91C_SPI_PCS_DATAFLASH,IMG_ADDRESS,IMG_SIZE,JUMP_ADDR);

#endif

?????? /*Load from Nandflash in RAM */

#ifdef CFG_NANDFLASH //不执行暂不分析,主要是从不同的flash中加载UBOOT到SDRAM

?????? load_nandflash(IMG_ADDRESS,JUMP_ADDR);

#endif

?????? /*Load from Norflash in RAM */

#ifdef CFG_NORFLASH//不执行暂不分析,主要是从不同的flash中加载UBOOT到SDRAM

?????? load_norflash(IMG_ADDRESS,JUMP_ADDR);

#endif

/* ==================== 3rd step:? Process the Image =================== */

?????? /* Uncompress the image */

#ifdef GUNZIP //解压缩映像文件,不需要,不执行

?????? decompress_image((void*)IMG_ADDRESS,(void *)JUMP_ADDR,IMG_SIZE); /*NOT IMPLEMENTED YET */

#endif /* GUNZIP */

/* ==================== 4th step: Start theapplication =================== */

?????? /* Set linux arguments *///不执行

#ifdef LINUX_ARG//设置启动参数,不需要,因为bootstrap只加载uboot到SDRAM中

?????? linux_arg(LINUX_ARG);???? /* NOT IMPLEMENTED YET */

#endif /* LINUX_ARG */

?????? /*Jump to the Image Address */

?????? returnJUMP_ADDR;//0x23F00000???? /* Final Jump Address */可以自行修改

}

通过对main函数的分析可知启示,在主函数中只有两函数要执行,特定的开发板,那就是:

hw_init()

硬件初始化执行

load_df(AT91C_SPI_PCS_DATAFLASH,JUMP_ADDR);

Dataflash加载到SDRAM中

对于从不同的flash中加载主要体现在,硬件是否支持哪种启动方式。

Load from Dataflash inRAM

Load from Nandflash inRAM

Load from Norflash inRAM ????需要有针对性的添加修改,来适应自己的开发板

?

本次移植使用的是AT的官方demo板子画的,所有只移植从Dataflash加载uboot即可。

?

以下具体分析这两函数的具体实现:

一硬件初始化void hw_init(void)

/*----------------------------------------------------------------------------*/

/* fn??? hw_init???????????????????????????????????????????? ????? */

/* brief This functionperforms very low level HW initialization????? ????? */

/* This function isinvoked as soon as possible during the c_startup??? ????? */

/* The bss segment mustbe initialized????????????????????????????? ????? */

/*----------------------------------------------------------------------------*/

void hw_init(void)

{

?????? unsigned int cp15;

?????? /* Configure PIOs */

?????? const struct pio_desc hw_pio[] = {

#ifdef CFG_DEBUG

????????????? {"RXD",AT91C_PIN_PB(14),PIO_DEFAULT,PIO_PERIPH_A},

????????????? {"TXD",AT91C_PIN_PB(15),

#endif

????????????? {(char *) 0,

?????? };//此结构体初始化为空,调试阶段有使用价值

?????? /* Disable watchdog */

?????? writel(AT91C_WDTC_WDDIS,AT91C_BASE_WDTC + WDTC_WDMR);

//关闭看门狗(0xFFFFFD40+4)=(0x1 << 15)

?????? /* At this stage the main oscillator is supposed to be enabled

?????? ?* PCK = MCK = MOSC *///在这个阶段,主振荡器启用PCK = MCK = MOSC

?????? /* Configure PLLA = MOSC * (PLL_MULA + 1) / PLL_DIVA */

?????? pmc_cfg_plla(PLLA_SETTINGS,PLL_LOCK_TIMEOUT);//0x2060BF09

?? ? ? ?/* PCK = PLLA = 2 * MCK */

?????? pmc_cfg_mck(MCKR_SETTINGS,PLL_LOCK_TIMEOUT);

?????? /* Switch MCK onPLLA output */

?????? pmc_cfg_mck(MCKR_CSS_SETTINGS,PLL_LOCK_TIMEOUT);

? ? ? ?/* Configure PLLB */

?????? pmc_cfg_pllb(PLLB_SETTINGS,PLL_LOCK_TIMEOUT);

? ? ? ?/* Configure CP15 */

?????? cp15 = get_cp15();//将协处理器P15的寄存器中数据传送到ARM处理器寄存器r0中。

?????? cp15 |= I_CACHE;//set bit 12 (I) I-Cache

?????? set_cp15(cp15);//设置CP15中的寄存器值,禁止指令Cache?

?????? /* Configure the PIO controller */

?????? pio_setup(hw_pio);//此函数直接跳出,因为hw_pio结构体的第一个元素是0,调试有用?

?????? /* Configure the EBI Slave Slot Cycle to 64 *///简单就是给某个寄存器写入一个值

writel( (readl((AT91C_BASE_MATRIX + MATRIX_SCFG3)) & ~0xFF)| 0x40,(AT91C_BASE_MATRIX+ MATRIX_SCFG3));

//先读出(MATRIX)Base Address+Slave Configuration Register 3 (ebi)寄存器的值,同时将低

//8位清零,再和0x40相与,即置位第7位 01000000? ,

// writel(X1XXXXXXX,刚刚读出的那个寄存器0xFFFFEE00+0X4C));

//将0XFFFFEE4C寄存器的第7位置1,具体什么功能,查数据手册????????????


#ifdef CFG_DEBUG ?//调试阶段使用,暂不分析

?????? /* Enable Debugmessages on the DBGU */

?????? dbg_init(BAUDRATE(MASTER_CLOCK,115200));

?????? dbg_print("Start AT91Bootstrap...nr");

#endif /* CFG_DEBUG */

#ifdef CFG_SDRAM

?????? /* Initializethe matrix *///简单就是给某个寄存器写入一个值

?????? writel(readl(AT91C_BASE_CCFG+ CCFG_EBICSA) | AT91C_EBI_CS1A_SDRAMC,AT91C_BASE_CCFG + CCFG_EBICSA);

//先读出(CCFG)Base Address+ EBI Chip Select Assignement Register寄存器的值

//再和(0x1<< 1) // (CCFG) Chip Select 1 is assigned to the SDRAM Controller.相或,即置位第//2位 0000 0010? ,

// writel(XXXXXXX1X,刚刚读出的那个寄存器0xFFFFEF10+0X0C));

//将0XFFFFEF1C寄存器的第2位置1,具体什么功能,查数据手册????????????

?????? /* Configure SDRAM Controller */

?????? sdram_init(???? AT91C_SDRAMC_NC_9? |

??????????????????????????? AT91C_SDRAMC_NR_13 |

??????????????????????????? AT91C_SDRAMC_CAS_2 |

??????????????????????????? AT91C_SDRAMC_NB_4_BANKS |

??????????????????????????? AT91C_SDRAMC_DBW_32_BITS |

??????????????????????????? AT91C_SDRAMC_TWR_2 |

??????????????????????????? AT91C_SDRAMC_TRC_7 |

??????????????????????????? AT91C_SDRAMC_TRP_2 |

??????????????????????????? AT91C_SDRAMC_TRCD_2 |

??????????????????????????? AT91C_SDRAMC_TRAS_5 |

??????????????????????????? AT91C_SDRAMC_TXSR_8,??????? ??? /* Control Register*/

??????????????????????????? (MASTER_CLOCK *7)/1000000,?????? /* Refresh TimerRegister */

??????????????????????????? AT91C_SDRAMC_MD_SDRAM);?????? /* SDRAM (no low power) */

#endif /* CFG_SDRAM */

}

两个重要宏定义

#define writel(value,address)

?????? (*(volatile unsigned int *)(address)) = (value)?? //向寄存器写入某个值

#define readl(address)

?????? (*(volatile unsigned int *)(address))??????????? //从寄存器中读取

重点分析以下几个子函数:

前3个是关于PLL的配置,最后一个是SDRAM初始化子函数。

/* Write PMC register */

static inline voidwrite_pmc(unsigned int offset,const unsigned int value)

{

?????? writel(value,offset + AT91C_BASE_PMC);// (0xFFFFFC00) // (PMC) Base Address

}

/* Read PMC registers */

static inline unsignedint read_pmc(unsigned int offset)

{

?????? return readl(offset + AT91C_BASE_PMC);// (0xFFFFFC00) // (PMC) Base Address

}

1//*----------------------------------------------------------------------------

//* fn???pmc_cfg_plla

//* brief Configurethe pll frequency to the corresponding value.

//*----------------------------------------------------------------------------*/

intpmc_cfg_plla(unsigned int pmc_pllar,unsigned int timeout)

{

?????? write_pmc((unsigned int)PMC_PLLAR,pmc_pllar);

// pmc_pllar=0x2060BF09写入到偏移(40)PLL A Register的寄存器中

?????? while ( (timeout--) && !(read_pmc(PMC_SR) & AT91C_PMC_LOCKA) );//延时等待

//若延时未到,则只有在PMC Status Register的(PMC) PLL A Status=0x02状态位是0x2跳出

//即//延时等待PLLA 锁定频率

?????? return (timeout) ? 0 : (-1);

}

2//*----------------------------------------------------------------------------

//* fn??? pmc_cfg_mck

//* brief Configurethe main oscillator to the corresponding value.

//*----------------------------------------------------------------------------*/

intpmc_cfg_mck(unsigned int pmc_mckr,unsigned int timeout)

{

?????? write_pmc(PMC_MCKR,?pmc_mckr);

???????????????????? // pmc_mckr写入到偏移(48) Master ClockRegister的寄存器中

?????? while ( (timeout--) && !(read_pmc(PMC_SR) & AT91C_PMC_MCKRDY) );

?//延时等待 Master Clock状态准备就绪

?????? return (timeout) ? 0 : (-1);

}

3

intpmc_cfg_pllb(unsigned int pmc_pllbr,unsigned int timeout)

{

?????? write_pmc(PMC_PLLBR,pmc_pllbr);

// pmc_pllbr=0x10483F0E写入到偏移(44) // PLL B Register的寄存器中

?????? while ( (timeout--) && !(read_pmc(PMC_SR) & AT91C_PMC_LOCKB) );

//延时等待PLLB 锁定频率

?????? return (timeout) ? 0 : (-1);

}

4//*----------------------------------------------------------------------------

//* fn??? sdram_init

//* brief Initializethe SDRAM Controller

//*----------------------------------------------------------------------------

关于SDRAM初始化的重要子函数

/* Write SDRAMCregister */

static inline voidwrite_sdramc(unsigned int offset,offset + AT91C_BASE_SDRAMC);// 0xFFFFEA00(SDRAMC) Base Address

}

/* Read SDRAMCregisters */

static inline unsignedint read_sdramc(unsigned int offset)

{

?????? return readl(offset + AT91C_BASE_SDRAMC); // 0xFFFFEA00(SDRAMC) Base Address

}

int sdram_init(unsignedint sdramc_cr,unsigned int sdramc_tr,unsigned char low_power)

{

?????? volatile unsigned int i;

?????? /* Performs the hardware initialization */

?????? sdramc_hw_init();//初始化IO,主要是写两寄存器

?????? /* CFG Control Register */

?????? write_sdramc(SDRAMC_CR,sdramc_cr);//主要是设置SDRAM的一些配置参数

????????????? //将sdramc_cr的值写入到地址偏移SDRAMC_CR的寄存器中

?????? /* Set MDR Register */

??? write_sdramc(SDRAMC_MDR,(low_power &0x01)); //(low_power=0 )& 0x01=0

?????? for (i =0; i< 1000;i++);//延时一段时间,到底是多少时间需要好好弄清楚了呀??????

//修改模式寄存器的值,改变工作模式0x1

write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_NOP_CMD);? // Set NOP

// (SDRAMC) Issue a NOP Command at every accesswrite_sdramc(SDRAMC_MR,1 );

writel(0x00000000,AT91C_SDRAM);//Perform NOP? AT91C_SDRAM=0x20000000

//修改模式寄存器的值,改变工作模式0x2

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_PRCGALL_CMD);

// Set PRCHG AL

?????? writel(0x00000000,AT91C_SDRAM); // Perform PRCHG? AT91C_SDRAM=0x20000000

?????? for (i =0; i< 10000;i++);//延时多少时间??????

//修改模式寄存器的值,改变工作模式0x4。以下代码实现每次设置工作模式为0x4,然后

//在地址0x20000004 写 0x0000 0001

//在地址0x20000008 写 0x0000 0002? 依次写直到

//在地址0x20000020 写 0x0000 0008?

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 1st CBR

?????? writel(0x00000001,AT91C_SDRAM+4);?????????????????? // Perform CBR

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 2 CBR

?????? writel(0x00000002,AT91C_SDRAM+8);?????????????????? // Perform CBR

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 3 CBR

?????? writel(0x00000003,AT91C_SDRAM+0xc);?????????????? // Perform CBR

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 4 CBR

?????? writel(0x00000004,AT91C_SDRAM+0x10);??????????????????? // Perform CBR

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 5 CBR

?????? writel(0x00000005,AT91C_SDRAM+0x14);??????????????????? // Perform CBR

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 6 CBR

?????? writel(0x00000006,AT91C_SDRAM+0x18);??????????????????? // Perform CBR

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 7 CBR

?????? writel(0x00000007,AT91C_SDRAM+0x1C);??????????????????? //Perform CBR

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_RFSH_CMD); // Set 8 CBR

?????? writel(0x00000008,AT91C_SDRAM+0x20);??????????????????? //Perform CBR

//修改模式寄存器的值,改变工作模式0x3,

//在地址0x20000024 写 0xcafe dede

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_LMR_CMD);??

//SetLMR operation

?????? writel(0xcafedede,AT91C_SDRAM+0x24);?????????????? //Perform LMR burst=1,lat=2

//修改刷新时间寄存器的值(MASTER_CLOCK * 7)/1000000,寄存器要填写的值怎么计算?

//MASTER_CLOCK???????????? (198656000/2)???? 具体这个值是怎么来的

?????? write_sdramc(SDRAMC_TR,sdramc_tr);????????????????? // Set Refresh Timer

?//修改模式寄存器的值,改变工作模式0x0,

?????? write_sdramc(SDRAMC_MR,AT91C_SDRAMC_MODE_NORMAL_CMD);?

// Set Normalmode

?????? writel(0x00000000,AT91C_SDRAM);?????????????? // Perform Normal mode

?????? return 0;

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读