嵌入式开发实验笔记(五)

移植新(2012.04.01) U-Boot 到S3C2440之中

date: 2018年1月23日

简述:相关知识点可以参考视频教程的附带文档,本文主要是写出每一步的操作过程;

修改时钟,配置新板

建立单板

  1. board/samsung/smdk2440
cd ./board/samsung
cp -rf smdk2410 smdk2440
cd smdk2440; mv smdk2410.c smdk2440.c; 
vim Makefile; 
- COBJS   := smdk2410.o
+ COBJS   := smdk2440.o
  1. include/config/smdk2440.h
cd ./include/config
cp smdk2410.h smdk2440.h
  1. boards.cfg
vim boards.cfg
+ smdk2440     arm  arm920t  -    samsung        s3c24x0                 
(参考smdk2410的书写规范即可)

修改源代码使得u-boot可以在s3c2440上启动

  1. 调整时钟

原因:UBOOT以60MHZ的时钟参数计算参数设置内存控制器,但是MPLL还未设置。所以第一步
将MPLL的设置转移至 start.S 中,注释掉 board_early_init_f 中的 MPLL 的设置

/* ./arch/arm/cpu/arm920t/start.S */
line: 170
-   /* FCLK:HCLK:PCLK = 1:2:4 */
-   /* default FCLK is 120 MHz ! */
-   ldr r0, =CLKDIVN
-   mov r1, #3
-   str r1, [r0]

+   /* FCLK:HCLK:PCLK = 1:4:8 */
+   /* default FCLK is 400 MHz ! */
+ /* 2. 设置时钟 */
+   ldr r0, =0x4c000014
+   // mov r1, #3               // FCLK:HCLK:PCLK= 1:2:4
+   mov r1, #5               // FCLK:HCLK:PCLK= 1:4:8
+   str r1, [r0]
+ 
+   /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
+   mrc p15, 0, r1, c1, c0, 0       /* 读出控制寄存器 */ 
+   orr r1, r1, #0xc0000000         /* 设置为“asynchronous bus mode” */
+   mcr p15, 0, r1, c1, c0, 0       /* 写入控制寄存器 */
+ 
+ #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
+ 
+   /* MPLLCON = S3C2440_MPLL_200MHZ */
+   ldr r0, =0x4c000004
+   ldr r1, =S3C2440_MPLL_400MHZ        /* 尽早进行时钟初始化,有利于提高效率 */
+   str r1, [r0]
+ 
+   /* 启动ICACHE */
+   mrc p15, 0, r0, c1, c0, 0   @ read control reg
+   orr r0, r0, #(1<<12)        @ r0 = r0 | (1<<12)
+   mcr p15, 0, r0, c1, c0, 0   @ write it back
/* board/samsung/smdk2440/smdk2440.c */
line76:
- /* to reduce PLL lock time, adjust the LOCKTIME register */
-  writel(0xFFFFFF, &clk_power->locktime);
- /* configure MPLL */
-  writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
-      &clk_power->mpllcon);
  1. 设置内存
/* board/samsung/smdk2440/lowlevel_init.S */
line 155:
- .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
- .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
- .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
- .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
- .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
- .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
- .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
- .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
- .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
- .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
- .word 0x32
- .word 0x30
- .word 0x30 
  
+ .long 0x22011110   //BWSCON
+ .long 0x00000700   //BANKCON0
+ .long 0x00000700   //BANKCON1
+ .long 0x00000700   //BANKCON2
+ .long 0x00000700   //BANKCON3  
+ .long 0x00000700   //BANKCON4
+ .long 0x00000700   //BANKCON5
+ .long 0x00018005   //BANKCON6
+ .long 0x00018005   //BANKCON7
+ .long 0x008C04F4   // REFRESH
+ .long 0x000000B1   //BANKSIZE
+ .long 0x00000030   //MRSRB6
+ .long 0x00000030   //MRSRB7
  1. 解决乱码问题 ( 串口波特率没有正确配置 )

原因:查看波特率设置(arch/arc/cpu/arm920t/s3c24x0/speed.c) 中配置get_HCLK里没有定义
CONFIG_S3C2440;解决方法:在 ./include/configs/smdk2440.h 中定义这个变量

