• Nand Flash 裸机程序


    硬件平台 :JZ2440

    实现功能:初始化 Nand Flash 和 sdram,并将代码从 Nand Flash 拷贝到 sdram。

    start.s      --> 上电初始化 nand 与sdram

    nand.c     -->  Nand Flash 初始化函数

    sdram.c   --> sdram 初始化函数

    leds.c      -->  led 闪烁

    start.s 源码:

    .text
    .global _start
    _start:
            ldr sp,=4096
            bl  disable_watch_dog
            bl  sdram_init
            bl  nand_init
            ldr r0,=0x30000000
            mov r1,#4096
            mov r2,#2048
            bl  nand_read
            ldr sp,=0x34000000
            ldr lr,=loop1
            ldr pc,=0x30000000
    loop1: 
          b loop1

    nand.c 源码:

    #define BUSY          1
    
    #define NAND_SECTOR_SIZE_LP    2048
    #define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)
    
    typedef struct 
    {
        int   NFCONF;
        int   NFCONT;
        int   NFCMD;
        int   NFADDR;
        int   NFDATA;
        int   NFMECCD0;
        int   NFMECCD1;
        int   NFSECCD;
        int   NFSTAT;
        int   NFESTAT0;
        int   NFESTAT1;
        int   NFMECC0;
        int   NFMECC1;
        int   NFSECC;
        int   NFSBLK;
        int   NFEBLK;
    } S3C2440_NAND;
    
    static S3C2440_NAND *s3c2440nand = (S3C2440_NAND *)0x4e000000;
    
    /* 供外部调用的函数 */
    void nand_init(void);
    void nand_read(unsigned char *buf, unsigned long start_addr, int size);
    
    /* S3C2440的NAND Flash处理函数 */
    static void nand_reset(void);
    static void wait_idle(void);
    static void nand_select_chip(void);
    static void nand_deselect_chip(void);
    static void write_cmd(int cmd);
    static void write_addr(unsigned int addr);
    static unsigned char read_data(void);
    
    
    /* 复位 */
    static void nand_reset(void)
    {
        nand_select_chip();
        write_cmd(0xff);  // 复位命令
        wait_idle();
        nand_deselect_chip();
    }
    
    /* 等待NAND Flash就绪 */
    static void wait_idle(void)
    {
        int i;
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
        while(!(*p & BUSY))
            for(i=0; i<10; i++);
    }
    
    /* 发出片选信号 */
    static void nand_select_chip(void)
    {
        int i;
        s3c2440nand->NFCONT &= ~(1<<1);
        for(i=0; i<10; i++);    
    }
    
    /* 取消片选信号 */
    static void nand_deselect_chip(void)
    {
        s3c2440nand->NFCONT |= (1<<1);
    }
    
    /* 发出命令 */
    static void write_cmd(int cmd)
    {
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
        *p = cmd;
    }
    
    /* 发出地址 */
    static void write_addr(unsigned int addr)
    {
        int i;
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
        int col, page;
    
        col = addr & NAND_BLOCK_MASK_LP;
        page = addr / NAND_SECTOR_SIZE_LP;
        
        *p = col & 0xff;            /* Column Address A0~A7 */
        for(i=0; i<10; i++);        
        *p = (col >> 8) & 0x0f;     /* Column Address A8~A11 */
        for(i=0; i<10; i++);
        *p = page & 0xff;            /* Row Address A12~A19 */
        for(i=0; i<10; i++);
        *p = (page >> 8) & 0xff;    /* Row Address A20~A27 */
        for(i=0; i<10; i++);
        *p = (page >> 16) & 0x03;    /* Row Address A28~A29 */
        for(i=0; i<10; i++);
    }
    
    /* 读取数据 */
    static unsigned char read_data(void)
    {
        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
        return *p;
    }
    
    
    /* 初始化NAND Flash */
    void nand_init(void)
    {
            #define TACLS   0
            #define TWRPH0  3
            #define TWRPH1  0   
    
            
            /* 设置时序 */
            s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
            /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
            s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0); 
            /* 复位NAND Flash */
            nand_reset();
    }
    
    
    /* 读函数 */
    void nand_read(unsigned char *buf, unsigned long start_addr, int size)
    {
        int i, j;
        if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP))
        {
            return ;    /* 地址或长度不对齐 */
        }
        /* 选中芯片 */
        nand_select_chip();
        for(i=start_addr; i < (start_addr + size);) 
        {
          /* 发出READ0命令 */
          write_cmd(0);
          /* Write Address */
          write_addr(i);
          write_cmd(0x30);        
          wait_idle();
          for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) //一页2k
          {
             *buf = read_data();
              buf++;
          }
        }
        /* 取消片选信号 */
        nand_deselect_chip();
        return ;
    }

    sdram.c 源码:

    void disable_watch_dog(void)
    {
        (*(unsigned long *)0x53000000)=0;
    }
    
    void sdram_init(void)
    {
        unsigned long p[]={    0x22011110,
                            0x00000700,
                            0x00000700,
                            0x00000700,
                            0x00000700,
                            0x00000700,
                            0x00000700,
                            0x00018005,
                            0x00018005,
                            0x008c07a3,
                            0x000000b1,
                            0x00000030,
                            0x00000030 };
        unsigned long *sdram_base=(unsigned long *)0x48000000;
        int i=0;
        for(;i<13;i++) sdram_base[i]=p[i];
    }

    leds.c 源码:

    #define    GPFCON        (*(volatile unsigned long *)0x56000050)
    #define    GPFDAT        (*(volatile unsigned long *)0x56000054)
    
    #define    GPF4_out    (1<<(4*2))
    #define    GPF5_out    (1<<(5*2))
    #define    GPF6_out    (1<<(6*2))
    
    void  wait(volatile unsigned long dly)
    {
        for(; dly > 0; dly--);
    }
    
    int main(void)
    {
        unsigned long i = 0;
    
        GPFCON = GPF4_out|GPF5_out|GPF6_out;        // 将LED1-3对应的GPF4/5/6三个引脚设为输出
    
        while(1){
            wait(80000);
            GPFDAT = (~(i<<4));         // 根据i的值,点亮LED1-3
            if(++i == 8)
                i = 0;
        }
    
        return 0;
    }

    链接脚本 nand.lds:

    SECTIONS
    {
     first  0x00000000 :{start.o sdram.o nand.o}
    seconed 0x30000000 :AT(4096) {leds.o}
    }

    编译的Makefile:

    objs:=start.o sdram.o nand.o leds.o
    
    nand.bin:$(objs)
        arm-linux-ld -Tnand.lds -o nand_elf $^
        arm-linux-objcopy -O binary -S nand_elf $@
        arm-linux-objdump -D -m arm nand_elf > nand.dis
    %.o:%.c
        arm-linux-gcc -o $@ -c $<
    %.o:%.S
        arm-linux-gcc -o $@ -c $<
    
    clean:
        rm *.o *.bin *.dis nand_elf
  • 相关阅读:
    Qt QLineEdit、QCombox、QCompleter 实现模糊搜索
    Windows CMD命令大全
    Excel后缀.xls和.xlsx有什么区别
    Qt 3D入门(二)
    Qt 3D入门(一)
    用C语言给NI公司数据采集卡编程序进行电压数据采集
    用C语言给NI数据采集卡编程序实现多路数据的同时采集
    Qt 蓝牙库基础
    Qt 类库模块划分详解
    Qt Modbus通信(RTU模式)
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10407887.html
Copyright © 2020-2023  润新知