您的位置:首页 > 编程语言

最小bootloader的实现,完整源代码

2009-12-30 15:19 441 查看
我们整个ARM课程就分为三部分,这是第一部分,实现一个自己的最小bootloader

1.Read Me

一、实现功能

1.硬件初始化

2.延时判断加载操作系统还是进入Bootloader Shell

3.加载操作系统

4.Bootloadershell

二、Bootloader Shell 支持的命令

1.help 帮助,显示所有支持的命令,及命令格式

2.loadx 下载文件到开发板的内存,默认到0x32000000

3.led_on 点亮一个led灯

4.led_off 关闭一个led灯

5.led_test 测试所有led灯,全亮全灭循环3次

6.beep_test 测试蜂鸣器,响3声

7.seg7_test 测试7段数码管

8.dip4_test 测试4位拨码开关

9.flash_load 将NandFlash中的文件搬移到SDARAM中

10.flash_write 将SDRAM中的内容下载到NandFlash中

11.GO 跳到某地址执行,默认到0x32000000

三、文件结构

1.start.s 程序入口,负责硬件初始化,Bootloader自搬移

2.uart.c uart.h 串口驱动的实现

3.load.c 选择加载操作系统还是进入Shell

4.stdlib.h stdlib.c 标准库函数的实现

5.stdio.h stdio.c 标准输入输出函数的实现

6.shell.c shell.h shell命令的实现

7.dip4.h dip4.c 拨码开关相关底层函数

8.seg7.h seg7.c 7段数码管相关底层函数

9.copy_myself.c nan.h NandFlash底层函数

10.xmodem.h xmodem.c xmodem协议实现

11.Datatype.h 数据定义

12.os/os.c 模拟操作系统

13.Makefile

四、流程及设计思想



1.硬件初始化

2.Bootloader自搬移

3.延时,判断是否有输入

4.(1)无输入则加载操作系统,操作系统烧写于Nand Flash的第100块,即位于100*32*512 = 0x190000

操作系统加载到内存的Sdram中

(2)有输入则进入shell命令模式

5.解释命令,使用自己实现的标准库函数来匹配输入的命令

6.匹配函数,定义了一个包含字符指针以及函数指针的结构体,可以通过对应关系迅速调用命令对应的函数

所有函数为void fun(void *)形式。

五、测试条件及结果

1. 打开超级终端,给开发板上电,超级终端上打印提示信息

2. 超级终端上开始3秒倒计时,3秒内不动键盘,提示加载操作系统,模拟操作系统的闪灯程序运行,可观察到LED等一闪一灭

3. 重启开发板,3秒内按下任意键,可看到有T-Boot#提示符,程序进入Shell模式

4. 输入help,可看到10条命令的使用方法

5. 输入led_on 1可看到第一个led灯亮

6. 输入led_off 1可看到第一个led灯灭

7. 输入led_test 可看到所有led一闪一灭3次

8. 输入beep_test 可听到蜂鸣器响3声

9. 输入seg7_test 可看到7段数码管每个led循环点亮

10.输入dip4_test 拨动拨码开关可观察到7段数码管对应的LED亮

11.输入loadx,发送文件0x/0s.bin

12.输入go 0x32000000 可观察到led灯一亮一灭

13.输入flash_load 0x190000 0x32000000 0x1000 (0x190000模拟操作系统烧写位置)

14.go 0x32000000 可观察到led一亮一灭

16.输入flash_write 0x32000000 0x200000 0x1000

17.输入flash_load 0x200000 0x31500000 0x1000

18.输入go 0x31500000 可观察到led灯一亮一灭

六、函数接口及功能

1.底层接口函数

uart.h

void uart_init(void); 初始化串口

void uart_putc(char ch); 打印一个字符到终端

char uart_getc(void); 从终端接收一个字符

void uart_test(void); 串口测试

void sdram_test(void); sdram测试

nand.h

void reset_nand(void); 重置串口

void init_nand(void); 初始化串口

int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);

读nand flash 第一个参数为需要存放书籍的内存首地址, 第二个参数为nand_flash的首地址,第三个参数为需要拷贝的大小

int nand_write_ll(unsigned char *buf, unsigned long start_addr, int size);

写nand flash 第一个参数为需要存放书籍的内存首地址, 第二个参数为nand_flash的首地址,第三个参数为需要拷贝的大小

dip.h



int dip_init(void); 初始化

int dip_num(void); 显示数字

int dip_test(void); 测试

seg7.h

int seg7_init(void); 初始化

int seg7_display_num(int num);显示数字

int seg7_test(void); 测试

2.库函数

stdio.h

char * uart_gets(char *buf); 打印字符串

void uart_puts(char *str); 接收字符串

void uart_printf(const char *str, ...);格式化输出

void uart_put_num(int num,int pow);打印数字

stdlib.h

int my_strcmp(char *src, char *dst);比较字符串,相等返回0

int my_atoi(char *str);转换字符串为数字