/* ./include/configs/smdk2440.h */
line38:
- #define CONFIG_S3C2410
+ #define CONFIG_S3C2440
  1. 解决报错:s3c2410_nand.c 中报错
s3c2410_nand.c: In function 's3c2410_hwcontrol':
s3c2410_nand.c:57: warning: implicit declaration of function 's3c2410_get_base_nand'
s3c2410_nand.c:57: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type

原因:因为上步中注释掉了CONFIG_S3C2410 宏,而这个文件里需要的结构体是在这个宏定义的前提下使用,所以现在先将 nand 移除,不进行编译

/* ./include/configs/smdk2440.h */
line103:
- #define CONFIG_CMD_NAND

修改原有代码来支持 nand flash 启动

  1. 拷贝自己写的 init.c 到 u-boot 中来简化我们的操作

注意对 init.c 中的代码进行修改,修改有一下几个方面:

  1. 更改函数名,对于 nand_read , nand_init 之类存在外部调用的,将名字改的更具辨识度
  2. 对于nand_cmd, IsBootFromNor 之类的函数只存在文件内的调用,通过函数定义前添加
    static 来限制函数的生效空间。
  3. 删去代码中多余的部分;
cp /path/to/init.c/ ./board/samsung/smdk2440
vim Makefile
line 28:
- COBJS   := smdk2440.o
+ COBJS   := smdk2440.o init.o
  1. ./arch/arm/cpu/arm920t/start.S 中的修改
/* 1. ./arch/arm/cpu/arm920t/start.S */
line 182:
bl  cpu_init_crit
#endif

+   ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)  /* sp = 30000f80 */
+   bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
+   bl nand_init_s3c2440
+   mov r0, #0
+   ldr r1, _TEXT_BASE
+   ldr r2, _bss_start_ofs
+   bl copy_code_to_sdram
+   bl clear_bss
+   ldr pc, =call_board_init_f

 /* Set stackpointer in internal RAM to call board_init_f */
 call_board_init_f:
-   ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
-   bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
    ldr r0,=0x00000000
    bl  board_init_f
    
+   /* unsigned int 的值正好存在r0里,正好给board_init_r */
+   ldr r1,=_TEXT_BASE
+   /* 调用第2阶段的代码 */
+   bl  board_init_r 
 
/* 2. 删除line:192-281; 重定位和clear_bss我们已经完成了 */
 - /*--------------------------------------------------------------*/      
 - /*                                             
 -  * void relocate_code (addr_sp, gd, addr_moni)                          
 -  * This "function" does not return, instead it continues in RAM        
 -  * after relocating the monitor code.                                  
 -  */ 
......
- clbss_l:str r2, [r0]        /* clear loop... */
- add r0, r0, #4
- cmp r0, r1
- bne clbss_l
- bl coloured_LED_init
- bl red_led_on
- #endif 
  1. 修改 CONFIG_SYS_INIT_SP_ADDR 的值
/* ./include/configs/smdk2440.h */
line: 43
- #define CONFIG_SYS_INIT_SP_ADDR 0x0
+ #define CONFIG_SYS_INIT_SP_ADDR 0x33f00000
  1. 修改board_init_f
/* 1. ./arch/arm/lib/board.c */
line 438:
- relocate_code(addr_sp, id, addr);
+ return (unsigned int)id;
line 259
- void board_init_f(ulong bootflag)
+ unsigned int board_init_f(ulong bootflag)
line 372
-   addr -= gd->mon_len;
-   addr &= ~(4096 - 1);
+   addr = CONFIG_SYS_TEXT_BASE;
/* 2. ./include/common.h */
line : 276
- void    board_init_f  (ulong) __attribute__ ((noreturn));
- void    board_init_r  (gd_t *, ulong) __attribute__ ((noreturn));  

+ unsigned int board_init_f (ulong);
+ void board_init_r (gd_t *, unlong);


  1. 修改连接脚本,Makefile 去掉 '-pie'

"-pie" --- 生成位置无关码; 原来的代码中带有此选项导致最后生成的 u-boot.bin 过大,不适合在
nand 中启动;

/* 1. 修改Makefile ./arch/arm/config.mk */
line 75:
- LDFLAGS_u-boot += -pie

