TQ2440裸板更新程序_update
来源:互联网 发布:淘宝促销活动 编辑:程序博客网 时间:2024/06/16 22:06
以前的裸板程序都是通过u-boot下载到内存运行,今天实现更新程序update,程序运行时会输出一个菜单供选择。
系统:ubuntu 10.04.4
单板:tq2440
编译器:arm-linux-gcc-4.3.2
搭建开发环境详见ubuntu 10.04.4开发环境配置。
目标:实现自我更新程序,串口输出菜单,有以下·功能供选择
*********************************
update program with serial port
The board:TQ2440
The NAND:K9F1216U0A 256MB
The NOR:EN29LV160AB 2MB
The SRAM:HY57V561620 x2 64MB
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(0x32000000), run it
[s] reset the programe
Please enter the chose:
一、编写源代码
根据s3c2440手册编写代码,包括文件:start.S init.c main.c boot.lds Makefile
文件start.S:
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))#define MEM_CTL_BASE 0x48000000.text.global_start_start:/*1.关看门狗*/ldr r0, =0x53000000mov r1, #0str r1, [r0]/*2.设置时钟*/ldr r0, =0x4c000014mov r1, #0x03str r1, [r0]/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */mrcp15, 0, r1, c1, c0, 0/* 读出控制寄存器 */ orrr1, r1, #0xc0000000/* 设置为“asynchronous bus mode” */mcrp15, 0, r1, c1, c0, 0/* 写入控制寄存器 *//* MPLLCON = S3C2440_MPLL_200MHZ */ldr r0, =0x4c000004ldr r1, =S3C2440_MPLL_200MHZstr r1, [r0]/*3.初始化SDRAM*/ldr r0, =MEM_CTL_BASEadr r1, sdram_config/*当前地址*/add r3, r0, #(13*4)1:ldr r2, [r1], #4str r2, [r0], #4cmp r0 ,r3bne 1b/*4.重定位:把bootloader本身代码从flash复制到他的链接地址*/ldr sp, =0x34000000bl nand_initmov r0, #0ldr r1, =_startldr r2, =__bss_startsub r2 ,r2, r1bl copy_code_to_sdrambl clear_bss/*5.执行main*///bl mainldr lr, =haltldr pc, =mainhalt:b haltsdram_config:.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文件init.c:
/* NAND FLASH控制器 */#define NFCONF (*((volatile unsigned long *)0x4E000000))#define NFCONT (*((volatile unsigned long *)0x4E000004))#define NFCMMD (*((volatile unsigned char *)0x4E000008))#define NFADDR (*((volatile unsigned char *)0x4E00000C))#define NFDATA (*((volatile unsigned char *)0x4E000010))#define NFSTAT (*((volatile unsigned char *)0x4E000020))/* GPIO */#define GPHCON (*(volatile unsigned long *)0x56000070)#define GPHUP (*(volatile unsigned long *)0x56000078)/* UART registers*/#define ULCON0 (*(volatile unsigned long *)0x50000000)#define UCON0 (*(volatile unsigned long *)0x50000004)#define UFCON0 (*(volatile unsigned long *)0x50000008)#define UMCON0 (*(volatile unsigned long *)0x5000000c)#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)#define UFSTAT0 (*(volatile unsigned long *)0x50000018)#define UTXH0 (*(volatile unsigned char *)0x50000020)#define URXH0 (*(volatile unsigned char *)0x50000024)#define UBRDIV0 (*(volatile unsigned long *)0x50000028)#define TXD0READY (1<<2)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; unsigned char *src_start = (unsigned char *)src; unsigned char *dest_start = (unsigned char *)dest; /*如果是Nor启动*/ if(isBootFromNorFlash()) { while (i < len){ //dest[i] = src[i]; dest_start[i] = src_start[i]; i++;} } else { //nand_init(); //nand_resd(src, dest, len) nand_read(src, dest, len); }}void clear_bss(void){ extern int __bss_start, __bss_end;int *p = &__bss_start;for (; p < &__bss_end; p++)*p = 0;}void nand_select(void){ NFCONT &= ~(1<<1);}void nand_deselect(void){ NFCONT |= (1<<1);}void nand_cmd(unsigned char cmd){ volatile int i; NFCMMD = cmd; for (i = 0; i < 10; i++);}void nand_addr(unsigned int addr){unsigned int col = addr % 2048;unsigned int page = addr / 2048;volatile int i;NFADDR = col & 0xff;for (i = 0; i < 10; i++);NFADDR = (col >> 8) & 0xff;for (i = 0; i < 10; i++);NFADDR = page & 0xff;for (i = 0; i < 10; i++);NFADDR = (page >> 8) & 0xff;for (i = 0; i < 10; i++);NFADDR = (page >> 16) & 0xff;for (i = 0; i < 10; i++);}void wait_ready(void){while (!(NFSTAT & 1));}unsigned char nand_get_data(void){return NFDATA;}void nand_send_data(unsigned char data){ NFDATA = data;}void nand_reset(void){ /* 选中 */ nand_select(); /* 发出0xff命令 */ nand_cmd(0xff); /* 等待就绪 */ wait_ready(); /* 取消选中 */ nand_deselect();}void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len){unsigned int addr = nand_start;int col = addr % 2048;int i = 0;unsigned char *dest = (unsigned char *)ddr_start;/* 1. 选中 */nand_select();while (i < len){/* 2. 发出读命令00h */nand_cmd(0x00);/* 3. 发出地址(分5步发出) */nand_addr(addr);/* 4. 发出读命令30h */nand_cmd(0x30);/* 5. 判断状态 */wait_ready();/* 6. 读数据 */for (; (col < 2048) && (i < len); col++){dest[i] = nand_get_data();i++;addr++;}col = 0;}/* 7. 取消选中 */nand_deselect();}void nand_erase_block(unsigned long addr){ int page = addr / 2048; 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 % 2048; //int left = i; nand_select(); while (count < len) { nand_cmd(0x80); nand_addr(addr); //for (; i < (2048-left) && count < len; i++) for (; i < 2048 && 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(); }void nand_init(void){#define TACLS 0#define TWRPH0 1#define TWRPH1 0 /* 设置时序 */ NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */ NFCONT = (1<<4)|(1<<1)|(1<<0); nand_reset();}#define PCLK 50000000 // init.c中的clock_init函数设置PCLK为50MHz#define UART_CLK PCLK // UART0的时钟源设为PCLK#define UART_BAUD_RATE 115200 // 波特率#define UART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)#define ENABLE_FIFO static void delay(void){ volatile int i = 10; while (i--);}/* * 初始化UART0 * 115200,8N1,无流控 */void uart0_init(void){ GPHCON |= 0xa0; // GPH2,GPH3用作TXD0,RXD0 GPHUP = 0x0c; // GPH2,GPH3内部上拉 ULCON0 = 0x03; // 8N1(8个数据位,无较验,1个停止位) UCON0 = 0x05; // 查询方式,UART时钟源为PCLK #ifdef ENABLE_FIFOUFCON0 = 0x07; /* FIFO enable */ #elseUFCON0 = 0x00; /* FIFO disable */ #endif UMCON0 = 0x00; // 不使用流控 UBRDIV0 = UART_BRD; // 波特率为115200}/* * 发送一个字符 */void putc(unsigned char c){ /* 等待,直到发送缓冲区中的数据已经全部发送出去 */ //while (!(UTRSTAT0 & TXD0READY)); #ifdef ENABLE_FIFO while (UFSTAT0 & (1<<14))delay(); #else while ((UTRSTAT0 & (1<<2)) == 0);#endif /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */ UTXH0 = c;}/* * 接收字符 */unsigned char getc(void){ /* 等待,直到接收缓冲区中的有数据 */ //while (!(UTRSTAT0 & RXD0READY)); #ifdef ENABLE_FIFO while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)delay(); #else while ((UTRSTAT0 & (1<<0)) == 0);#endif /* 直接读取URXH0寄存器,即可获得接收到的数据 */ 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 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); elseputc('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); elseputc('A' + j - 0xa); }}文件main.c:
extern void uart0_init(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_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 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 update_program(void){ unsigned char *buf = (unsigned char *)0x32000000; //unsigned char *buf = (unsigned char *)0xD0036000; 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 *)0x32000000; //unsigned char *buf = (unsigned char *)0xD0036000; unsigned long len = 0; int have_begin = 0; int nodata_time = 0; void (*theProgram)(void); int i; /* 璇讳覆鍙h幏寰楁暟鎹?*/ 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 == 10000){ 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 0x32000000 to run it\n\r"); theProgram = (void (*)(void))0x32000000; theProgram();}int main(void){ char c; uart0_init(); puts("\n\r*********************************\n\r"); puts("update program with serial port\n\r"); puts("The board:TQ2440\n\r"); puts("The NAND:K9F1216U0A 256MB\n\r"); puts("The NOR:EN29LV160AB 2MB\n\r"); puts("The SRAM:HY57V561620 x2 64MB\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(0x32000000), 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))0x33f80000; theProgram(); break; }} } return 0;}文件boot.lds:
SECTIONS { . = 0x33f80000; .text : { *(.text) } . = ALIGN(4); .rodata : {*(.rodata*)} . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); __bss_start = .; .bss : { *(.bss) *(COMMON) } __bss_end = .;}文件Makefile:
CC = arm-linux-gccLD = arm-linux-ldAR = arm-linux-arOBJCOPY = arm-linux-objcopyOBJDUMP = arm-linux-objdumpCFLAGS := -Wall -O2CPPFLAGS := -nostdinc -nostdlib -fno-builtinobjs := start.o init.o main.oupdate.bin: $(objs)${LD} -Tboot.lds -o boot.elf $^${OBJCOPY} -O binary -S boot.elf $@${OBJDUMP} -D -m arm boot.elf > update.dis%.o:%.c${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<%.o:%.S${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<clean:rm -f *.o *.bin *.elf *.dis二、编译源代码
change@change:~$ cd Si/TQ2440/update/
change@change:~/Si/TQ2440/update$ make clean
rm -f *.o *.bin *.elf *.dis
change@change:~/Si/TQ2440/update$ ls
boot.lds init.c main.c Makefile start.S
change@change:~/Si/TQ2440/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 init.o init.c
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o main.o main.c
main.c: In function 'nand_write_test':
main.c:38: warning: pointer targets in passing argument 2 of 'nand_write' differ in signedness
main.c: In function 'nand_read_test':
main.c:69: warning: passing argument 2 of 'nand_read' makes integer from pointer without a cast
arm-linux-ld -Tboot.lds -o boot.elf start.o init.o main.o
arm-linux-objcopy -O binary -S boot.elf update.bin
arm-linux-objdump -D -m arm boot.elf > update.dis
change@change:~/Si/TQ2440/update$ cp update.bin /home/change/work/tftpboot/
change@change:~/Si/TQ2440/update$
三、烧写、测试
单板从NOR flash启动,用u-boot下载上面编译的程序update.bin到NAND Flash
U-Boot 1.1.6 (Mar 24 2012 - 03:44:51)
DRAM: 64 MB
Flash: 2 MB
NAND: 256 MiB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
TQ2440 # set ipaddr 172.16.1.133
TQ2440 # set gatewayip 172.16.1.1
TQ2440 # set serverip 172.16.1.131
TQ2440 # tftp 0x32000000 update.bin
dm9000 i/o: 0x20000000, id: 0x90000a46
MAC: 00:80:00:80:00:80
could not establish link
TFTP from server 172.16.1.131; our IP address is 172.16.1.133
Filename 'update.bin'.
Load address: 0x32000000
Loading: ##
done
Bytes transferred = 5136 (1410 hex)
TQ2440 # nand erase 0 0x40000
NAND erase: device 0 offset 0x0, size 0x40000
Erasing at 0x20000 -- 100% complete.
OK
TQ2440 # nand write 0x32000000 0 0x40000
NAND write: device 0 offset 0x0, size 0x40000
262144 bytes written: OK
TQ2440 # save
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
TQ2440 #
程序烧写完毕,接着单板断电从NAND启动,设置串口115200 8 n 1输出如下:
*********************************
update program with serial port
The board:TQ2440
The NAND:K9F1216U0A 256MB
The NOR:EN29LV160AB 2MB
The SRAM:HY57V561620 x2 64MB
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(0x32000000), run it
[s] reset the programe
Please enter the chose:
下面开始用串口v2.2.exe测试更新程序:
*********************************
update program with serial port
The board:TQ2440
The NAND:K9F1216U0A 256MB
The NOR:EN29LV160AB 2MB
The SRAM:HY57V561620 x2 64MB
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(0x32000000), run it
[s] reset the programe
Please enter the chose:
手动发送g
g
use V2.2.exe/gtkterm to send file
选择要发送的程序文件eg:boot.bin,并发送文件
have get data:0x000008BC bytes
the first 16 bytes data:
0x53 0x04 0xA0 0xE3 0x00 0x10 0xA0 0xE3 0x00 0x10 0x80 0xE5 0x98 0x00 0x9F 0xE5
Press Y to program the flash:
y
此时需谨慎,手动发送y,会擦除以前的程序,向NAND写新的程序
update program successful
这表明程序更新完毕,断电重启就会启动上面发送文件程序,这里串口输出如下:
Copy kernel from nand
0x1234ABCD
0x7D98ACBA
Set boot params
Boot kernel
测试OK,程序跑起来了。
- TQ2440裸板更新程序_update
- S5PC100裸板更新程序_update
- OK6410裸板更新程序_update
- micro2440裸板更新程序_update
- TQ2440串口裸板程序uart0
- elasticsearch的_update方法,一次调用执行多次更新
- TQ2440实验板OV9650测试程序的详解
- TQ2440第一个裸板程序led
- TQ2440裸奔程序>>流水灯测试程序
- TQ2440裸奔程序>>PWM蜂鸣器测试程序
- TQ2440裸奔程序>>看门狗测试程序
- TQ2440裸奔程序>>PWM蜂鸣器测试程序
- TQ2440开发板存储器
- TQ2440裸板学习笔记10--加速读取过程
- TQ2440开发板的流水灯程序-IDE为KEIL ARM !
- Ubuntu 12.04系统环境利用USB下载程序到TQ2440开发板
- TQ2440开发板学习纪实(4)--- 初始化片外RAM,让程序有更大内存空间
- TQ2440开发板学习纪实(4)--- 初始化片外RAM,让程序有更大内存空间
- 双系统(CentOS和XP)的系统时间相差8小时
- Weka 开发[1]-Instances类
- 关于载波与发送数据
- spring-data-mongo :Error creating bean with name 'indexCreationHelper':
- 光纤通道协议网络拓扑结构简介
- TQ2440裸板更新程序_update
- java 连接mysql数据库
- Windows对话框程序的大小与DPI的关系
- Visual Studio 2012 编译错误【error C4996: 'scanf': This function or variable may be unsafe. 】的解决方案
- java 调用user32.dll 锁定电脑
- android中自定义主题style的使用,app风格Theme自定义
- Composition(组合)与Aggregation(聚合)的区别
- quartz cron 表达式详解
- uva 10830 A New Function