char * found_ch(char *str, char ch);在一个字符串中寻找一个字符

int my_strlen(char *str);计算字符串长度

int is_number(char ch);一个字符是否数字

int pow(int num, int power);计算num的power次方

int my_atox(char *str);将一个字符串按16进制转为数字

3.协议

xmodem.h

int xmodem_receive(int argc, char *argv);

int get_record(void);

4.其他

命令对应的解释函数,为方便调用参数均为void *

void help(void *argv);

void go(void *argv);

void loadx(void *argv);

void beep_test(void *argv);

void led_off(void *argv);

void led_on(void *argv);

void seg7_on(void *argv);

void dip4_on(void *argv);

void shell(void);

void led_test(void * argv);

void flash_load(void *argv);

void flash_write(void *argv);

void delay(int);

2.start.s



Code:

;s3c2440 bootloader

;author: tongxiaohua

;time : 2009.12.22



AREA FIRST, CODE, READONLY

ENTRY

CODE32

IMPORT uart_test

IMPORT sdram_test



START



WatchDog

;Close WatchDog

LDR R0, =0X53000000

MOV R1, #0X0

STR R1, [R0]



Led_on

;Make a Led on

LDR R2, =0x20800000

MOV R4, #0X1

STRB R4, [R2]



;BL DELAY



Beep_off

;Close Beep

;Control GPB0 output

LDR R0, =0x56000010

MOV R1, #0X1

STR R1, [R0]



LDR R0, =0X56000014

MOV R1, #0X0

STR R1, [R0]



Interrupt_off

;CLose Interrupt

LDR R0, =0X4A000008

LDR R1, =0XFFFFFFFF

STR R1, [R0]



Init_Clock



; Init Clock

; Set Mode

MRC p15,0,R1,c1,c0,0

ORR R1,R1,#0XC0000000

MCR p15,0,R1,c1,c0,0



;CAMDIVN

;When Config the register CLKDIVN Nedd This Configre

LDR R0,=0x4c000018

MOV R1,#0x0

STR R1,[r0]





;LOCKTIME PLL

LDR R0,=0x4c000000

LDR R1,=0x00ffffff

STR R1,[r0]



;UPLLCON

LDR R0,=0x4c000008

LDR R1,=0x00038022

STR R1,[R0]

NOP

NOP

NOP

NOP

NOP

NOP

NOP



;MPLLCON

LDR R0,=0x4c000004

LDR R1,=0x00044011

STR R1,[r0]



;CLKCON

;Witch divice need Clock

LDR R0,=0x4c00000c

LDR R1,=0x00fffff0

STR R1,[R0]



;CLKSLOW

;Low Clock

LDR R0,=0x4c000010

LDR R1,=0x00000004

STR R1,[R0]



;CLKDIVN

;HCLK = FCLK/3 PCLK = HCLK/2

LDR R0,=0x4c000014

LDR R1,=0x00000007

STR R1,[R0]



;Uart0

;Uart

;LDR SP, =0x1000

;LDR R2, =0x20800000

;MOV R4, #0X7

;STRB R4, [R2]

;BL uart_test



Memsetup



;SDRAM Init

ldr r1,=MEM_CTL_BASE

adrl r2,mem_cfg_val

add r3,r1,#52



1

ldr r4,[r2],#4

str r4,[r1],#4

cmp r1,r3

bne %1

nop

nop

nop

nop



MEM_CTL_BASE EQU 0X48000000



mem_cfg_val

DCD 0x22111110

DCD 0x00000700

DCD 0x00000700

DCD 0x00000700

DCD 0x00000700

DCD 0x00000700

DCD 0x00000700

DCD 0X00018005

DCD 0X00018005

DCD 0X008E0459

DCD 0X000000B1

DCD 0X00000030

DCD 0X00000030





Nandflash



;NandFlash,Bootloader CopyMyself

ldr sp,=0x33ef0000



IMPORT copy_myself



;nand_begin=0x0

;size=0x20000

;sdram_begin=0x33f00000



BL copy_myself



ldr r1,=on_the_ram

add pc,r1,#0

nop

nop

nop



on_the_ram



;Select mode

IMPORT load

ldr sp,=0x33ef0000

BL uart_test

BL sdram_test

BL load



B .



END

2.Copy_myself.c

Code:

/* NAND Flash registers 2440*/

#include "DataType.h"

#include "stdio.h"

#define NFCONF (*(volatile unsigned int *)0x4e000000)

#define NFCONT (*(volatile unsigned int *)0x4e000004)

#define NFCMD (*(volatile unsigned char *)0x4e000008)

#define NFADDR (*(volatile unsigned char *)0x4e00000c)

#define NFDATA (*(volatile unsigned char *)0x4e000010)

#define NFSTAT (*(volatile unsigned char *)0x4e000020)

#define NFMECC0 (*(volatile unsigned *)0x4E00002C)

#define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))

