从2016年第一次接触rtthread,感觉很容易上手,记得一个项目是小飞行器上的IPC,趁着空闲,手里有一块jz2440的板子,准备在这块板子上跑起来rtthread,查了很多资料,最后决定自己写一个简单的BootLoader启动板子,启动rtthread系统。下面是简单的BootLoader源代码。

init.c

主要是内存控制器初始化、串口初始化及与串口相关函数实现、nandflash初始化及读写功能。

/* 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 UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028) unsigned int *pGPFCON = (unsigned int *)0x56000050;
unsigned int *pGPFDAT = (unsigned int *)0x56000054; void led_on(void)
{
/* 配置GPF4为输出引脚 */
*pGPFCON = 0x1500;
/* 设置GPF4输出0 */
*pGPFDAT = ;
} void led_off(void)
{
/* 配置GPF4为输出引脚 */
*pGPFCON = 0x1500;
/* 设置GPF4输出0 */
*pGPFDAT = 0xff;
}
#define TXD0READY (1<<2) void nand_read(unsigned int addr, unsigned char *buf, unsigned int len); extern void puthex(unsigned int val);
extern void puts(char *str);
int isBootFromNorFlash(void)
{
volatile int *p = (volatile int *);
int val; val = *p;
*p = 0x12345678;
if (*p == 0x12345678)
{
/* 写成功, 是nand启动 */
*p = val;
return ;
}
else
{
/* NOR不能像内存一样写 */
return ;
}
} void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{
int i = ; /* 如果是NOR启动 */
if (isBootFromNorFlash())
{
while (i < len)
{
dest[i] = src[i];
i++;
}
}
else
{
//nand_init();
nand_read((unsigned int)src, dest, len);
}
} void clear_bss(void)
{
extern int __bss_start, __bss_end;
int *p = &__bss_start; for (; p < &__bss_end; p++)
*p = ;
} void nand_init(void)
{
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
/* 设置时序 */
NFCONF = (TACLS<<)|(TWRPH0<<)|(TWRPH1<<);
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
NFCONT = (<<)|(<<)|(<<);
} void nand_select(void)
{
NFCONT &= ~(<<);
} void nand_deselect(void)
{
NFCONT |= (<<);
} void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = ; i < ; i++);
} void nand_addr(unsigned int addr)
{
unsigned int col = addr % ;
unsigned int page = addr / ;
volatile int i; NFADDR = col & 0xff;
for (i = ; i < ; i++);
NFADDR = (col >> ) & 0xff;
for (i = ; i < ; i++); NFADDR = page & 0xff;
for (i = ; i < ; i++);
NFADDR = (page >> ) & 0xff;
for (i = ; i < ; i++);
NFADDR = (page >> ) & 0xff;
for (i = ; i < ; i++);
} void nand_wait_ready(void)
{
while (!(NFSTAT & ));
} unsigned char nand_data(void)
{
return NFDATA;
}
void nand_chip_id(void)
{
unsigned char buf[]={}; nand_select();
nand_cmd(0x90);
nand_addr(0x00); buf[] = nand_data();
buf[] = nand_data();
buf[] = nand_data();
buf[] = nand_data();
buf[] = nand_data();
nand_deselect(); puts("maker id\n\r");
puthex(buf[]);
puts("\n\r");
puts("device id\n\r");
puthex(buf[]);
puts("\n\r");
puts("3rd byte\n\r");
puthex(buf[]);
puts("\n\r");
puts("4th byte\n\r");
puthex(buf[]);
puts("\n\r");
puts("page size\n\r");
puthex( << (buf[] & 0x03));
puts("\n\r");
puts("block size\n\r");
puthex( << ((buf[] >> ) & 0x03));
puts("\n\r");
puts("5th byte\n\r");
puthex(buf[]);
} void nand_w_data(unsigned char val)
{
NFDATA = val;
} void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
int col = addr % ;
int i = ; /* 1. 选中 */
nand_select(); while (i < len)
{
/* 2. 发出读命令00h */
nand_cmd(0x00); /* 3. 发出地址(分5步发出) */
nand_addr(addr); /* 4. 发出读命令30h */
nand_cmd(0x30); /* 5. 判断状态 */
nand_wait_ready(); /* 6. 读数据 */
for (; (col < ) && (i < len); col++)
{
buf[i] = nand_data();
i++;
addr++;
} col = ;
} /* 7. 取消选中 */
nand_deselect();
} void nand_addr_byte(unsigned char addr)
{
volatile int i;
NFADDR = addr;
for(i=; i<; i++);
} int nand_erase(unsigned int addr, unsigned int len)
{
int page = addr / ; if (addr & (0x1FFFF))
{
puts("nand_erase err, addr is not block align\n\r");
return ;
} if (len & (0x1FFFF))
{
puts("nand_erase err, len is not block align\n\r");
return ;
} nand_select(); while ()
{
page = addr / ; nand_cmd(0x60);
/* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>) & 0xff);
nand_addr_byte((page>>) & 0xff);
nand_cmd(0xD0);
nand_wait_ready(); len -= (*);
if (len == )
break;
addr += (*);
} nand_deselect();
return ;
} void nand_write(unsigned int addr, unsigned char *buf, unsigned int len)
{
int page = addr / ;
int col = addr & ( - );
int i = ; nand_select(); while ()
{
nand_cmd(0x80); nand_addr(addr); /* 发出数据 */
for (; (col < ) && (i < len); )
{
nand_w_data(buf[i++]);
}
nand_cmd(0x10);
nand_wait_ready(); if (i == len)
break;
else
{
/* 开始下一个循环page */
col = ;
page++;
} } nand_deselect();
} #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) /*
* 初始化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
UFCON0 = 0x00; // 不使用FIFO
UMCON0 = 0x00; // 不使用流控
UBRDIV0 = UART_BRD; // 波特率为115200
} /*
* 发送一个字符
*/
void putc(unsigned char c)
{
/* 等待,直到发送缓冲区中的数据已经全部发送出去 */
while (!(UTRSTAT0 & TXD0READY)); /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
UTXH0 = c;
} void puts(char *str)
{
int i = ;
while (str[i])
{
putc(str[i]);
i++;
}
} void puthex(unsigned int val)
{
/* 0x1234abcd */
int i;
int j; puts("0x"); for (i = ; i < ; i++)
{
j = (val >> ((-i)*)) & 0xf;
if ((j >= ) && (j <= ))
putc('' + j);
else
putc('A' + j - 0xa); } }

