您的位置 首页 编程

ARM移植之BootLoader(4)

4.BootLoader第二阶段viviBootloader的第二阶段又分成了八个小阶段,在main函数中分别调用这几个小阶段的相关函数:intmain(int…

4. BootLoader第二阶段

  vivi Bootloader的第二阶段又分成了八个小阶段,在main函数中别离调用这几个小阶段的相关函数:

int main(int argc, char *argv[])
{
int ret;

/*
* Step 1:
*/
putstr(“\r\n”);
putstr(vivi_banner);

reset_handler();

/*
* Step 2:
*/
ret = board_init();
if (ret) {
putstr(“Failed a board_init() procedure\r\n”);
error();
}

/*
* Step 3:
*/
mem_map_init();
mmu_init();
putstr(“Succeed memory mapping.\r\n”);

/*
* Now, vivi is running on the ram. MMU is enabled.
*/

/*
* Step 4:
*/
/* initialize the heap area*/
ret = heap_init();
if (ret) {
putstr(“Failed initailizing heap region\r\n”);
error();
}

/* Step 5:
*/
ret = mtd_dev_init();

/* Step 6:
*/
init_priv_data();

/* Step 7:
*/
misc();

init_builtin_cmds();

/* Step 8:
*/
boot_or_vivi();

return 0;
}

  STEP1的putstr(vivi_banner)句子在串口输出一段字符阐明vivi的版别、作者等信息,vivi_banner界说为:

const char *vivi_banner =
“VIVI version ” VIVI_RELEASE ” (” VIVI_COMPILE_BY “@”
VIVI_COMPILE_HOST “) (” VIVI_COMPILER “) ” UTS_VERSION “\r\n”;

  reset_handler进行相应的复位处理:

void
reset_handler(void)
{
 int pressed;

 pressed = is_pressed_pw_btn();

 if (pressed == PWBT_PRESS_LEVEL) {
  DPRINTK(“HARD RESET\r\n”);
  hard_reset_handle();
 } else {
  DPRINTK(“SOFT RESET\r\n”);
  soft_reset_handle();
 }
}

  hard_reset_handle会clear内存,而软件复位处理则什么都不做:

static void
hard_reset_handle(void)
{
 clear_mem((unsigned long)USER_RAM_BASE, (unsigned long)USER_RAM_SIZE);
}

  STEP2进行板初始化,设置时刻和可编程I/O口:

int board_init(void)
{
 init_time();
 set_gpios();

 return 0;
}

  STEP3进行内存映射及MMU初始化:

void mem_map_init(void)
{
 #ifdef CONFIG_S3C2410_NAND_BOOT
  mem_map_nand_boot();
 #else
  mem_map_nor();
 #endif
 cache_clean_invalidate();
 tlb_invalidate();
}

  S3C2410A的MMU初始化只需要调用通用的arm920 MMU初始化函数:

static inline void arm920_setup(void)
{
unsigned long ttb = MMU_TABLE_BASE;

__asm__(
/* Invalidate caches */
“mov r0, #0\n”
“mcr p15, 0, r0, c7, c7, 0\n” /* invalidate I,D caches on v4 */
“mcr p15, 0, r0, c7, c10, 4\n” /* drain write buffer on v4 */
“mcr p15, 0, r0, c8, c7, 0\n” /* invalidate I,D TLBs on v4 */
/* Load page table pointer */
“mov r4, %0\n”
“mcr p15, 0, r4, c2, c0, 0\n” /* load page table pointer */
/* Write domain id (cp15_r3) */
“mvn r0, #0\n” /* Domains 0, 1 = client */
“mcr p15, 0, r0, c3, c0, 0\n” /* load domain access register */
/* Set control register v4 */
“mrc p15, 0, r0, c1, c0, 0\n” /* get control register v4 */
/* Clear out unwanted bits (then put them in if we need them) */
/* .RVI ..RS B… .CAM */
“bic r0, r0, #0x3000\n” /* ..11 …. …. …. */
“bic r0, r0, #0x0300\n” /* …. ..11 …. …. */
“bic r0, r0, #0x0087\n” /* …. …. 1… .111 */
/* Turn on what we want */
/* Fault checking enabled */
“orr r0, r0, #0x0002\n” /* …. …. …. ..1. */
#ifdef CONFIG_CPU_D_CACHE_ON
“orr r0, r0, #0x0004\n” /* …. …. …. .1.. */
#endif
#ifdef CONFIG_CPU_I_CACHE_ON
“orr r0, r0, #0x1000\n” /* …1 …. …. …. */
#endif
/* MMU enabled */
“orr r0, r0, #0x0001\n” /* …. …. …. …1 */
“mcr p15, 0, r0, c1, c0, 0\n” /* write control register */
: /* no outputs */
: “r” (ttb) );
}

  STEP4设置仓库;STEP5进行mtd设备的初始化,记载MTD分区信息;STEP6设置私有数据;STEP7初始化内建指令。

  STEP8发动一个SHELL,等候用户输出指令并进行相应处理。在SHELL退出的情况下,发动操作系统:

#define DEFAULT_BOOT_DELAY 0x30000000
void boot_or_vivi(void)
{
char c;
int ret;
ulong boot_delay;

boot_delay = get_param_value(“boot_delay”, &ret);
if (ret) boot_delay = DEFAULT_BOOT_DELAY;
/* If a value of boot_delay is zero,
* unconditionally call vivi shell */
if (boot_delay == 0) vivi_shell();

/*
* wait for a keystroke (or a button press if you want.)
*/
printk(“Press Return to start the LINUX now, any other key for vivi\n”);
c = awaitkey(boot_delay, NULL);
if (((c != \r) && (c != \n) && (c != \0))) {
printk(“type \”help\” for help.\n”);
vivi_shell();
}
run_autoboot();

return;
}

  SHELL中读取用户从串口输出的指令字符串,履行该指令:

void
vivi_shell(void)
{
 #ifdef CONFIG_SERIAL_TERM
  serial_term();
 #else
  #error there is no terminal.
 #endif
}
void serial_term(void)
{
 char cmd_buf[MAX_CMDBUF_SIZE];

 for (;;) {
  printk(“%s> “, prompt);

  getcmd(cmd_buf, MAX_CMDBUF_SIZE);

  /* execute a user command */
  if (cmd_buf[0])
   exec_string(cmd_buf);
 }
}

  5.电路板调试

  在电路板的调试过程中,咱们首要要在ADT新建的工程中增加第一阶段的汇编代码head.S文件,修正Link脚本,将代码和数据映射到S3C2410A自带的0x40000000开端的4KB内存空间内:

SECTIONS
{
. = 0x40000000;
.text : { *(.text) }
Image_RO_Limit = .;
Image_RW_Base = .;
.data : { *(.data) }
.rodata : { *(.rodata) }
Image_ZI_Base = .;
.bss : { *(.bss) }
Image_ZI_Limit = .;
__bss_start__ = .;
__bss_end__ = .;
__EH_FRAME_BEGIN__ = .;
__EH_FRAME_END__ = .;
PROVIDE (__stack = .);
end = .;
_end = .;
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_abbrev 0 : { *(.debug_abbrev)}
.debug_frame 0 : { *(.debug_frame) }
}

   凭借万用表、示波器等仪器仪表,调通SDRAM,并将vivi中自带的串口、NAND FLASH驱动增加到工程中,调试经过板上的串口和FLASH。假如板电路的原理与三星公司DEMO板有距离,则vivi中硬件的操作要进行相应的修正。 悉数调试经往后,修正vivi源代码,从头编译vivi,将其烧录入NAND FLASH就可以在复位后发动这个Bootloader了。

  调试板上的新增硬件时,宜在ADT中增加相应的代码,在不加载操作系统的情况下,单纯地操作这些硬件。假如电路板规划有误,要进行飞线和割线等处理。

  6.小结

  本章讲解了ARM汇编、Bootloader的功用,Bootloader的调试环境及ARM电路板的调试办法。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/biancheng/275762.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部