#define NAND_CHIP_DISABLE (NFCONT |= (1<<1))

#define NAND_CLEAR_RB (NFSTAT |= (1<<2))

#define NAND_DETECT_RB { while(! (NFSTAT&(1<<0)) );}

/* 在第一次实用NAND Flash前,复位一下NAND Flash */

#define BUSY 1

#define InitEcc() (NFCONT |= (1<<4))

#define MEccUnlock() (NFCONT &= ~(1<<5))

#define MEccLock() (NFCONT |= (1<<5))

#define SEccUnlock() (NFCONT &= ~(1<<6))

#define SEccLock() (NFCONT |= (1<<6))



/*for 8 bit nand flash, only use NFMECC0*/

#define RdNFMEcc() (NFMECC0)

#define NAND_SECTOR_SIZE 512

#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)



/*

inline void wait_idle(void)

{

while(!(NFSTAT & BUSY));

NFSTAT |= BUSY;

}

*/





void reset_nand(void)

{

//int i=0;

// NFCONF &= ~0x800;

// for(; i<10; i++);



NFCONF = 0x1400;

NFCONT = 0x73;



NAND_CHIP_ENABLE;



NFCMD = 0xff; //reset command



while(!(NFSTAT & BUSY));

NFSTAT |= BUSY;

}





/* 初始化NAND Flash */



void init_nand(void)

{



NFCONT = 0x73;

NAND_CHIP_DISABLE;

reset_nand();

}



/* low level nand read function */

int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)

{

int i, j;



if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

return -1; /* invalid alignment */

}



NAND_CHIP_ENABLE;



for(i=start_addr; i < (start_addr + size);) {

/* READ0 */

NAND_CLEAR_RB;

NFCMD = 0;



/* Write Address */

NFADDR = i & 0xff;

NFADDR = (i >> 9) & 0xff;

NFADDR = (i >> 17) & 0xff;

NFADDR = (i >> 25) & 0xff;



NAND_DETECT_RB;



for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {

*buf = (NFDATA & 0xff);

buf++;

}



}

NAND_CHIP_DISABLE;

return 0;

}





int NandErase(unsigned long start_addr)

{

if (start_addr & NAND_BLOCK_MASK) {

return -1; /* invalid alignment */

}



NAND_CHIP_ENABLE;



NAND_CLEAR_RB;

NFCMD = 0x60;



NFADDR = (start_addr>> 9) & 0xff;

NFADDR = (start_addr>> 17) & 0xff;

NFADDR = (start_addr>> 25) & 0xff;







NFCMD = 0xd0;

NAND_DETECT_RB;

uart_printf("Erase 0x%x/r",start_addr);



NAND_CHIP_DISABLE;



return 0;

}



int nand_write_ll(unsigned char *buf, unsigned long start_addr, int size)

{

int i, j, k;



if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

return -1; /* invalid alignment */

}

for(k = 0; k <= size / (16 * 1024); k++)

NandErase(start_addr + (k * 16 * 1024));

NAND_CHIP_ENABLE;



for(i=start_addr; i < (start_addr + size);) {

/* READ0 */

// if(k % 32 == 0) NandErase(start_addr);



NAND_CLEAR_RB;

NFCMD = 0x80;



/* Write Address */

NFADDR = i & 0xff;

NFADDR = (i >> 9) & 0xff;

NFADDR = (i >> 17) & 0xff;

NFADDR = (i >> 25) & 0xff;





for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {

NFDATA = *buf;

buf++;

}

NFCMD = 0x10;

NAND_DETECT_RB;

}

NAND_CHIP_DISABLE;

return 0;

}





void copy_myself(void)

{

unsigned char *buf = ((unsigned char *)0x33f00000);

unsigned long start_addr = 0;

int size = 0x20000;



reset_nand();

init_nand();

nand_read_ll(buf,start_addr,size);



}

3.dip.c

Code:

/*

* dip.c - dip api & driver

*

* Board: akae2440

* environment: bootloader & ADS

* Author: akaedu

* Date: 2009-5-26

* web: www.akaedu.org

*

*

* GPIO address_MAP

*

* CPLD_MAP_BASE physical address is 0x20800000

* CPLD_LED physical address is 0x20800000

* CPLD_SEG physical address is 0x20800080

* CPLD_DIP physical address is 0x208000a0

*

* GPIO port_MAP

*

* GPA_PORT~GPB_PORT(130 multi-functional input port pins)

* GPIO_BASE : GPACON : 0x56000000

*

* NAME GPIO CPLD_IN CPLD_OUT GPIO_CON MODE_bit_CON GPIO_DAT MODE_bit_DAT

* BEEP GPB0 TOUT0 BEEP 0x56000010 [1:0] 0x56000014 [0]

*

* GPIO key_scn_MAP

*

* NAME PORT_OUT PORT_IN

* KEY(sw1) KBOUT1 : GPB8 KBIN1 : ENT0 : GPF0

* KEY(sw2) KBOUT0 : GPB9 KBIN1 : ENT0 : GPF0

* KEY(sw3) KBOUT1 : GPB8 KBIN0 : ENT2 : GPF2

* KEY(sw4) KBOUT1 : GPB8 KBIN1 : ENT2 : GPF2

*

* GPIO_CON GPIO_DAT GPIO MODE_bit_CON MODE_bit_DAT

* GPBCON : 0x56000010 GPBDAT : 0x56000014 GPB8 [17:16] [8]

* GPBCON : 0x56000010 GPBDAT : 0x56000014 GPB9 [19:18] [9]

* GPFCON : 0x56000050 GPBDAT : 0x56000054 GPF0 [1:0] [0]

* GPFCON : 0x56000050 GPBDAT : 0x56000054 GPF2 [5:4] [2]

*

*/

