为AM335x移植Linux内核主线代码(7)使用SD卡中的U-Boot操作NAND Flash

ARM 342浏览

使用OK335xD核心板上的NAND Flash,无论是速度还是稳定性,都比SD卡好,所以接下来的任务是使用SD中的U-Boot操作NAND Flash,把需要的镜像烧录进去之后,就可以从NAND Flash启动了!

第一步:按照《U-Boot for AM335x》的步骤准备好:
OK335x开发板
按照TI公司官方文档的要求,格式化的SD卡(create-sdcard.sh)
准备一份编译通过的可用的U-Boot源代码(uart/mmc0/eth/gpio/i2c功能)
uImage和文件系统镜像

第二步:修改U-Boot源代码中mux部分:
static struct module_pin_mux nand_pin_mux[] = {
{OFFSET(gpmc_ad0),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_ad1),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_ad2),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_ad3),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_ad4),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_ad5),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_ad6),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_ad7),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_wait0),    MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_wpn),      MODE(0) | PULLUP_EN | RXACTIVE},
{OFFSET(gpmc_csn0),     MODE(0) | PULLUP_EN},
{OFFSET(gpmc_oen_ren),  MODE(0) | PULLUP_EN},
{OFFSET(gpmc_wen),      MODE(0) | PULLUP_EN},
{OFFSET(gpmc_be0n_cle), MODE(0) | PULLUP_EN},
{-1},
};

别忘了执行下面这句:
configure_module_pin_mux(nand_pin_mux);

第三步:在U-Boot源代码中board_init函数中添加:
gpmc_init();

第四步:在include/configs/maria_am335x.h中添加:
#define CONFIG_CMD_NAND
#define CONFIG_SYS_MAX_NAND_DEVICE      1
#define CONFIG_SYS_NAND_BASE            0x800000

#define CONFIG_NAND_OMAP_GPMC
#define CONFIG_NAND_OMAP_ELM
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT      (CONFIG_SYS_NAND_BLOCK_SIZE /
CONFIG_SYS_NAND_PAGE_SIZE)
#define CONFIG_SYS_NAND_PAGE_SIZE       2048
#define CONFIG_SYS_NAND_OOBSIZE         64
#define CONFIG_SYS_NAND_BLOCK_SIZE      (128*1024)
#define CONFIG_SYS_NAND_BAD_BLOCK_POS   NAND_LARGE_BADBLOCK_POS
#define CONFIG_SYS_NAND_ECCPOS          { 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, }

#define CONFIG_SYS_NAND_ECCSIZE         512
#define CONFIG_SYS_NAND_ECCBYTES        14
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_NAND_OMAP_ECCSCHEME      OMAP_ECC_BCH8_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START    CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS     0x80000

为什么不直接只用CONFIG_NAND,这些宏不就跟着定义了吗?
因为CONFIG_NAND的含义是从NAND启动,而这里只是要对NAND Flash进行读取和烧写操作,booting设备还是SD卡。

第五步:修改arch/arm/cpu/armv7/am33xx/mem.c中的"gpmc_init"函数:
void gpmc_init(void)
{
gpmc_cfg = (struct gpmc *)GPMC_BASE;
const u32  gpmc_regs[GPMC_MAX_REG] = {  M_NAND_GPMC_CONFIG1,
M_NAND_GPMC_CONFIG2,
M_NAND_GPMC_CONFIG3,
M_NAND_GPMC_CONFIG4,
M_NAND_GPMC_CONFIG5,
M_NAND_GPMC_CONFIG6,
0
};
u32 size = GPMC_SIZE_256M;
u32 base = CONFIG_SYS_NAND_BASE;

writel(0x00000008, &gpmc_cfg->sysconfig);
writel(0x00000000, &gpmc_cfg->irqstatus);
writel(0x00000000, &gpmc_cfg->irqenable);
writel(0x00000012, &gpmc_cfg->config);

writel(0, &gpmc_cfg->cs[0].config7);
sdelay(1000);

enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size);
}

这是因为gpmc_init依赖于CONFIG_NAND,要不然基本不干活,因此去掉它的宏判断。

第六步:编译它:
make ARCH=arm CROSS_COMPILE=/opt/arm-arago-linux-gcc/usr/bin/arm-linux-gnueabihf- -j8 O=../build maria_am335x_config
make ARCH=arm CROSS_COMPILE=/opt/arm-arago-linux-gcc/usr/bin/arm-linux-gnueabihf- -j8 O=../build all

第七步:将生成的MLO和u-boot.img放置到SD卡中:
cp ../build/MLO ../build/u-boot.img /run/media/maria/boot/

第八步:开发板插入SD卡,设置为从SD卡启动,上电。
在命令提示符下输入:
U-Boot# set ipaddr 192.168.1.117
U-Boot# set serverip 192.168.1.116

U-Boot# tftp 0x82000000 MLO
U-Boot# nand erase 0x0 0x20000
U-Boot# nand write.i 0x82000000 0x0 0x20000

U-Boot# tftp 0x82000000 u-boot.img
U-Boot# nand erase 0x80000 0x40000
U-Boot# nand write.i 0x82000000 0x80000 0x40000

这些命令的含义是,从tftp服务器上获取MLO和u-boot.img,存放在SDRAM的0x82000000处,并分别烧写在NAND Flash的0x0和0x80000地址。拔除SD卡,重新上电,就能看到U-Boot从NAND Flash启动的串口打印信息了!

NOTICE: 存放在tftp上的MLO和u-boot.img不能是Forlinx光盘里面的镜像,也不是上面所述的这个,而是需要使用全新的源代码重新编译。因为Forlinx和这里的MLO和u-boot.img都是从SD卡启动的,全新编译出来的应该是从NAND Flash启动。参照boards.cfg文件!

现在,这张SD卡就相当于一个下载器了,可以使用它实现读取和烧写存储器的功能,包括串口、SD卡和NAND Flash操作,这也说明,U-Boot的重要性,硬件开发绝对绕不开它!