写一个简单的BootLoader(二)——init.c分析笔记
2016-08-15 22:45
274 查看
这个文件负责完成内核启动前的初始化任务:
1. 初始化SDRAM
2. 初始化UART
3. 初始化Nand Flash
没什么好说的,直接上代码好了。一下代码来自韦东山老师视频中使用的代码。
1. 初始化SDRAM
2. 初始化UART
3. 初始化Nand Flash
没什么好说的,直接上代码好了。一下代码来自韦东山老师视频中使用的代码。
/* 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) #define TXD0READY (1<<2) void nand_read(unsigned int addr, unsigned char *buf, 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 char *src, unsigned char *dest, unsigned int len) { int i = 0; /* 如果是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 = 0; } void nand_init(void) { #define TACLS 0 #define TWRPH0 1 //这个要大于等于15ns,系统使用的HCLK是100MHz #define TWRPH1 0 /* 设置时序 */ NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */ NFCONT = (1<<4)|(1<<1)|(1<<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 nand_wait_ready(void) { while (!(NFSTAT & 1)); } unsigned char nand_data(void) { return NFDATA; } void nand_read(unsigned int addr, unsigned char *buf, unsigned int len) { int col = addr % 2048; int i = 0; /* 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 < 2048) && (i < len); col++) { buf[i] = nand_data(); i++; addr++; } col = 0; } /* 7. 取消选中 */ 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 = 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); } }
相关文章推荐
- 写一个简单的BootLoader(四)——链接文件boot.lds分析笔记
- 写一个简单的BootLoader(一)——Start.S分析笔记
- 写一个简单的BootLoader(三)——boot.c分析笔记
- linux0.11学习笔记-技术铺垫-简单AB任务切换程序(1)-实现一个简单的bootloader
- linux0.11学习笔记-技术铺垫-简单AB任务切换程序(1)-实现一个简单的bootloader
- (Java2D 学习笔记系列) (一)一个简单的图像填充实例及其分析理解
- Linux内核分析 笔记三 构造一个简单的Linux系统MenuOS ——by王玥
- AfxoleInit()的一个错误(oleinit.cpp第54行)的简要分析
- (Java2D 学习笔记系列) (一)一个简单的图像填充实例及其分析理解
- Python源码分析2 - 一个简单的Python程序的执行
- 一个最简单的arm linux bootloader
- 一个简单的ThreadPool分析
- [《网络渗透技术》学习笔记(1)]——Windows平台上一个最简单溢出程序的调试分析--漫步阳光的BLOG
- 一个简单存储过程的性能分析
- 一个.net KeygenMe简单分析
- J2EE学习笔记二:配置一个简单的J2EE测试环境
- 一个简单实用的保护视力的方法(IT人士必看的方法)
- 一个简单例子的设计模式分析
- ACE学习笔记 ----- 一个简单的网页链接提取程序
- 对一个uClinux中的Makefile文件的简单分析(ZT)