#include "dip.h"

#include "seg7.h"



#define CPLD_DIP *((volatile unsigned char *)0x208000a0)



int dip_init(void)

{

return 0;

}

int dip_num(void)

{

return CPLD_DIP;

}



int dip_test(void)

{

int dip_input;

int i = 5000000;

seg7_init();

dip_init();



while(i--)

{

dip_input = dip_num();

seg7_display_num(dip_input);

}



return 0;

}

4.load.c

Code:

#include "uart.h"

#include "shell.h"

#include "stdlib.h"

#include "stdio.h"

#include "nand.h"



#define SEC 3

#define LOAD_OS 0

#define LOAD_SHELL 1

#define OS_MEM_ADDR 0x31000000

#define OS_ADDR (100 * 32 * 512) /*OS address*/

#define OS_SIZE 0x20000



/*Move OS to Sdram From NandFlash*/

void os_test(void)

{



unsigned char *buf = (unsigned char *)OS_MEM_ADDR;

unsigned long start = OS_ADDR;

int size = OS_SIZE;



uart_printf("/rcopy opration system to the sdrm from nanflash.../r");



reset_nand();

init_nand();

nand_read_ll(buf, start, size);



}



/*Wait for User Enter Any Key to Login in the Shell of Bootloader*/

int delay_p(int sec)

{

int osec = 500000, i, j;



uart_printf("Enter any key to load in the shell of bootloader:%d", sec);

for(i = 0; i < sec; i++)

{

for(j = 0; j < osec; j++)

{

if(UTRSTAT0 & UTRSTAT_R_READY){

uart_getchar();

return LOAD_SHELL;

}

}



uart_printf("/b%d", sec - i);

}

//uart_printf("return");

return LOAD_OS;

}



/*Shell or OS*/

void load(void)

{

int load_stat;



if((load_stat = delay_p(SEC)) == LOAD_OS)

{

os_test();

uart_printf("/rrun in the oprition system.../r");

go((void *)OS_MEM_ADDR);

}

else

{

shell();

}

}

5.seg7.c

Code:

/*

* seg7.c - seg7 api & driver

*

* Board: akae2440

* environment: bootloader & ADS

* Author: akaedu

* Date: 2009-5-26

* web: www.akaedu.org

*

*

* GPIO address_MAP

*

* CPLD_MAP_BASE physical address is 0x20800000

* CPLD_LED physical address is 0x20800000

* CPLD_SEG7 physical address is 0x20800080

* CPLD_DIP physical address is 0x208000a0

*

* GPIO port_MAP

*

* GPA_PORT~GPB_PORT(130 multi-functional input port pins)

* GPIO_BASE : GPACON : 0x56000000

*

* NAME GPIO CPLD_IN CPLD_OUT GPIO_CON MODE_bit_CON GPIO_DAT MODE_bit_DAT

* BEEP GPB0 TOUT0 BEEP 0x56000010 [1:0] 0x56000014 [0]

*

* GPIO key_scn_MAP

*

* NAME PORT_OUT PORT_IN

* KEY(sw1) KBOUT1 : GPB8 KBIN1 : ENT0 : GPF0

* KEY(sw2) KBOUT0 : GPB9 KBIN1 : ENT0 : GPF0

* KEY(sw3) KBOUT1 : GPB8 KBIN0 : ENT2 : GPF2

* KEY(sw4) KBOUT1 : GPB8 KBIN1 : ENT2 : GPF2

*

* GPIO_CON GPIO_DAT GPIO MODE_bit_CON MODE_bit_DAT

* GPBCON : 0x56000010 GPBDAT : 0x56000014 GPB8 [17:16] [8]

* GPBCON : 0x56000010 GPBDAT : 0x56000014 GPB9 [19:18] [9]

* GPFCON : 0x56000050 GPBDAT : 0x56000054 GPF0 [1:0] [0]

* GPFCON : 0x56000050 GPBDAT : 0x56000054 GPF2 [5:4] [2]

*

*/

#include "seg7.h"

#include "shell.h"



#define CPLD_SEG7 *((volatile unsigned char *)0x20800080)