start.S

    a、 初始化硬件:关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH
    b、如果bootloader比较大,要把它重定位到SDRAM
    c、把内核从NAND FLASH读到SDRAM
   e、设置"要传给内核的参数"
 
#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
#define MEM_CTL_BASE 0x48000000 .text
.global _start
_start: /* 1. 关看门狗 */
ldr r0, =0x53000000
mov r1, #
str r1, [r0] /* 配置GPF4为输出引脚
* 把0x100写到地址0x56000050
*/
ldr r1, =0x56000050
ldr r0, =0x1500 /* mov r0, #0x100 */
str r0, [r1]
/* 设置GPF4输出高电平
* 把0写到地址0x56000054
*/
ldr r1, =0x56000054
ldr r0, = /* mov r0, #0 */
str r0, [r1]
/* 2. 设置时钟 */
ldr r0, =0x4c000014
// mov r1, #0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8
str r1, [r0] /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
mrc p15, , r1, c1, c0, /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
mcr p15, , r1, c1, c0, /* 写入控制寄存器 */ /* MPLLCON = S3C2440_MPLL_400MHZ */
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0] /* 启动ICACHE */
mrc p15, , r0, c1, c0, @ read control reg
orr r0, r0, #(<<)
mcr p15, , r0, c1, c0, @ write it back /* 3. 初始化SDRAM */
ldr r0, =MEM_CTL_BASE
adr r1, sdram_config /* sdram_config的当前地址 */
add r3, r0, #(*)
:
ldr r2, [r1], #
str r2, [r0], #
cmp r0, r3
bne 1b /* 4. 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 */
ldr sp, =0x34000000 bl nand_init mov r0, #
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 sdram_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

boot.c

实现把rtthread从nandflash读到SDRAM

extern void uart0_init(void);
extern void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
extern void puts(char *str);
extern void puthex(unsigned int val);
extern void led_on(void);
extern void led_off(void); int strlen(char *str)
{
int i = ;
while (str[i])
{
i++;
}
return i;
} void strcpy(char *dest, char *src)
{
while ((*dest++ = *src++) != '\0');
} int main(void)
{
void (*theKernel)( unsigned int params);
unsigned int *p = 0x30000000;
/* 0. 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口 */
uart0_init(); /* 1. 从NAND FLASH里把内核读入内存 */
puts("Copy kernel from nand\n\r");
nand_read(0x0, (unsigned char *)0x30000000, 0x100000);
puts("\n\r");
led_off(); /* 3. 跳转执行 */
puts("Boot rtthread\n\r");
theKernel = (void (*)(unsigned int))0x30000000;
theKernel(0x30000000);
puts("Error!\n\r");
/* 如果一切正常, 不会执行到这里 */ return -;
}

boot.lds

链接脚本

