zoukankan      html  css  js  c++  java
  • UBoot200903移植笔记(从Nandflash启动一)

    U-Boot-2009-03移植笔记(点亮第一展灯)中,我们初始化好了sdram,点亮了第一盏灯。在本文中,我们将移植好nandflash启动的驱动代码。

    对于S3C2440,有一个steppingston,在CPU上电的时候,由硬件将Nandflash的前4KB代码拷贝到片内的SRAM中,并且内部SRAM被映射到地址0x0,于是我们的代码才能被cpu执行。

    但问题是我们的代码肯定不止4KB,所以我们必须自己写代码,把nandflash中的剩余代码拷贝到内存中,然后让CPU跳转到对应的内存地址执行。

    设置堆栈指针,为C语言准备运行环境

    1         /*设置堆栈*/
    2     ldr sp, DW_STACK_START
    3     mov fp,#0    

    注意第二行引用了DW_STACK_START标号,我们定义在标号_start_armboot后面

    1 _start_armboot:    .word start_armboot
    2 DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

    第二行的STACK_BASE和STACK_SIZE都定义在include/configs/xinna2440.h中

    1 #define STACK_BASE  0x33f00000     //定义堆栈的地址
    2 #define STACK_SIZE  0x8000         //堆栈的长度大小

     设置好了堆栈指针,下面我们只需要初始化好Nandflash之后,就可以读取数据,存到sdram中了。

    初始化NandFlash

    我们在board/xinna2440/文件夹下,增加nand_op.c文件,然后修改board/xinna2440/Makefile,添加对nand_op.c的编译

    1 COBJS        := xinna2440.o flash.o nand_op.o

    编辑board/xinna2440/nand_op.c,添加以下文件,我们的板子上用的是K9F2G08U0A,2KB一页,共64MB大小。  1 /*

      2  * board/samsung/reille2440/nand_read.c
      3  *
      4  * (C) Copyright 2011
      5  * reille <http://blog.csdn.net/reille/> <reille@qq.com>
      6  *
      7  * This program is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU General Public License as
      9  * published by the Free Software Foundation; either version 2 of
     10  * the License, or (at your option) any later version.
     11  *
     12  */
     13 #include <config.h>
     14 #define NF_BASE   0x4E000000  //Nand Flash配置寄存器基地址
     15 #define __REGb(x) (*(volatile unsigned char *)(x))
     16 #define __REGi(x) (*(volatile unsigned int  *)(x))
     17 #if 0
     18 #define NFCONF __REGi(NF_BASE + 0x0 )  //通过偏移量还是得到配置寄存器基地址
     19 #define NFCONT __REGi(NF_BASE + 0x4 )  //通过偏移量得到控制寄存器基地址
     20 #define NFCMD  __REGb(NF_BASE + 0x8 )  //通过偏移量得到指令寄存器基地址
     21 #define NFADDR __REGb(NF_BASE + 0xC )  //通过偏移量得到地址寄存器基地址
     22 #define NFDATA __REGb(NF_BASE + 0x10)  //通过偏移量得到数据寄存器基地址
     23 #define NFSTAT __REGb(NF_BASE + 0x20)  //通过偏移量得到状态寄存器基地址
     24 #endif
     25 
     26 #define NFCONF (*(volatile unsigned int *)(NF_BASE + 0X0))
     27 #define NFCONT (*(volatile unsigned short *)(NF_BASE + 0x4))
     28 #define NFCMD  (*(volatile unsigned short *)(NF_BASE + 0X8))
     29 #define NFADDR (*(volatile unsigned short *)(NF_BASE + 0xc))
     30 #define NFDATA (*(volatile unsigned char *)(NF_BASE + 0x10))
     31 #define NFSTAT (*(volatile unsigned char *)(NF_BASE + 0x20))
     32 
     33 
     34 #define NAND_CHIP_ENABLE  (NFCONT &= ~(1<<1))  //Nand片选使能
     35 #define NAND_CHIP_DISABLE (NFCONT |= (1<<1))   //取消Nand片选
     36 #define NAND_CLEAR_RB     (NFSTAT |= (1<<2));
     37 #define NAND_DETECT_RB    { while(! (NFSTAT&(1<<2)) );}
     38 #define NAND_SECTOR_SIZE 2048
     39 #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
     40 #if 0
     41 #define DEBUGN    printf
     42 #else
     43 #define DEBUGN(x, args ...) {}
     44 #endif
     45 
     46 /* low level nand read function */
     47 #define GPBCON  (*(volatile unsigned long *)0x56000010)
     48 #define GPBDAT  (*(volatile unsigned long *)0x56000014)
     49 
     50 #define GPACON    (*(volatile unsigned long *)0x56000000)
     51 
     52 void nand_wait_ll(void)
     53 {
     54     int k;
     55     while(!(NFSTAT & 1))
     56         for(k = 0; k < 20; k++);
     57     return;
     58 //    NAND_DETECT_RB
     59 }
     60 
     61 void nand_reset_ll(void)
     62 {
     63     NAND_CHIP_ENABLE; //选中Nand片选
     64 //    NAND_CLEAR_RB 
     65     NFCMD = 0xff;
     66     nand_wait_ll();
     67 //    NAND_CLEAR_RB 
     68     NAND_CHIP_DISABLE; //取消片选信号
     69 }
     70 
     71 
     72 unsigned char nand_read_id(unsigned char*mc,unsigned char *dc,unsigned char *pc)
     73 {
     74     int i=0;
     75     unsigned char res;
     76     NAND_CHIP_ENABLE; //选中Nand片选
     77     NFCMD = 0x90;
     78     for(i = 0;i < 100;i++);
     79     NFADDR = 0 & 0xFF;
     80     NFADDR = (0 >> 9) & 0xFF;
     81     NFADDR = (0 >> 17) & 0xFF;
     82     NFADDR = (0 >> 25) & 0xFF;
     83     for(i = 0;i < 100;i++);
     84     nand_wait_ll();
     85     *mc = NFDATA;
     86     *dc = NFDATA;
     87     res = NFDATA;
     88     *pc = NFDATA;
     89     NAND_CHIP_DISABLE; //取消片选信号
     90     return *mc;
     91 }
     92 
     93 void nand_init_ll(void)
     94 {
     95     int TACLS = 3;
     96     int TWRPH0 = 7;
     97     int TWRPH1 = 7;
     98     int i = 0;
     99     //配置gpio
    100 //    GPACON = (GPACON &~(0x3f << 17)) | ( 0x3f << 17);
    101     GPACON = GPACON | (0x3f << 17);
    102     NFCONF = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4) | (0 << 0);
    103 
    104     NFCONT = (0 << 13) | (0 << 12) | ( 0 << 10) | (0 << 9) | (0 << 8) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 1) | (1 << 0);
    105 
    106     nand_reset_ll();
    107 }
    108 
    109 #if 0
    110 int nand_write_ll(void)
    111 {
    112     int i = 0x90000;
    113     unsigned char j = 0;
    114     NAND_CHIP_ENABLE; //选中Nand片选
    115     NFCMD = 0x80;
    116 
    117     NFADDR = 0x00;
    118     NFADDR = 0x00;
    119     NFADDR = i & 0xFF;
    120     NFADDR = (i >> 8) & 0xFF;
    121     NFADDR = (i >> 16) & 0xFF;
    122     for(j = 0; j < 100;j++);
    123 
    124 
    125     NFCMD = 0x10;
    126     nand_wait_ll();
    127 
    128     for(j = 0 ; j < 100; j++)
    129     {
    130         NFDATA = j;
    131     }
    132     NFCMD = 0x10;
    133     nand_wait_ll();
    134 
    135     NAND_CHIP_DISABLE; //取消片选信号
    136     return 0;
    137 }
    138 #endif
    139 
    140 static void write_addr(unsigned int addr)
    141 {
    142     int col,page,i;
    143     col = addr & NAND_BLOCK_MASK;
    144     page = addr & NAND_SECTOR_SIZE;
    145 
    146     NFADDR = col & 0xff;
    147     for(i = 0; i < 10; i++);
    148     NFADDR = (col >> 8) & 0x0f;
    149     for(i = 0; i < 10; i++);
    150 
    151 
    152     NFADDR = page & 0xFF;
    153     for(i = 0; i < 10; i++);
    154     NFADDR = (page >> 8) & 0xFF;
    155     for(i = 0; i < 10; i++);
    156 
    157     NFADDR = (page >> 16) & 0x01;
    158     for(i = 0; i < 10; i++);
    159 }
    160 
    161 static nand_read_page_ll(unsigned char *buf,unsigned long pageaddr)
    162 {
    163     int i = 0;
    164     NAND_CHIP_ENABLE; //选中Nand片选
    165 
    166     //发出READ0指令
    167     NFCMD = 0;
    168 
    169     //对Nand进行寻址
    170     NFADDR = 0x00;
    171     NFADDR = 0x00;
    172     NFADDR = pageaddr & 0xff;
    173     NFADDR = (pageaddr >> 8) & 0xff;
    174     NFADDR = (pageaddr >> 16) & 0xff;
    175 
    176     NFCMD = 0x30;
    177     nand_wait_ll();
    178         
    179     for(i=0; i < NAND_SECTOR_SIZE; i++)
    180         buf[i] = NFDATA;
    181 
    182     NAND_CHIP_DISABLE; //取消片选信号
    183 }
    184 
    185 int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
    186 {
    187     int pageaddr = 0;
    188     for(pageaddr = 0; pageaddr < 100;pageaddr++)
    189     {
    190         nand_read_page_ll(buf,pageaddr);
    191         buf += NAND_SECTOR_SIZE;
    192     }
    193     return 0;
    194 }
    195 

     写好了nand_flash驱动之后,我们在start.S中调用,将u-boot自身,从nandflash读到sdram中。

     1     bl nand_init_ll     /*调用nandflash初始化函数*/
     2 
     3     ldr r0, =TEXT_BASE  /*指定uboot在内存中的地址,这个宏定义在board/xinna2440/config.mk中,默认是0x33f80000*/
     4     mov r1, #0x0  /*从nandflash的0地址读取*/
     5     mov r2, #0x30000  /*读取长度*/
     6 
     7     bl nand_read_ll    /*开始循环读取*/
     8     tst r0, #0x0  /*判断函数返回值*/
     9     beq ok_nand_read
    10 
    11 bad_nand_read:
    12     loop2: b loop2  /*读取出错,死循环*/
    13 
    14 ok_nand_read:
    15     mov r0,#0
    16     ldr r1,=TEXT_BASE
    17     mov r2,#0x400
    18         /*读取成功,以下代码用于校验内存数据和sram中的数据是否一样*/
    19 
    20 go_next:
    21     ldr r3, [r0], #4
    22     ldr r4, [r1], #4
    23     teq r3, r4
    24     bne notmatch
    25     subs r2, r2, #4
    26     beq stack_setup
    27     bne go_next
    28 
    29 notmatch:    /*数据不一致,死循环*/
    30     loop3: b loop3           /* infinite loop */

    至此,我们添加了从nandflash启动u-boot的代码,我们在后面添加一个点灯代码,点亮led1和led2。

    1 loo:
    2     ldr r4,=0x56000010
    3     ldr r5,=( 1 << 10) | (1 << 12)
    4     str r5,[r4]
    5  
    6     ldr r4,=0x56000014
    7     ldr r5,=~(( 1 << 5) | ( 1 << 6))
    8     str r5,[r4]
    9     b loo

     烧到板子跑,发现led1和led2并没有像我们所预期的被点亮,是什么原因呢?下回分解!

    80岁也要写程序
  • 相关阅读:
    html----响应式布局,左侧栏目固定,右侧内容随着屏幕宽度变化而变化
    es6----set map应用场景
    html----实现元素上下左右居中
    html----怎样实现元素的垂直居中
    html----BFC独立渲染区
    js-----new一个对象的过程
    解决ios手机上传竖拍照片旋转90度的问题
    软键盘遮挡问题
    在不同浏览器中,input里面的输入光标大小表现形式却大不相同
    样式兼容开头
  • 原文地址:https://www.cnblogs.com/smartcoder/p/3103683.html
Copyright © 2011-2022 走看看