/* delay for about one second */

/*static void delay(int time)

{

int i, j;



for(i = 0; i < time; i++)

for(j = 0; j < 500000; j++)

;

}*/



int seg7_init(void)

{

CPLD_SEG7 = 0x0;



return 0;

}



/* display number on seg7 */

int seg7_display_num(int num)

{

CPLD_SEG7 = 1<<num;



return 0;

}



int seg7_test(void)

{

int i;



seg7_init();

for(i = 0; i < 8; i++)

{

seg7_display_num(i);

delay(1);

}

return 0;

}

8.shell.c

Code:

#include "shell.h"

#include "uart.h"

#include "stdlib.h"

#include "stdio.h"

#include "xmodem.h"

#include "dip.h"

#include "seg7.h"

#include "nand.h"



#define START_ADDR 0x30000000

#define END_ADDR 0x34000000

#define MAX_LINE 256

#define CMD_NUM 11

#define LED_NUM 8

#define START_FLASH 0x0

#define END_FLASH 0x40000000

#define START_MEM 0x30000000

#define END_MEM 0x34000000

#define MAX_SIZE (END_MEM - START_MEM - 0x20000)

#define LED_ADDR *((volatile unsigned int *)0x20800000)

#define GPB0 *((volatile unsigned int *)0x56000010)

#define BEEP *((volatile unsigned int *)0x56000014)



/*delay*/

void delay(int sec)

{

int i, j;

for(i = 0; i < sec; i++)

{

for(j = 0; j < 500000; j++)

;

}

}



struct CMD{

char *cmd_line;

void (*fun)(void *);

}cmd[CMD_NUM] ={

{"help", help},

{"loadx", loadx},

{"go", go},

{"led_on", led_on},

{"led_off", led_off},

{"beep_test", beep_test},

{"led_test", led_test},

{"seg7_test", seg7_on},

{"dip4_test", dip4_on},

{"flash_load", flash_load},

{"flash_write", flash_write},

//{"flash_write", flash_write},

};





void flash_load(void *arg)

{

char *argv[4], *end;

int flash_start, mem_start, size;



argv[1] = arg;

uart_printf("the arg is %s/r", arg);

if((end = found_ch(arg, ' ')) == NULL)

{

uart_printf("Uaseage1: <flash_load> <flash address> <sdram address> <size>/r");

return;

}

else

{

*end = '/0';

end++;

}



argv[2] = end;

if((end = found_ch(end, ' ')) == NULL)

{

uart_printf("Uaseage2: <flash_load> <flash address> <sdram address> <size>/r");

return;

}

else

{

*end = '/0';

end++;

}



argv[3] = end;



if((flash_start = my_atox(argv[1])) < START_FLASH || (mem_start = my_atox(argv[2])) < START_MEM ||(size = my_atox(argv[3])) > MAX_SIZE || (mem_start + size) > END_MEM)

{

uart_printf("Access Violation: Please check your address/r");

uart_printf("flash_start = %x/rmem_start = %x/r size = %x/r", flash_start, mem_start, size);

}

else

{ uart_printf("flash_start = %x/rmem_start = %x/r size = %x/r", flash_start, mem_start, size);

nand_read_ll((unsigned char *)mem_start, flash_start, size);

}

}

#if 1

void flash_write(void *arg)

{

char *argv[4], *end;

int flash_start, mem_start, size;



argv[1] = arg;

uart_printf("the arg is %s/r", arg);

if((end = found_ch(arg, ' ')) == NULL)

{

uart_printf("Uaseage1: <flash_load> <sdram address> <flash address> <size>/r");

return;

}

else

{

*end = '/0';

end++;

}



argv[2] = end;

if((end = found_ch(end, ' ')) == NULL)

{

uart_printf("Uaseage2: <flash_load> <sdram address> <flash address> <size>/r");

return;

}

else

{

*end = '/0';

end++;

}



argv[3] = end;



if((flash_start = my_atox(argv[2])) < START_FLASH || (mem_start = my_atox(argv[1])) < START_MEM ||(size = my_atox(argv[3])) > MAX_SIZE || (mem_start + size) > END_MEM)

{

uart_printf("Access Violation: Please check your address/r");

// reset_nand();

// init_nand();

uart_printf("flash_start = %x/rmem_start = %x/r size = %x/r", flash_start, mem_start, size);

}

else

{

uart_printf("flash_start = %x/rmem_start = %x/r size = %x/r", flash_start, mem_start, size);

// reset_nand();

// init_nand();

nand_write_ll((unsigned char *)mem_start, flash_start, size);

}

}



#endif



void loadx(void * argv)

{

int argc;



uart_printf("argv is %s/r",(char *)argv);

if(argv != NULL) argc = 2;

else argc = 1;



if(found_ch(argv, ' ') != NULL)

{

uart_printf("Error: Usage <loadx> <address>/r");

}

else

{

xmodem_receive(argc, argv);

uart_printf("Success!");

}



return;



}



