OK6410裸板更新程序_update
2013-04-26 15:30
549 查看
我用的飞淩ok6410开发板,DNW下载程序太容易出问题了,于是买了个openjtag,买回来才发现暂不支持MLC NAND。我下决心写个有下载程序功能的裸板程序update.
再也不用忍受DNW了,并且还介绍一种SD卡下载方法。先用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把自己要下载的程序以u-boot.bin命名,也拷到sd卡,
mmc.bin会自动帮你把程序烧写到NAND,再从NAND启动就运行你的程序了。以后这片sd卡就相当于你的下载器,需要跑什么程序拷到sd卡就OK了。
具体操作过程见后面,现在开始写update程序。
系统:ubuntu 10.04.4
单板:ok6410
编译器:arm-linux-gcc-4.3.2
搭建开发环境详见ubuntu 10.04.4开发环境配置。
目标:串口输出菜单,有以下·功能供选择
*********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
即实现读写nand,通过V2.2.exe/gtkterm发送文件到内存,再写到NADN flash 0地址,以及重启update程序。
改程序主要功能是实现更新程序,以及把程序放到内存运行·。
一、编写源代码
根据s5pc100手册编写代码,包括源文件start.S clock.S sdram.c init.c main.c boot.lds Makefile
文件start.S:
文件boot.lds:
文件Makefile:
change@change:~/Si/OK6410/update$ cd /home/change/
change@change:~$ cd Si/OK6410/update/
change@change:~/Si/OK6410/update$ make clean
rm -f *.o *.bin *.elf *.dis
change@change:~/Si/OK6410/update$ make
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o start.o start.S
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o clock.o clock.S
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o sdram.o sdram.c
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o init.o init.c
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o main.o main.c
main.c: In function 'nand_read_test':
main.c:50: warning: passing argument 2 of 'nand_read' makes integer from pointer without a cast
main.c: In function 'nand_write_test':
main.c:98: warning: pointer targets in passing argument 2 of 'nand_write' differ in signedness
arm-linux-ld -Tboot.lds -o boot.elf start.o clock.o sdram.o init.o main.o
arm-linux-objcopy -O binary -S boot.elf update.bin
arm-linux-objdump -D -m arm boot.elf > boot.dis
change@change:~/Si/OK6410/update$
这都是经过修改后的最终编译结果,所以没有错误。
三、烧写、测试
用新想到的方法烧写程序,不用前面说的u-boot下载程序。先用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把上面编译生成的update.bin以u-boot.bin命名,并拷到sd卡,接着把单板拨到sd卡启动。我的OK6410在NAND启动的情况下直接把6、7拨到on就变成SD启动了。单板SD卡启动上电,串口(115200 8 n 1)输出如下:
K
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 1877 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
5228 bytes read
NAND write: device 0 offset 0x0, size 0x100000
1032192 bytes written: OK
reading zImage
** Unable to read "zImage" from mmc 0:1 **
说明u-boot烧写完毕。烧写mmc.bin的SD卡,会自动帮你把程序烧写到NAND。接着断电取下SD卡,单板拨到NAND启动,串口输出如下:
*********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
用串口工具v2.2.exe,演示update程序功能如下:
*********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
g
use V2.2.exe/gtkterm to send file
接着选择要发送的文件eg:u-boot.bin,并发送文件,发送完毕输出如下:
have get data:0x0003A6BC bytes
the first 16 bytes data:
0x15 0x00
0x00 0xEA
0x14 0xF0
0x9F 0xE5
0x14 0xF0
0x9F 0xE5
0x14 0xF0
0x9F 0xE5
Press Y to program the flash:
接着手动发送y,这里要谨慎操作,因为一旦输入y,程序就会擦除以前的程序。串口输出如下:
update program successful
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
看到update program successful上面程序更新完毕。下面来验证,断电重启,串口输出如下:
U-Boot 2012.04.01 (Nov 25 2012 - 21:01:21) for SMDK6410
CPU: S3C6400@532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board: SMDK6410
DRAM: 128 MiB
WARNING: Caches not enabled
Flash: 0 KB
NAND: select s3c_nand_oob_mlc_64
id_data[0] = 0xec id_data[1] = 0xd5 id_data[2] = 0x94 id_data[3] = 0x29 id_data[4] = 0x34 id_data[5] = 0x41 id_data[6] = 0xec id_data[7] = 0xd5 NAND_ECC_NONE selected by board driver. This is not recommended !!
2048 MiB
realpage value:255
page value:255
ret value:0
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: dm9000
Hit any key to stop autoboot: 0
##### 100ask Bootloader for OpenJTAG #####
Download u-boot to Nand Flash
[k] Download Linux kernel uImage
[j] Download root_jffs2 image
[y] Download root_yaffs image
[d] Download to SDRAM & Run
[z] Download zImage into RAM
[g] get file, and write to nand flash 0 block
[f] Format the Nand Flash
[s] Set the boot parameters
[b] Boot the system
[r] Reboot u-boot
[q] Quit from menu
Enter your selection: q
SMDK6410 #
说明u-boot已经下载完毕,当然以前的程序也就擦掉了。经过测试基本OK,可能还存在bug,反正人多力量大,可以提出一起解决。
刚刚新发现一问题,用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把上面编译生成的update.bin以u-boot.bin命名,并拷到sd卡,接着把单板拨到sd卡启动。出现问题
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 943 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
error found: 0010
解决error found: 0010方法:
在这里http://www.pc6.com/softview/SoftView_66768.html下载Aomei Partition Assistant Professional Edition 4.0,用该分区根据将以前分区删除,然后新建分区就行了,记住只选择你的SD卡盘,不要把自己系统盘给删了,那就亏大了。重新分区后的SD卡启动如下
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 1904 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
239292 bytes read
NAND write: device 0 offset 0x0, size 0x100000
1032192 bytes written: OK
reading zImage
** Unable to read "zImage" from mmc 0:1 **
这样就OK了。发现啥问题尽量提,一起解决它。
再也不用忍受DNW了,并且还介绍一种SD卡下载方法。先用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把自己要下载的程序以u-boot.bin命名,也拷到sd卡,
mmc.bin会自动帮你把程序烧写到NAND,再从NAND启动就运行你的程序了。以后这片sd卡就相当于你的下载器,需要跑什么程序拷到sd卡就OK了。
具体操作过程见后面,现在开始写update程序。
系统:ubuntu 10.04.4
单板:ok6410
编译器:arm-linux-gcc-4.3.2
搭建开发环境详见ubuntu 10.04.4开发环境配置。
目标:串口输出菜单,有以下·功能供选择
*********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
即实现读写nand,通过V2.2.exe/gtkterm发送文件到内存,再写到NADN flash 0地址,以及重启update程序。
改程序主要功能是实现更新程序,以及把程序放到内存运行·。
一、编写源代码
根据s5pc100手册编写代码,包括源文件start.S clock.S sdram.c init.c main.c boot.lds Makefile
文件start.S:
.text .global _start _start: /*0. 硬件相关的设置 */ /* Peri port setup */ ldr r0, =0x70000000 orr r0, r0, #0x13 mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff) /*1.关看门狗*/ ldr r0, =0x7E004000 mov r1, #0 str r1, [r0] ldr sp, =8*1024 /*2.设置时钟*/ bl clock_init /*3.初始化SDRAM DDR*/ bl ddr_init /*4.重定位:把代码从flash复制到他的链接地址*/ ldr sp, =0x58000000 bl nand_init mov r0, #0 ldr r1, =_start ldr r2, =__bss_start sub r2, r2, r1 bl copy_code_to_sdram bl clear_bss /*5.执行main*/ ldr lr, =halt ldr pc, =main halt: b halt文件clock.S:
.globl clock_init clock_init: /* 1.设置LOCK_TIME */ ldr r0, =0x7E00F000 /* APLL_LOCK */ ldr r1, =0x0000FFFF str r1, [r0] str r1, [r0, #4] /* MPLL_LOCK */ str r1, [r0, #8] /* EPLL_LOCK */ #define OTHERS 0x7e00f900 @ set async mode /* 当CPU时钟 != HCLK时,要设为异步模式 */ ldr r0, =OTHERS ldr r1, [r0] bic r1, r1, #0xc0 /* 1100,0000 */ str r1, [r0] loop1: /* 等待,直到CPU进入异步模式 */ ldr r0, =OTHERS ldr r1, [r0] and r1, r1, #0xf00 cmp r1, #0 bne loop1 /* SYNC667 */ /* MISC_CON[19] = 0 */ #define ARM_RATIO 0 /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1) */ #define HCLKX2_RATIO 1 /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */ #define HCLK_RATIO 1 /* HCLK = HCLKX2 / (HCLK_RATIO + 1) */ #define PCLK_RATIO 3 /* PCLK = HCLKX2 / (PCLK_RATIO + 1) */ #define MPLL_RATIO 0 /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1) */ ldr r0, =0x7E00F020 /* CLK_DIV0 */ ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12) str r1, [r0] /* 2.配置时钟 */ /* 2.1 配置APLL */ /* 2.1.1 设置APLL * 2.1.2 MUXAPLL * 2.1.3 SYNC667 * 2.1.4 DIVAPLL */ #define APLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1)) ldr r0, =0x7E00F00C ldr r1, =APLL_CON_VAL str r1, [r0] /* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */ /* 2.2 配置MPLL */ /* 2.2.1 设置MPLL * 2.2.2 MUXMPLL * 2.2.3 SYNCMUX * 2.2.4 SYNC667 * 2.2.5 HCLKX2_RATIO * 2.2.6 PCLK_RATIO */ #define MPLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1)) ldr r0, =0x7E00F010 ldr r1, =MPLL_CON_VAL str r1, [r0] /* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */ /* 3.选择PLL的输出作为时钟源 */ ldr r0, =0x7E00F01C ldr r1, =0x03 str r1, [r0] mov pc, lr文件sdram.c:
//#include <common.h> #define MEMCCMD 0x7e001004 #define P1REFRESH 0x7e001010 #define P1CASLAT 0x7e001014 #define MEM_SYS_CFG 0x7e00f120 #define P1MEMCFG 0x7e00100c #define P1T_DQSS 0x7e001018 #define P1T_MRD 0x7e00101c #define P1T_RAS 0x7e001020 #define P1T_RC 0x7e001024 #define P1T_RCD 0x7e001028 #define P1T_RFC 0x7e00102c #define P1T_RP 0x7e001030 #define P1T_RRD 0x7e001034 #define P1T_WR 0x7e001038 #define P1T_WTR 0x7e00103c #define P1T_XP 0x7e001040 #define P1T_XSR 0x7e001044 #define P1T_ESR 0x7e001048 #define P1MEMCFG2 0X7e00104c #define P1_chip_0_cfg 0x7e001200 #define P1MEMSTAT 0x7e001000 #define P1MEMCCMD 0x7e001004 #define P1DIRECTCMD 0x7e001008 #define HCLK 133000000 #define nstoclk(ns) (ns/( 1000000000/HCLK)+1) #define vi *( volatile unsigned int * ) #define set_zero( addr, bit ) ( (vi addr) &= ( ~ ( 1 << (bit) ) ) ) #define set_one( addr, bit ) ( (vi addr) |= ( 1 << ( bit ) ) ) #define set_bit( addr, bit, val ) ( (vi addr) = (( vi addr)&=(~(1<<(bit))) ) | ( (val)<<(bit) ) ) #define set_2bit( addr, bit, val ) ( (vi addr) = (( vi addr)&(~(3<<(bit))) ) | ( (val)<<(bit) ) ) #define set_nbit( addr, bit, len, val ) \ ( (vi addr) = ((( vi addr)&(~(( ((1<<(len))-1) )<<(bit)))) | ( (val)<<(bit) ) )) #define get_bit( addr, bit ) ( (( vi addr ) & ( 1 << (bit) )) > 0 ) #define get_val( addr, val ) ( (val) = vi addr ) #define read_val( addr ) ( vi ( addr ) ) #define set_val( addr, val ) ( (vi addr) = (val) ) #define or_val( addr, val ) ( (vi addr) |= (val) ) void ddr_init( void ) { // tell dramc to configure set_val( MEMCCMD, 0x4 ); // set refresh period set_val( P1REFRESH, nstoclk(7800) ); // set timing para set_val( P1CASLAT, ( 3 << 1 ) ); set_val( P1T_DQSS, 0x1 ); // 0.75 - 1.25 set_val( P1T_MRD, 0x2 ); set_val( P1T_RAS, nstoclk(45) ); set_val( P1T_RC, nstoclk(68) ); unsigned int trcd = nstoclk( 23 ); set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) ); unsigned int trfc = nstoclk( 80 ); set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) ); unsigned int trp = nstoclk( 23 ); set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) ); set_val( P1T_RRD, nstoclk(15) ); set_val( P1T_WR, nstoclk(15) ); set_val( P1T_WTR, 0x7 ); set_val( P1T_XP, 0x2 ); set_val( P1T_XSR, nstoclk(120) ); set_val( P1T_ESR, nstoclk(120) ); // set mem cfg set_nbit( P1MEMCFG, 0, 3, 0x2 ); /* 10 column address */ /* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */ set_nbit( P1MEMCFG, 3, 3, 0x2 ); /* 13 row address */ set_zero( P1MEMCFG, 6 ); /* A10/AP */ set_nbit( P1MEMCFG, 15, 3, 0x2 ); /* Burst 4 */ set_nbit( P1MEMCFG2, 0, 4, 0x5 ); set_2bit( P1MEMCFG2, 6, 0x1 ); /* 32 bit */ set_nbit( P1MEMCFG2, 8, 3, 0x3 ); /* Mobile DDR SDRAM */ set_2bit( P1MEMCFG2, 11, 0x1 ); set_one( P1_chip_0_cfg, 16 ); /* Bank-Row-Column organization */ // memory init set_val( P1DIRECTCMD, 0xc0000 ); // NOP set_val( P1DIRECTCMD, 0x000 ); // precharge set_val( P1DIRECTCMD, 0x40000 );// auto refresh set_val( P1DIRECTCMD, 0x40000 );// auto refresh set_val( P1DIRECTCMD, 0xa0000 ); // EMRS set_val( P1DIRECTCMD, 0x80032 ); // MRS set_val( MEM_SYS_CFG, 0x0 ); // set dramc to "go" status set_val( P1MEMCCMD, 0x000 ); // wait ready while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1)); }文件init.c:
#define MEM_SYS_CFG (*((volatile unsigned long *)0x7E00F120)) #define NFCONF (*((volatile unsigned long *)0x70200000)) #define NFCONT (*((volatile unsigned long *)0x70200004)) #define NFCMMD (*((volatile unsigned long *)0x70200008)) #define NFADDR (*((volatile unsigned long *)0x7020000C)) #define NFDATA (*((volatile unsigned char *)0x70200010)) #define NFSTAT (*((volatile unsigned long *)0x70200028)) void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len); int isBootFromNorFlash(void) { volatile int *p = (volatile int *)0; int val; val = *p; *p = 0x12345678; if (*p == 0x12345678) { /*写成功,是nand启动*/ *p = val; return 0; } else { /*Nor不能像内存一样写*/ return 1; } } void copy_code_to_sdram(unsigned int src, unsigned int dest, unsigned int len) { int i = 0; /*如果是Nor启动*/ unsigned char *src_start = (unsigned char *)src; unsigned char *dest_start = (unsigned char *)dest; if(isBootFromNorFlash()) { while (i < len) { dest_start[i] = src_start[i]; i++; } } else { //nand_init(); //nand_resd(src, dest, len) nand_read(src, dest, len); } } void nand_select(void) { NFCONT &= ~(1<<1); } void nand_deselect(void) { NFCONT |= (1<<1); } void nand_cmd(unsigned char cmd) { NFCMMD = cmd; } void nand_addr(unsigned char addr) { NFADDR = addr; } unsigned char nand_get_data(void) { return NFDATA; } void nand_send_data(unsigned char data) { NFDATA = data; } void wait_ready(void) { while ((NFSTAT & 0x1) == 0); } void nand_reset(void) { /* 选中 */ nand_select(); /* 发出0xff命令 */ nand_cmd(0xff); /* 等待就绪 */ wait_ready(); /* 取消选中 */ nand_deselect(); } void clear_bss(void) { extern int __bss_start, __bss_end; int *p = &__bss_start; for (; p < &__bss_end; p++) *p = 0; } void nand_init(void) { /* 让xm0csn2用作nand flash cs0 片选引脚 */ MEM_SYS_CFG &= ~(1<<1); /* 设置时间参数 */ #define TACLS 0 #define TWRPH0 2 #define TWRPH1 1 NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4)); NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4)); /* 使能nand flash controller */ NFCONT |= 1; NFCONT &= ~(1<<16); /* 森止soft lock */ nand_reset(); } void nand_send_addr(unsigned int addr) { #if 1 unsigned int page = addr / 4096; unsigned int colunm = addr & (4096 - 1); /* 这两个地址表示从页内哪里开始 */ nand_addr(colunm & 0xff); nand_addr((colunm >> 8) & 0xff); /* 下面三个地址表示哪一页 */ nand_addr(page & 0xff); nand_addr((page >> 8) & 0xff); nand_addr((page >> 16) & 0xff); #else nand_addr(addr & 0xff); /* a0~a7 */ nand_addr((addr >> 8) & 0x1f); /* 程序的角度: a8~a12 */ nand_addr((addr >> 13) & 0xff); /* 程序的角度: a13~a20 */ nand_addr((addr >> 21) & 0xff); /* 程序的角度: a21~a28 */ nand_addr((addr >> 29) & 0x7); /* 程序的角度: a29 ~ */ #endif } void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len) { unsigned int addr = nand_start; int i = nand_start % 4096; int left = i; int count = 0; unsigned char *dest = (unsigned char *)ddr_start; unsigned char data = 0; /* 选中芯片 */ nand_select(); while (count < len) { /* 发出命令0x00 */ nand_cmd(0x00); /* 发出地址 */ nand_send_addr(addr); /* 发出命令0x30 */ nand_cmd(0x30); /* 等待就绪 */ wait_ready(); /* 读数据 */ for (; i < (4096-left) && count < len; i++)//从某页的i处开始读 { data = nand_get_data(); if(addr<16384)//前4页每次只能写2K { if(i<(2048-left)) { dest[count++] = data; } } else { dest[count++] = data; } //dest[count++] = nand_get_data(); addr++; } i = 0; left = i; } /* 取消片选 */ nand_deselect(); // return 0; } void nand_erase_block(unsigned long addr) { int page = addr / 4096; nand_select(); nand_cmd(0x60); nand_addr(page & 0xff); nand_addr((page >> 8) & 0xff); nand_addr((page >> 16) & 0xff); nand_cmd(0xd0); wait_ready(); nand_deselect(); } void nand_write(unsigned int nand_start, unsigned char * buf, unsigned int len) { unsigned long count = 0; unsigned long addr = nand_start; int i = nand_start % 4096; int left = i; nand_select(); while (count < len) { nand_cmd(0x80); nand_send_addr(addr); for (; i < (4096-left) && count < len; i++) { if(addr<16384)//写前2K { if(i<(2048-left))//前2页每页只能写2K { nand_send_data(buf[count++]); } } else { nand_send_data(buf[count++]); } //nand_send_data(buf[count++]); addr++; } nand_cmd(0x10); wait_ready(); i = 0; left = i; } nand_deselect(); } #define ULCON0 (*((volatile unsigned long *)0x7F005000)) #define UCON0 (*((volatile unsigned long *)0x7F005004)) #define UFCON0 (*((volatile unsigned long *)0x7F005008)) #define UMCON0 (*((volatile unsigned long *)0x7F00500C)) #define UTRSTAT0 (*((volatile unsigned long *)0x7F005010)) #define UFSTAT0 (*((volatile unsigned long *)0x7F005018)) #define UTXH0 (*((volatile unsigned char *)0x7F005020)) #define URXH0 (*((volatile unsigned char *)0x7F005024)) #define UBRDIV0 (*((volatile unsigned short *)0x7F005028)) #define UDIVSLOT0 (*((volatile unsigned short *)0x7F00502C)) #define GPACON (*((volatile unsigned long *)0x7F008000)) #define ENABLE_FIFO static void delay(void) { volatile int i = 10; while (i--); } void init_uart(void) { GPACON &= ~0xff; GPACON |= 0x22; /* ULCON0 */ ULCON0 = 0x3; /* 数据位:8, 无较验, 停止位: 1, 8n1 */ UCON0 = 0x5; /* 使能UART发送、接收 */ #ifdef ENABLE_FIFO UFCON0 = 0x07; /* FIFO enable */ #else UFCON0 = 0x00; /* FIFO disable */ #endif UMCON0 = 0; /* 波特率 */ /* DIV_VAL = (PCLK / (bps x 16 ) ) - 1 * bps = 115200 * DIV_VAL = (66500000 / (115200 x 16 ) ) - 1 * = 35.08 */ UBRDIV0 = 35; /* x/16 = 0.08 * x = 1 */ UDIVSLOT0 = 0x1; } unsigned char getc(void) { #ifdef ENABLE_FIFO while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)delay(); #else while ((UTRSTAT0 & (1<<0)) == 0); #endif return URXH0; } int getc_nowait(unsigned char *pChar) { #ifdef ENABLE_FIFO if ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0) #else if ((UTRSTAT0 & (1<<0)) == 0) #endif { return -1; } else { *pChar = URXH0; return 0; } } void putc(char c) { #ifdef ENABLE_FIFO while (UFSTAT0 & (1<<14))delay(); #else while ((UTRSTAT0 & (1<<2)) == 0); #endif UTXH0 = c; } void puts(char *str) { int i = 0; while (str[i]) { putc(str[i]); i++; } } void puthex(unsigned int val) { /* 0x1234abcd */ int i; int j; puts("0x"); for (i = 0; i < 8; i++) { j = (val >> ((7-i)*4)) & 0xf; if ((j >= 0) && (j <= 9)) putc('0' + j); else putc('A' + j - 0xa); } } void putbyte(unsigned char val) { /* 0x1234abcd */ int i; int j; puts("0x"); for (i = 0; i < 2; i++) { j = (val >> ((1-i)*4)) & 0xf; if ((j >= 0) && (j <= 9)) putc('0' + j); else putc('A' + j - 0xa); } }文件main.c:
extern void init_uart(void); extern void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len); extern void putc(char c); extern void puts(char *str); extern void puthex(unsigned int val); extern unsigned char getc(void); extern int getc_nowait(unsigned char *pChar); extern void putbyte(unsigned char val); extern void nand_erase_block(unsigned long addr); extern void nand_write(unsigned int nand_start, unsigned char * buf, unsigned int len); int strlen(char *str) { int i = 0; while (str[i]) { i++; } return i; } void nand_read_test(void) { int i; char buf[100]; unsigned long addr; unsigned long size; puts("enter the start address: 0x80000"); //scanf("%s", buf); //addr = strtoul(buf, NULL, 0); addr = 0x80000; //puts("read addr = 0x%x\n\r", addr); puts("enter the size: 0x60"); //scanf("%s", buf); //size = strtoul(buf, NULL, 0); size = 0x60; if (size > 100) { puts("the max size is 100\n\r"); size = 100; } nand_read(addr, buf, size); puts("datas: \n\r"); for (i = 0; i < size; i++) { // printf("%02x ", buf[i]); putbyte(buf[i]); puts("\t"); if ((i+1) % 8 == 0) { puts("\n\r"); } } puts("\n\r"); } void nand_erase_test(void) { //char buf[100]; unsigned long addr; puts("enter the start address: "); //scanf("%s", buf); //addr = strtoul(buf, NULL, 0); addr = 0x80000; puts("erase addr = "); puthex(addr); puts("\n\r"); nand_erase_block(addr); } void nand_write_test(void) { char buf[20] = {"abcd1234ABCD"}; unsigned long addr; unsigned long size; puts("enter the start address:0x80000 "); //scanf("%s", buf); //addr = strtoul(buf, NULL, 0); addr = 0x80000; puts("enter the string:abcd1234ABCD "); //scanf("%s", buf); size = strlen(buf) + 1; puts(" size= "); puthex(size); puts("\n\r"); nand_write(addr, buf, size); } void update_program(void) { unsigned char *buf = (unsigned char *)0x52000000; unsigned long len = 0; int have_begin = 0; int nodata_time = 0; unsigned long erase_addr; char c; int i; /* 璇讳覆鍙h幏寰楁暟鎹?*/ puts("\n\ruse V2.2.exe/gtkterm to send file\n\r"); while (1) { if (getc_nowait(&buf[len]) == 0) { have_begin = 1; nodata_time = 0; len++; } else { if (have_begin) { nodata_time++; } } if (nodata_time == 1000) { break; } } puts("\n\rhave get data:"); puthex(len); puts(" bytes\n\r"); puts("the first 16 bytes data: \n\r"); for (i = 0; i < 16; i++) { // put("%02x ", buf[i]); putbyte(buf[i]); puts("\t"); } puts("\n\r"); puts("Press Y to program the flash: \n\r"); c = getc(); putc(c); puts("\n\r"); if (c == 'y' || c == 'Y') { /* 鐑у啓鍒皀and flash block 0 */ for (erase_addr = 0; erase_addr < ((len + 0x1FFFF) & ~0x1FFFF); erase_addr += 0x20000) { nand_erase_block(erase_addr); } nand_write(0, buf, len); puts("update program successful\n\r"); } else { puts("Cancel program!\n\r"); } } void run_program(void) { unsigned char *buf = (unsigned char *)0x57e00000; unsigned long len = 0; int have_begin = 0; int nodata_time = 0; void (*theProgram)(void); int i; puts("\n\r use gtkterm to send file\n\r"); while (1) { if (getc_nowait(&buf[len]) == 0) { have_begin = 1; nodata_time = 0; len++; } else { if (have_begin) { nodata_time++; } } if (nodata_time == 1000) { break; } } //printf("have get %d bytes data\n\r", len); puts("\n\r have get data:"); puthex(len); puts(" bytes\n\r"); puts("the first 16 bytes data: \n\r"); for (i = 0; i < 16; i++) { // put("%02x ", buf[i]); putbyte(buf[i]); puts("\t"); //putc('\0'); } puts("\n\r"); puts("jump to 0x57e00000 to run it\n\r"); theProgram = (void (*)(void))0x57e00000; theProgram(); } int main(void) { char c; init_uart(); puts("\n\r*********************************\n\r"); puts("update program with serial port\n\r"); puts("The board:witech(ok6410)\n\r"); puts("The NAND:K9GAG08U0D 2048MB\n\r"); puts("The DDR:K4X1G163PCX2 256MB\n\r"); puts("The NET:DM9000AEP\n\r"); puts(" date: 2013.4.26\n\r"); puts("***********************************\n\r"); while (1) { puts("the menu of the update programe:\n\r"); puts("[w] write the nand flash\n\r"); puts("[r] read the nand flash\n\r"); puts("[e] erase the nand flash\n\r"); puts("[g] get file, and write to nand flash 0 block\n\r"); puts("[x] get file to ddr(0x57e00000), run it\n\r"); puts("[s] reset the programe\n\r"); puts("Please enter the chose:\n\r"); do { c = getc(); if (c == '\n' || c == '\r') { puts("\n\r"); } else { putc(c); } } while (c == '\n' || c == '\r'); switch (c) { case 'w': case 'W': { nand_write_test(); break; } case 'r': case 'R': { nand_read_test(); break; } case 'e': case 'E': { nand_erase_test(); break; } case 'g': case 'G': { update_program(); break; } case 'x': case 'X': { run_program(); break; } case 's': case 'S': { void (*theProgram)(void); theProgram = (void (*)(void))0x57e00000; theProgram(); break; } } } return 0; }
文件boot.lds:
SECTIONS { . = 0x57e00000; .text : { *(.text) } . = ALIGN(4); .rodata : {*(.rodata*)} . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); __bss_start = .; .bss : { *(.bss) *(COMMON) } __bss_end = .; }
文件Makefile:
CC = arm-linux-gcc LD = arm-linux-ld AR = arm-linux-ar OBJCOPY = arm-linux-objcopy OBJDUMP = arm-linux-objdump CFLAGS := -Wall -O2 CPPFLAGS := -nostdinc -nostdlib -fno-builtin objs := start.o clock.o sdram.o init.o main.o update.bin: $(objs) ${LD} -Tboot.lds -o boot.elf $^ ${OBJCOPY} -O binary -S boot.elf $@ ${OBJDUMP} -D -m arm boot.elf > boot.dis %.o:%.c ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $< %.o:%.S ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $< clean: rm -f *.o *.bin *.elf *.dis二、编译源程序
change@change:~/Si/OK6410/update$ cd /home/change/
change@change:~$ cd Si/OK6410/update/
change@change:~/Si/OK6410/update$ make clean
rm -f *.o *.bin *.elf *.dis
change@change:~/Si/OK6410/update$ make
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o start.o start.S
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o clock.o clock.S
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o sdram.o sdram.c
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o init.o init.c
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o main.o main.c
main.c: In function 'nand_read_test':
main.c:50: warning: passing argument 2 of 'nand_read' makes integer from pointer without a cast
main.c: In function 'nand_write_test':
main.c:98: warning: pointer targets in passing argument 2 of 'nand_write' differ in signedness
arm-linux-ld -Tboot.lds -o boot.elf start.o clock.o sdram.o init.o main.o
arm-linux-objcopy -O binary -S boot.elf update.bin
arm-linux-objdump -D -m arm boot.elf > boot.dis
change@change:~/Si/OK6410/update$
这都是经过修改后的最终编译结果,所以没有错误。
三、烧写、测试
用新想到的方法烧写程序,不用前面说的u-boot下载程序。先用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把上面编译生成的update.bin以u-boot.bin命名,并拷到sd卡,接着把单板拨到sd卡启动。我的OK6410在NAND启动的情况下直接把6、7拨到on就变成SD启动了。单板SD卡启动上电,串口(115200 8 n 1)输出如下:
K
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 1877 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
5228 bytes read
NAND write: device 0 offset 0x0, size 0x100000
1032192 bytes written: OK
reading zImage
** Unable to read "zImage" from mmc 0:1 **
说明u-boot烧写完毕。烧写mmc.bin的SD卡,会自动帮你把程序烧写到NAND。接着断电取下SD卡,单板拨到NAND启动,串口输出如下:
*********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
用串口工具v2.2.exe,演示update程序功能如下:
*********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
g
use V2.2.exe/gtkterm to send file
接着选择要发送的文件eg:u-boot.bin,并发送文件,发送完毕输出如下:
have get data:0x0003A6BC bytes
the first 16 bytes data:
0x15 0x00
0x00 0xEA
0x14 0xF0
0x9F 0xE5
0x14 0xF0
0x9F 0xE5
0x14 0xF0
0x9F 0xE5
Press Y to program the flash:
接着手动发送y,这里要谨慎操作,因为一旦输入y,程序就会擦除以前的程序。串口输出如下:
update program successful
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:
看到update program successful上面程序更新完毕。下面来验证,断电重启,串口输出如下:
U-Boot 2012.04.01 (Nov 25 2012 - 21:01:21) for SMDK6410
CPU: S3C6400@532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board: SMDK6410
DRAM: 128 MiB
WARNING: Caches not enabled
Flash: 0 KB
NAND: select s3c_nand_oob_mlc_64
id_data[0] = 0xec id_data[1] = 0xd5 id_data[2] = 0x94 id_data[3] = 0x29 id_data[4] = 0x34 id_data[5] = 0x41 id_data[6] = 0xec id_data[7] = 0xd5 NAND_ECC_NONE selected by board driver. This is not recommended !!
2048 MiB
realpage value:255
page value:255
ret value:0
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: dm9000
Hit any key to stop autoboot: 0
##### 100ask Bootloader for OpenJTAG #####
Download u-boot to Nand Flash
[k] Download Linux kernel uImage
[j] Download root_jffs2 image
[y] Download root_yaffs image
[d] Download to SDRAM & Run
[z] Download zImage into RAM
[g] get file, and write to nand flash 0 block
[f] Format the Nand Flash
[s] Set the boot parameters
[b] Boot the system
[r] Reboot u-boot
[q] Quit from menu
Enter your selection: q
SMDK6410 #
说明u-boot已经下载完毕,当然以前的程序也就擦掉了。经过测试基本OK,可能还存在bug,反正人多力量大,可以提出一起解决。
刚刚新发现一问题,用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把上面编译生成的update.bin以u-boot.bin命名,并拷到sd卡,接着把单板拨到sd卡启动。出现问题
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 943 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
error found: 0010
解决error found: 0010方法:
在这里http://www.pc6.com/softview/SoftView_66768.html下载Aomei Partition Assistant Professional Edition 4.0,用该分区根据将以前分区删除,然后新建分区就行了,记住只选择你的SD卡盘,不要把自己系统盘给删了,那就亏大了。重新分区后的SD卡启动如下
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 1904 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
239292 bytes read
NAND write: device 0 offset 0x0, size 0x100000
1032192 bytes written: OK
reading zImage
** Unable to read "zImage" from mmc 0:1 **
这样就OK了。发现啥问题尽量提,一起解决它。
相关文章推荐
- 程序卡OK6410裸板更新程序_update
- ARM嵌入式学习--OK6410裸板程序--2.GPIO控制LED跑马灯(从ARM汇编跳转到C语言)
- ARM嵌入式学习--OK6410裸板程序--1.GPIO控制LED
- OK6410串口裸板程序uart0
- TQ2440裸板更新程序_update
- Ok6410裸板程序开发(1)-开发环境搭建
- TQ2440裸板更新程序_update
- OK6410学习之裸板LED程序及RAM烧录
- ok6410第一个裸板程序led
- ok6410-第05篇-Linux 下裸板程序的开发
- micro2440裸板更新程序_update
- 飞凌OK6410开发板(裸板) 第一个点亮LED灯程序
- S5PC100裸板更新程序_update
- 在OK6410上运行QT程序找不到libQtGui.so.4的解决
- 关于ok6410的c语言环境初始化,以及点亮led程序
- Qt Creator可执行程序移植到OK6410上
- OK6410裸机程序之开始模板(Linux环境)
- ok6410LCD测试程序
- ok6410的定时器0 测试程序
- 在ok6410 Androdi开发板运行c程序,添加驱动模块,并测试android驱动