SECTIONS {
. = 0x33f80000;
.text : { *(.text) } . = ALIGN();
.rodata : {*(.rodata*)} . = ALIGN();
.data : { *(.data) } . = ALIGN();
__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 init.o boot.o boot.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

rtthread移植到jz2440之BootLoader的更多相关文章

  1. RT-Thread移植到stm32

    一.移植RT-Thread准备 RT-Thread源码 源码版本和下载方式,可以参考RT-Thread移植入门学习. keil软件 STM32工程项目模板 因为每一厂家提供的库文件可能有一些区别,在移 ...

  2. Linux内核移植到JZ2440

    一.准备工作:1.Linux内核:Linux2.6.22.6,可从www.kernel.org上下载:2.交叉工具编译链:arm-linux-gcc-3.4.5-glibc-2.3.6:3.yaffs ...

  3. 高通平台MSM8916LCM模块移植(一)-bootloader部分

    此次移植打算分成两个模块来说,bootloader部分和kernel部分.在实际的移植调试过程中也是这么分成了两个部分分别调试. 高通平台中的bootloader叫做LK(Little Kernel, ...

  4. 高通平台MSM8916LCM模块移植(一)-bootloader部分【转】

    本文转载自:http://www.mobile-open.com/2016/970947.html 高通平台中的bootloader叫做LK(Little Kernel,对于LCM来说LK部分相当重要 ...

  5. RT-Thread移植入门学习

    一.简介 RT-Thread 是一款主要由中国开源社区主导开发的开源实时操作系统(许可证GPLv2).实时线程操作系统不仅仅是一个单一的实时操作系统内核,它也是一个完整的应用系统,包含了实时.嵌入式系 ...

  6. 【转】U-boot分析与移植(1)----bootloader分析

    原文网址:http://blog.csdn.net/jianchi88/article/details/7061089  一.Boot Loader 概念 就是在操作系统内核运行之前运行的一段小程序. ...

  7. U-boot分析与移植(1)----bootloader分析

    一.Boot Loader 概念 就是在操作系统内核运行之前运行的一段小程序.通过这段小程序,我们可以初始化硬件设备.建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作 ...

  8. Linux学习 :移植U-boot_2016.09到JZ2440开发板

    一.下载源码:ftp://ftp.denx.de/pub/u-boot/ 二.初始化编译: ①新建一个单板: cd board/samsung/ cp smdk2410 smdk2440 -rf   ...

  9. Linux学习 :移植U-boot_2012.04.01到JZ2440开发板

    一.下载U-boot源码:ftp://ftp.denx.de/pub/u-boot/ 二.uboot的启动过程: 部分硬件初始化——>加载完整uboot到RAM——>跳转到第二阶段入口开始 ...

随机推荐

  1. Android MVP开发模式及Retrofit + RxJava封装

    代码已上传到Github,因为接口都是模拟无法进行测试,明白大概的逻辑就行了! 欢迎浏览我的博客--https://pushy.site 1. MVP模式 1.1 介绍 如果熟悉MVP模式架构的话,对 ...

  2. Android UI组件----用相对布局RelativeLayout做一个登陆界面

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  3. MATLAB filter2/conv2 函数在 Python 语言中的等价函数

    MATLAB filter2 和 conv2 函数说明 在 MATLAB 中,filter2 函数实现二维数字滤波器.conv2 函数实现二维卷积. filter2(H, X, mode) 等价于 c ...

  4. leetCode题解单链表反转

    1.题目描述 反转一个单链表.链表节点结构如下: struct ListNode { int val; ListNode* next; }; 2.问题分析 特殊情况是输入的头结点是一个空的,或者只有一 ...

  5. SQL Server ->> 条件筛选做法之 -- IN(VALUE1,VALUE2,...)与INNER JOIN STRING_SPLIT()性能对比

    在以逗号拼接而成的字符串,传入给IN字句的元素字符串中包涵了1400多个元素 两种做法分别为 AND e.ssPfCityId IN ( SELECT CAST(value AS INT) FROM ...

  6. 一次存储链路抖动因I/O timeout不同在AIX和HPUX上的不同表现(转)

    去年一个故障案例经过时间的沉淀问题没在发生今天有时间简单的总结一下,当时正时午睡时分,突然告警4库8个实例同时不可用,这么大面积的故障多数是有共性的关连,当时查看数据库DB ALERT日志都是I/O错 ...

  7. 定制二选一按钮SwitchButton

    定制二选一按钮SwitchButton 效果: 源码: SwitchButton.h 与 SwitchButton.m // // SwitchButton.h // KongJian // // C ...

  8. Linux查看系统当前字符集

    常用的命令展示 参考当前环境的字符集 方法一: cat /etc/sysconfig/i18n [ssh客户端工具最好也是utf-8,保持一致] 方法二:echo $LANG 设置当前环境的字符集 方 ...

  9. 铁乐学python_day23_面向对象进阶1_反射

    铁乐学python_day23_面向对象进阶1_反射 以下内容大部分摘自博客http://www.cnblogs.com/Eva-J/ isinstance()和issubclass() 两者的返回值 ...

  10. Mysql--通俗易懂的左连接、右连接、内连接

    刚开始看书的时候花了好长时间理解 先通俗易懂的描述下: left join(左联接): 返回包括左表中的所有记录和右表中联结字段相等的记录. right join(右联接): 返回包括右表中的所有记录 ...