void led_on(void * argv)

{

/*test 第3字节有效*/

// uart_printf("%dnd led is on/r", (int)argv + 1);

// LED_ADDR = 0xff0000;

LED_ADDR |= (1 << ((int)argv + 16));

}



void led_off(void * argv)

{

// uart_printf("%dnd led is off/r", (int)argv + 1);

LED_ADDR &= ~(1 << ((int)argv + 16));

}



void led_test(void * argv)

{

int i, j;

for(i = 0; i < 3; i++ )

{

for(j = 0; j < LED_NUM; j++)

{

led_on((void *)j);

}

delay(1);

for(j = 0; j < LED_NUM; j++)

{

led_off((void *)j);

}

delay(1);

}

}



void beep_test(void *argv)

{

int i;



GPB0 |= 0x1;



for(i = 0; i < 3; i++)

{

BEEP = 0x1;

delay(1);

BEEP = 0x0;

delay(1);

}



}



void seg7_on(void *argv)

{

seg7_test();

}



void dip4_on(void * argv)

{

dip_test();

}



void help(void * argv)

{



uart_printf("loadx - [address], download a file to the borad/r");

uart_printf("go - <address>, go to the addrress/r");

uart_printf("flash_load - <flash address><sdram address><size>, Move the code to sdram from nandflash/r");

uart_printf("flash_write - <sdram address><flash address><size>, Move the code to Nandflash from sdram/r");

uart_printf("led_on - <led number>, test led/r");

uart_printf("led_off - <led_number>, test_led/r");

uart_printf("led_test - test all led/r");

uart_printf("beep_test - test beep/r");

uart_printf("seg7_test - test seg/r");

uart_printf("dip4_test - test dip4, you have ten second to test it/r/r");

}



void go(void *argv)

{

int addr = (int)argv;

if(addr == 0) addr = 0x32000000;

// void (*gt)(void) = (void (*) (void))addr;

if(addr < START_ADDR || addr > END_ADDR)

{

// return -1;

}

else

{

uart_printf("in go/r");

(*(void (*) (void))addr)();

}

}



void shellcmd(char buf[])

{

char *start, *end, *argv = NULL;

int i, i_argv;



start = buf;



if((end = found_ch(buf, ' ')) != NULL)

{

*end = '/0';

argv = end + 1;

}



// uart_printf("buf is before is%s/r",buf);

// uart_printf("the command is %s", start);

// uart_printf("the command is %s", cmd[0].cmd_line);



for(i = 0; i < CMD_NUM; i++)

{

if(my_strcmp(start, cmd[i].cmd_line) == 0)

{

if(i == 3 || i == 4){

i_argv = my_atoi(argv);

// uart_printf("i_argv is %d/r", i_argv);

(* cmd[i].fun)((void *) i_argv);

}

else if(i == 2)

{ i_argv = my_atox(argv);

// uart_printf("i_argv is %x/r", i_argv);

(* cmd[i].fun)((void *) i_argv);

}

else

{

(*cmd[i].fun)((void *) argv);

}

break;

}

}

if(i == CMD_NUM)

{

uart_printf("Command not found/r");

}

}



void shell(void)

{

char buf[MAX_LINE];



while(1)

{

uart_puts("/rT-BOOT#");

uart_gets(buf);

// uart_printf("/rget the command/r");

//uart_puts(buf);

shellcmd(buf);

}

}

6.stdio.c

Code:

#include <stdarg.h>

#include "stdlib.h"

#include "uart.h"

#include "stdio.h"



void uart_puts(char *str)

{

while(*str != '/0')

{

uart_putchar(*str);

str++;

}

}



char *uart_gets(char *str)

{

int i;

if(str == NULL) return str;



for(i = 0; ; i++)

{

str[i] = uart_getchar();



/*do shomthing when '/b is input'*/

if(str[i] == '/b')

{

if(i > 0){

uart_putchar('/b');

i -= 2;

}

else

{

i = -1;

}

}

else

{

uart_putchar(str[i]);

}

if(str[i] == '/r' || str[i] == '/n')

{

str[i] = '/0';

break;

}

}



return str;

}



void uart_put_num(int num,int pow)

{

if(num != 0)

{

uart_put_num(num/pow, pow);

if(num%pow > 9)

uart_putchar((char)(num%pow - 10) + 'A');

else

uart_putchar((char)(num%pow + '0'));

}

}





void uart_printf(const char *str, ...)

{

va_list ap;

char c, ch;

char * s; int num;



va_start(ap, str);

while(c = *str++)

{

if(c != '%')

{

uart_putchar(c);

}

else

{

c = *str++;

switch(c)

{

case 'c':

ch = va_arg(ap, int);

uart_putchar((char)ch);

break;

case 's':

s = va_arg(ap, char *);

uart_puts(s);

break;

case 'd':

num = va_arg(ap, int);

uart_put_num(num, 10);

break;

case 'x':

num = va_arg(ap, int);

uart_put_num(num, 16);

break;

default:

uart_putchar(c);

}

}

}

va_end(ap);

}

