Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31550
  • 博文数量: 15
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 80
  • 用 户 组: 普通用户
  • 注册时间: 2017-07-03 09:21
文章分类

全部博文(15)

文章存档

2017年(15)

我的朋友
最近访客

分类: 嵌入式

2017-07-16 22:48:41

自己写一个bootloader基本步骤如下:
1.上电关看门狗避免复位

点击(此处)折叠或打开

  1. .text
  2. .global _start
  3. _start:
  4. /* 1.关看门狗 */
  5.     ldr r0, =0x53000000 //WDTCON
  6.     mov r1, #0
  7.     str r1, [r0]
2.设置时钟,单板上电复位后几毫秒即可设置时钟

点击(此处)折叠或打开

  1. /* 2.设置时钟 到时候可以改变一下时钟试一试, pclk:hclk:fclk=1:2:4*/
  2.     ldr r0, =0x4c000014
  3.     mov r1, #3
  4.     str r1, [r0]
  5. /* 3.因为HDIVN不是0,所以要改变cpu模式从fast bus to asynchronous */
  6.     mrc p15, 0, r1, c1, c0, 0
  7.     orr r1, r1, #0xc0000000
  8.     mcr p15, 0, r1, c1, c0, 0
  9. /* 4.设置MPLLCON时钟,便可确定FCLK HCLK PCLK */
  10.     ldr r0, =0x4c000004
  11.     ldr r1, =MPLLCON_SET_200MHZ
  12.     str r1, [r0]


3.初始化sdram,之后我们需要把代码从flash中读取到sdram中去运行

点击(此处)折叠或打开

  1. /* 5.初始化sdram */
  2.     ldr r0, =MEM_CTL_BASE
  3.     adr r1, sdram_config
  4.     add r3, r0, #52
  5. 0:
  6.     ldr r2, [r1], #4
  7.     str r2, [r0], #4
  8.     cmp r0, r3
  9.     bne 0b
  10. sdram_config:
  11.     .long 0x22011110    //bwscon
  12.     .long 0x00000700    //bankcon0
  13.     .long 0x00000700    //bankcon1
  14.     .long 0x00000700    //bankcon2
  15.     .long 0x00000700    //bankcon3
  16.     .long 0x00000700    //bankcon4
  17.     .long 0x00000700    //bankcon5
  18.     .long 0x00018005    //bankcon6
  19.     .long 0x00018005    //bankcon7
  20.     .long 0x008c04f4    //refresh
  21.     .long 0x000000b1    //banksize
  22.     .long 0x00000030    //mrsrb6
  23.     .long 0x00000030    //mrsrb7
4.设置好堆栈,之后都是运行C了,将堆栈指针sp指向一块不用的内存即可
ldr sp, =0x34000000

5.初始化串口,可以打印一些有用的信息

点击(此处)折叠或打开

  1. void uart_init(void)
  2. {
  3.      GPHCON |= 0xa0; // GPH2,GPH3用作TXD0,RXD0
  4.      GPHUP = 0x0c; // GPH2,GPH3内部上拉
  5.     
  6.     ULCON0 = 3;//115200 1 stopbit 8bit no parity
  7.     UCON0 = 5;//查询方式 clock pclk
  8.     UFCON0 = 0;//不用fifo
  9.     UMCON0 = 0;//不用流控
  10.     UBRDIV0 = UART_BRD;
  11. }

6.初始化nandflash

点击(此处)折叠或打开

  1. void nand_init(void)
  2. {
  3. #define TACLS    0
  4. #define TWRPH0    1
  5. #define TWRPH1    0

  6.     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
  7.     /* 初始化ECC 禁止片选 */
  8.     NFCONT = (1<<4)|(1<<1)|(1<<0);
  9. }
  10. void nand_read(unsigned char* dest, unsigned long addr, unsigned long len)
  11. {
  12.     unsigned long i = 0;
  13.     unsigned short col = addr%2048;
  14.     
  15.     nand_select();
  16.     
  17.     while (i < len)
  18.     {
  19.         nand_cmd(0x00);
  20.         nand_addr(addr);
  21.         nand_cmd(0x30);
  22.         wait_for_ready();
  23.         while (col < 2048)
  24.         {
  25.             dest[i++] = nand_data();
  26.             col++;
  27.             addr++;
  28.         }
  29.         col = 0;
  30.     }
  31.     
  32.     nand_diselect();
  33. }

7.拷贝代码从flash到sdram去运行

点击(此处)折叠或打开

  1. mov r0, #0
  2.     ldr r1, =_start
  3.     ldr r2, =__bss_start
  4.     sub r2, r2, r1
  5.         
  6.     bl copy_code_2_sram
8.清bss段

点击(此处)折叠或打开

  1. void clear_bss(void)
  2. {
  3.     extern int __bss_start, __bss_end;
  4.     int *p = &__bss_start;

  5.     for (; p < &__bss_end; p++)
  6.     {
  7.         *p = 0;
  8.     }
  9. }

9.main中代码负责:
1.将内核从flash读入sdram固定位置(0x30008000)
2.设置启动参数,memory commandline,启动参数存放位置(0x30000100)
3.跳转到内核特定位置去执行

点击(此处)折叠或打开

  1. puts("in main func\r\n");
  2.     void (*thekernel)(int zero, int arch, unsigned long params);
  3. /* 将内核从flash中读入sdram */
  4.     puts("copy kernel to sdram\r\n");
  5.     nand_read((unsigned char *)0x30008000 ,0x60000 + 64, 0x200000);
  6. /* 设置启动参数 */
  7.     setup_start_tag();
  8.     setup_memory_tag();
  9.     setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
  10.     setup_end_tag();
  11. /* 跳转去执行 */
  12.     puts("boots kernel\r\n");
  13.     thekernel = (void(*)(int, int, unsigned long))0x30008000;
  14.     thekernel(0, 362, 0x30000100)

 编写的过程中主要被以下几个地方给难住了
1:copy code to sdram 起始地址目的地址给搞混了,起始地址应该是flash中的0地址,
拷贝的目的地址应该是_start 长度为 _bss_start-_start
2: clear bss还没有完全搞明白
3:几个地址搞明白,目的地址_start 0x30008000是代码应该允许的位置,0x60000是flash中内核所在的位置(带头部),
0x30000100是启动参数存放 地址,所以应该把内核搬运到0x30008000-64的位置去。
阅读(1638) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~