/* 2. 修改连接脚本,将start.S, init.c, lowlevel_init.S等文件放在最前面 
 * ./arch/arm/cpu/u-boot.lds
 */
 line 38
 +        board/samsung/smdk2440/libsmdk2440.o (.text)
  1. yaffs2部分报错
/* ./include/configs/smdk2440.h */
line: 228
- #define CONFIG_YAFFS2

目前为止所有修改过的文件:

  1. board/samsung/smdk2440/smdk2440.c
  2. arch/arm/cpu/arm920t/start.S
  3. board/samsung/smdk2440/lowlevel_init.S
  4. include/configs/smdk2440.h
  5. board/samsung/smdk2440/init.c
  6. arch/arm/lib/board.c
  7. include/common.h
  8. board/samsung/smdk2440/Makefile
  9. arch/arm/config.mk
  10. arch/arm/cpu/u-boot.lds

修改源码支持NorFlash

  1. 去掉 源码自带的Flash检测死循环
/* arch/arm/lib/board.c line 527: */
- puts(failed);
- hang();
+ puts("0KB\n\r");
  1. 在 cfi_flash.c 中打开调试开关以供分析
/* drivers/mtd/cfi_flash.c line 45 */
+ #define DEBUG 1
+ #define _DEBUG 1
// 最后记得把标志注释掉!!!!
  1. 添加我们自己的设备信息结构体
/* drivers/mtd/jedec_flash.c line 370 */
+ {
+   .mfr_id     = (u16)MX_MANUFACT,
+   .dev_id     = MX29LV160,
+   .name       = "MXIC MX29LV160",
+   .uaddr      = {
+       [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
+   },
+   .DevSize    = SIZE_2MiB,
+   .CmdSet     = P_ID_AMD_STD,
+   .NumEraseRegions= 4,
+   .regions    = {
+           ERASEINFO(16 * 1024, 1),
+           ERASEINFO(8 * 1024, 2),
+           ERASEINFO(32 * 1024, 1),    
+           ERASEINFO(64 * 1024, 31),
+   }
+ },

/* drivers/mtd/jedec_flash.c line 77 */
+ #define MX29LV160 0x2249
  1. 报错 too many flash sectors
/* include/configs/smdk2440.h line 190 */
- #define CONFIG_SYS_MAX_FLASH_SECT (19)
+ #define CONFIG_SYS_MAX_FLASH_SECT (128)
  1. 经过NORFlash 读写实验得出,u-boot 中的栈的设置不准确
/* arch/arm/cpu/arm920t/start.S line 113 */
/* 定义一个可以与C语言进行数据交换的变量
+ .globl base_sp
+ base_sp:
+   .long 0
/* arch/arm/cpu/arm920t/start.S line 232 */
+   ldr sp, base_sp                 /* 重新设置栈 */

/* arch/arm/lib/board.c line 265 */
+ extern ulong base_sp;               /* 声明变量 */
/* arch/arm/lib/board.c line 439 */
+ base_sp = addr_sp;

目前为止所有修改过的文件:

  1. arch/arm/lib/board.c
  2. drivers/mtd/cfi_flash.c
  3. drivers/mtd/jedec_flash.c
  4. include/configs/smdk2440.h
  5. arch/arm/cpu/arm920t/start.S
  6. arch/arm/lib/board.c

修改源码支持NANDFlash

  1. 加上刚开始为了编译而注释掉的NAND的宏
/* ./include/configs/smdk2440.h */
line103:
+ #define CONFIG_CMD_NAND
  1. 创建对应于 S3C2440 的 NANDFlash 操作文件(s3c2440_nand.c)
# 1. 创建s3c2440_nand.c
cd drivers/mtd/nand
cp s3c2410_nand.c s3c2440_nand.c
# 2. 将s3c2440_nand.c 加入编译之中
/* 2.1 include/configs/smdk2440.h line 211 */
+ #ifdef CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
+ #else
+ #define CONFIG_NAND_S3C2440
+ #define CONFIG_SYS_S3C2440_NAND_HWECC
+ #endif

# 2.2
cd drivers/mtd/nand
vim Makefile  # line 61
+ COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o 
  1. 修改s3c2440_nand.c
 /* drivers/mtd/nand/s3c2440_nand.c */
 1. line 129:
 - struct s3c2410_nand *nand_reg = s3c2410_get_base_nand();
 + struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();
 2. line 146
+ #if 0
    cfg = S3C2410_NFCONF_EN;
    cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
+ #endif
+ /* 初始化时序 */
+ cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);
+ /* 使能NAND Flash控制器,初始化ECC,禁止片选 */
+ writel((1<<4)|(1<<1)|(1<<0), &nand_reg->nfcont);

 3. line 90 - line 122 有关于ECC的部分删除
 4. 替换 s3c2440_nand.c 中 所有s3c2410的函数名为s3c2440;
 5. line 71:
 - if (ctrl & NAND_NCE)  /* 使能选中 */
 -      writel(readl(&nand->nfcont) & ~S3C2410_NFCONF_nFCE,
 -          &nand->nfconf);
 -  else    /* 取消选中 */
 -      writel(readl(&nand->nfcont) | S3C2410_NFCONF_nFCE,
 -          &nand->nfconf);
 
 + if (ctrl & NAND_NCE)  /* 使能选中 */
 +      writel(readl(&nand->nfcont) & ~(1<<1),
 +          &nand->nfcont);
 +  else    /* 取消选中 */
 +      writel(readl(&nand->nfcont) | (1<<1),
 +          &nand->nfcont);
 
 6. 自己添加 s3c2440_nand_select 的函数
 /* line 130 */
 -  nand->select_chip = NULL;
 +  nand->select_chop = s3c2440_nand_select;
 删除 函数 s3c2440_hwcontrol 的原有内容,自己重新完成
 +  struct s3c2440_nand *nand = s3c2440_get_base_nand();
 +  if (ctrl & NAND_CLE) {
 +      /* 发命令 */
 +      writeb (dat, &nand->nfcmd);
 +  } else if (ctrl & NAND_ALE) {
 +      /* 发地址 */
 +      writeb (dat, &nand->nfaddr);
 +  }