6.stdlib.h

Code:

#include "stdlib.h"

#include "stdio.h"



int my_strcmp(char *src, char *dst)

{

if(src == NULL || dst == NULL) goto exit;



while(*src == *dst && *src!= '/0' && *dst != '/0')

{

src++;

dst++;

}



exit:

return (*src - *dst);

}



char *found_ch(char *str, char ch)

{

if(str == NULL) goto exit;



while(*str != ch && *str != '/0')

{

str++;

}



exit:

if(*str == ch) return str;

else return NULL;

}



int my_strlen(char *str)

{

char *p = str;



if(str == NULL) goto exit;



while(*str != '/0')

{

str++;

}

exit:

return (str - p);

}



int is_number(char ch)

{

if('0' <= ch && ch <= '9') return 1;

else return 0;

}



int pow(int num, int power)

{

/*do not care about overflow*/

int count = 1;



while(power--)

{

count *= num;

}



return count;

}



int my_atoi(char *str)

{

int len = my_strlen(str), i, count = 0;



// uart_printf("the str is %s/r", str);

// uart_printf("len = %d/r", len);



if(str == NULL) goto exit;



// if(*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))

// str += 2;



for(i = 0; i < len; i++)

{

if(!is_number(str[i])) goto exit;



count += ((str[i] - '0')*pow(10, len - i - 1));

}



exit:

return count;

}



int my_atox(char *str)

{

int len = my_strlen(str), i, count = 0;



// uart_printf("the str is %s/r", str);

// uart_printf("len = %d/r", len);



if(str == NULL) goto exit;



if(*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X')){

str += 2;

len -= 2;

}

for(i = 0; i < len; i++)

{

if(!is_number(str[i])) goto exit;



count += ((str[i] - '0')*pow(16, len - i - 1));

// uart_printf("the count is %x/r", count);

}



exit:

return count;

}

7.uart.c

Code:

/*Uart Driver on S3C2440*/

/*Athor: tongxiaohua */

/*Time : 2009.12.27 */

#include "uart.h"

#include "stdlib.h"

#include "stdio.h"

#include "shell.h"





/*Init Uart0*/

void uart_init(void)

{

ULCON0 |= 3; /*8N1*/

UCON0 = 5; /*Work Frequency Select PCLK, the mode of recive/send select poll*/

UTRSTAT0 &= 6; /*Set Null of recive/send Buffer*/

UBRDIV0 = 26; /*(int)50000000 / (115200*16) - 1*/

GPHCON = 0xa0; /*Set F2, F3 Function*/

UFCON0 = 0;

UMCON0 = 0;

}



/*Put a byte to the Uart0*/

void uart_putchar(char ch)

{

while (!(UTRSTAT0 & UTRSTAT_T_EMPTY));

UTX0 = ch;



/*Back Space*/

if(ch == '/b')

{

while (!(UTRSTAT0 & UTRSTAT_T_EMPTY));

UTX0 = ' ';

while (!(UTRSTAT0 & UTRSTAT_T_EMPTY));

UTX0 = '/b';

}



/*Enter*/

if(ch == '/r')

{

while (!(UTRSTAT0 & UTRSTAT_T_EMPTY));

UTX0 = '/n';

}

}



/*Get a byte from Uart*/

char uart_getchar(void)

{

while (!(UTRSTAT0 & UTRSTAT_R_READY));

return URX0;

}



/*Test the Uart is or not Working*/

void uart_test(void)

{

uart_init();

uart_printf("/r/rWelecom to use my bootloader/rAuthor:tong xiaohua/rBoard:s3c2440/r");

uart_printf("Time: 2009.12.27/rCPU: Arm 920T/rSRAM: 4k/rSDRAM:32M/rNAND FLASH:64M/r");

uart_printf("Uart0 is working.../r");

}



/*Test the Sdram is or Not Working*/

void sdram_test(void)

{

int testnum = 0x12345678;

*((volatile unsigned int *)0x32000000) = testnum;

testnum = *((volatile unsigned int *)0x32000000);

if(testnum == 0x12345678)

{

// uart_printf("%x/r", testnum);

uart_printf("sdram is working.../r");

// uart_printf("test.../r");

}

else

{

// uart_printf("test faild/r");

uart_printf("sdram working error.../r", testnum);

// uart_printf("test.../r");

}

}

8.xmodem.c

Code:

#include "xmodem.h"

/* 这两个头文件是你已经实现的功能函数,下面

* 代码中用到的函数如不是xmodem.c中定义的,

* 需移植你已写好的函数接口到本程序中,如

* uart0_getchar()、uart0_putchar()、

* myprintf()等

*/

#include "stdio.h"

#include "uart.h"

#include "stdlib.h"





/* global error variable */