完成的s3c2440_nand_select函数
static void s3c2440_nand_select(struct mtd_info *mtd, int chipnr)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    switch (chipnr) {
    case -1:  /* 取消选中 */
        nand->nfcont |= (1<<1);
        break;
    case 0:  /* 选中 */
        nand->nfcont &= ~(1<<1);
        break;
    default:
        BUG();
    }
}

目前为止所有修改过的文件:

  1. include/configs/smdk2440.h
  2. drivers/mtd/nand/s3c2440_nand.c
  3. drivers/mtd/nand/Makefile // 直接在u-boot 中进行修改注意检查

修改源码支持DM9000

u-boot 的代码有DM9000的网卡的代码,只需要修改配置文件编译即可

/* include/configs/smdk2440.h line 59 */
+ #if 0
#define CONFIG_CS8900       /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE  0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
+ #else
+ #define CONFIG_DRIVER_DM9000
+ #endif
/* board/samsung/smdk2440/lowlevel_init.S line 160 */
-       .long 0x00000700     //BANKCON4
+       .long 0x00000740     //BANKCON4
/* board/samsung/smdk2440/smdk2440.c line 141 */
+ #ifdef CONFIG_DRIVER_DM9000
+   rc = dm9000_initialize(bis);
+ #endif

  1. 测试未连通,*** ERROR: `ethaddr' not set
# 不要执行save,因为还没有设置参数存放地址
 set ipaddr 192.168.1.17
 set ethaddr 00:0c:29:b2:67:65 (不设置这个就会出现上述报错)

目前为止所有修改过的文件:

  1. include/configs/smdk2440.h
  2. board/samsung/smdk2440/lowlevel_init.S
  3. board/samsung/smdk2440/smdk2440.c

裁剪和设置环境变量,让u-boot更易用

1. 一些完善性的修改

  1. 传给内核的启动参数
/* include/configs/smdk2440.h line  162 */
#define CONFIG_BOOTARGS "console=ttySAC0,115200 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND "nand read 30000000; bootm 30000000 "

/* board/samsung/smdk2440.c line 116 */
- gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
+ gd->bd->bi_arch_number = MACH_TYPE_S3C2440;

/* include/configs/smdk2440.h line  123 */
- #define CONFIG_IPADDR     10.0.0.110
- #define CONFIG_SERVERIP       10.0.0.1

+ #define CONFIG_IPADDR     192.168.1.17
+ #define CONFIG_SERVERIP       192.168.1.25
+ #define CONFIG_ETHADDR     00:0c:29:b2:67:66

2. 删减

/* include/configs/smdk2440.h */
1. line 77 - 80 USB 部分
2. line 85 RTC 部分
3. line 93 - 96 BOOTP 部分
4. line 105, 106, 111
// #define CONFIG_CMD_DATE
// #define CONFIG_CMD_DHCP
// #define CONFIG_CMD_USB
5. line 237 - 245 文件系统部分

3. 分区

  1. 注释掉原有的环境变量设置: include/configs/smdk2440.h line 202 - 207
  2. 重设自己的环境变量宏:
/* include/configs/smdk2440.h line 210 */
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET        0x00040000
#define CONFIG_ENV_SIZE          0x00020000
#define CONFIG_ENV_RANGE         CONFIG_ENV_SIZE
  1. 添加分区命令 mtdparts 至编译队列之中
/* include/configs/smdk2440.h line 215 */
+ #define CONFIG_CMD_MTDPARTS
+ #define CONFIG_MTD_DEVICE
+ #define MTDIDS_DEFAULT        "nand0=jz2440-0"  /* 哪一个设备 */
+ #define MTDPARTS_DEFAULT  "mtdparts=jz2440-0:256k(u-boot),"   \
+                       "128k(params),"     \
+                       "3m(kernel),"   \
+                       "-(rootfs)"     \
  1. 在 board.c 中设置分区
/* arch/arm/lib/board.c line 654 */
+   run_command ("mtdparts default", 0);
  1. 修改配置文件添加 yaffs2 支持
/* include/configs/smdk2440.h line 163 */
+ #define CONFIG_CMD_NAND_YAFFS
/* driver/mtd/nand/nand_util.c line 556 */
-           ops.mode = MTD_OOB_AUTO;
+           ops.mode = MTD_OOB_RAW;
/* driver/mtd/nand/nand_util.c line 567 */
- if(!rval)  
+ if (rval)   /* 错误修改 */

目前为止所有修改过的文件:

  1. include/configs/smdk2440.h
  2. board/samsung/smdk2440/lowlevel_init.S
  3. board/samsung/smdk2440/smdk2440.c
  4. arch/arm/lib/board.c
  5. driver/mtd/nand/nand_util.c

制作补丁

diff -urN u-boot-2012.04.01 u-boot-2012.04.01_100ask > u-boot-2012.04.01_100ask.patch

补充: DNW下载方式操作

对于课程自带的 u-boot1.1.6 来说,u-boot 界面集成了dnw下载的快捷连接
选择相应选项,然后再用dnw下载文件即可。不过对于通过 u-boot1.1.6 来下载
u-boot2012.04.01 这种情况是无法使用现有选项的,因为bootloader的分区太小
放不下新版的u-boot

1. 对于下载到NORFlash的操作

# q 退出u-boot 的选择菜单
1. usb 1 30000000  # 连接usb, 此时可以通过dnw开始下载文件
2. protect off all  # 关闭NORFlash 的写保护
3. erase 0 7FFFF    # 擦出指定空间,第一个参数是起始地址,第二个参数是偏移量
4. cp.b 30000000 0 80000  # 拷贝文件到指定位置,第一个参数是源文件的首地址,第二个参数是目标地址,第三个参数是大小

2. 对于下载到NANDFlash的操作

# q 退出u-boot 的选择菜单
1. usb 1 30000000  # 连接usb, 此时可以通过dnw开始下载文件
2. nand erase 0 7FFFF    # 擦出指定空间,第一个参数是起始地址,第二个参数是偏移量
3. nand write 30000000 0 80000  # 拷贝文件到指定位置,第一个参数是源文件的首地址,第二个参数是目标地址,第三个参数是大小   

你可能感兴趣的:(嵌入式开发实验笔记(五))