char *xmodem_errtxt = NULL;

int get_byte_err = 0;

U8 volatile receive_buffer[BLOCK_SIZE];

//unsigned download_addr = 0x8000;

/* prototypes of helper functions */

int get_record(void);



enum

{

SAC_SEND_NAK = 0,

SAC_SENT_NAK = 1,

SAC_PAST_START_NAK = 2

};



static volatile int seen_a_char = SAC_SEND_NAK;



//static int one_nak = 0;

//static unsigned long xmodem_timeout = GET_BYTE_TIMEOUT;



char debugbuf[4096];

int db_idx = 0;



static void delay(void)

{

int j;

for (j = 0; j < 2000090; j++)

;

}



int xmodem_receive(int argc, char *argv)

{

char ochr;

int r = 0, rx_block_num = 0, error_count = 0;

int foffset = 0;

int i;

unsigned int download_addr;

char nak = NAK;



xmodem_errtxt = NULL;

seen_a_char = 0;



uart_printf("in xmodem argc = %d, argv = %s /r", argc, argv);



// if(argc > 1) download_addr = atox(argv[1]);

if(argc > 1) download_addr = my_atox(argv);

else download_addr = 0x32000000;



uart_printf("download_addr is %x," , download_addr);



UART0_putchar('9');

delay();

UART0_putchar('8');

delay();

UART0_putchar('7');

delay();

UART0_putchar('6');

delay();

UART0_putchar('5');

delay();

UART0_putchar('4');

delay();

UART0_putchar('3');

delay();

UART0_putchar('2');

delay();

UART0_putchar('1');

delay();

UART0_putchar('0');



//uart_putchar(UART0_BASE, nak);

UART0_putchar(nak);



rx_block_num = 1;



/* times to retry */

error_count = RETRIES;



do {

/* when local block number equals to the block number in the packet,

store the data into the memory which download_addr points*/

if ((r = get_record()) == (rx_block_num & 255)) {

error_count = RETRIES;

for (i = 0; i <BLOCK_SIZE; i++)

*(U8 *)(download_addr+foffset+i) = receive_buffer[i];

xmodem_errtxt = "RX PACKET";

rx_block_num++;

ochr = ACK;

foffset += BLOCK_SIZE;

} else {

switch (r) {

case -1: /* TIMEOUT */

xmodem_errtxt = "TIMEOUT";

ochr = NAK;

break;

case -2: /* Bad block */

xmodem_errtxt = "BAD BLOCK#";

/* eat teh rest of the block */

#if 0

get_byte_err = 0;

while (get_byte_err != -1) get_byte();

#endif

ochr = NAK;

break;

case -3: /* Bad checksum */

xmodem_errtxt = "BAD CHKSUM";

ochr = NAK;

break;

case -4: /* End of file */

xmodem_errtxt = "DONE";

ochr = ACK;

break;

case -5: /* Cancel */

xmodem_errtxt = "ABORTED";

ochr = ACK;

break;

default: /* Block out of sequence */

xmodem_errtxt = "WRONG BLK";

ochr = NAK;

}

error_count--;

}



UART0_putchar(ochr);

} while ((r > -3) && error_count);



if ((!error_count) || (r != -4)) {

foffset = 0; /* indicate failure to caller */

}

my_printf( "Loaded file at address 0x%x, size = %d /r/n",(int)download_addr, foffset);



return foffset;

}



/*

* Read a record in the XMODEM protocol, return the block number

* (0-255) if successful, or one of the following return codes:

* -1 = Bad byte

* -2 = Bad block number

* -3 = Bad block checksum

* -4 = End of file

* -5 = Canceled by remote

*/

int get_record(void)

{

char c;

int block_num = 0;

int i;



U32 check_sum;



/* clear the buffer */

for (i = 0; i < BLOCK_SIZE; i++)

receive_buffer[i] = 0x00;



check_sum = 0;



/* initialize i to -2,when begin to transfer,the first byte

will be store into blcok_num,and after plused one,the next

byte will be treated as a negated section */

i = -2;

//uart_getchar( UART0_BASE, &c);

c = UART0_getchar();



switch (c)

{

case SOH: /* Receive packet */

for (;;)

{

//uart_getchar( UART0_BASE, &c);

c = UART0_getchar();



switch (i)

{

case -2:

block_num = c;

break;



case -1:

#if 0

#ifdef CHECK_NEGATED_SECTNUM

if (c != (-block_num -1))

return -2;

#endif

#endif

break;

case BLOCK_SIZE:

/* check if reveived data is correct,

when correct,block num is returned,

else -3 is returned */

if ((check_sum & 0xff) != c)

return -3;

else

return block_num;

break;



default:

/* save data to buffer,and accumulate to check_sum */

receive_buffer[i] = c;

check_sum += c;

}

i++;

}

case EOT: /* end of file encountered */

return -4;

case CAN: /* cancel protocol */

return -5;

default:

return -5;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: