历史上的今天
返回首页

历史上的今天

今天是:2024年10月11日(星期五)

正在发生

2018年10月11日 | OK6410裸机之NAND Flash操作更新固件

2018-10-11 来源:eefocus

start.S源码:

.globl _start

_start:

// 硬件相关的设置 

    // Peri port setup 

    ldr r0, =0x70000000

    orr r0, r0, #0x13

    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)

    

// 关看门狗 

    // 往WTCON(0x7E004000)写0   

    ldr r0, =0x7E004000

    mov r1, #0

    str r1, [r0]

    

    // 设置栈 

    ldr sp, =8*1024

    // 设置时钟 

    bl clock_init

    // 设置DDR 

    bl ddr_init

    

// 重定位 

    //把片内内存中程序的代码段、数据段复制到它的链接地址去   

    adr r0, _start          // 获得_start指令当前所在的地址 : 0

    ldr r1, =_start        // _start的链接地址 0x51000000 

    

    ldr r2, =bss_start   // bss段的起始链接地址 

    

    sub r2, r2, r1

    

    cmp r0,r1

    beq clean_bss

    

    bl copy2ddr

    cmp r0, #0

    bne halt

        

// 清BSS 

    // 把BSS段对应的内存清零 

clean_bss:

    ldr r0, =bss_start

    ldr r1, =bss_end

    mov r3, #0

    cmp r0, r1

    beq on_ddr

clean_loop:

    str r3, [r0], #4

    cmp r0, r1    

    bne clean_loop        

on_ddr:

    ldr pc, =main

halt:

    b halt    

==================================================================

clock.S源码:

.globl clock_init

clock_init:

    

    // 1.设置LOCK_TIME 

    ldr r0, =0x7E00F000  // APLL_LOCK 

    ldr r1, =0x0000FFFF

    str r1, [r0]

    

    str r1, [r0, #4]     // MPLL_LOCK 

    str r1, [r0, #8]     // EPLL_LOCK     

    

#define OTHERS        0x7e00f900

    @ set async mode  // 当CPU时钟 != HCLK时,要设为异步模式 

    ldr r0, =OTHERS

    ldr r1, [r0]

    bic r1, #0xc0            

    str r1, [r0]

loop1:                        // 等待,直到CPU进入异步模式 

    ldr r0, =OTHERS

    ldr r1, [r0]

    and r1, #0xf00                    

    cmp r1, #0

    bne loop1        

    

    // SYNC667 

    // MISC_CON[19] = 0 

#define ARM_RATIO    0     // ARMCLK = DOUTAPLL / (ARM_RATIO + 1)    

#define HCLKX2_RATIO 1   // HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) 

#define HCLK_RATIO   1     // HCLK = HCLKX2 / (HCLK_RATIO + 1)       

#define PCLK_RATIO   3      // PCLK   = HCLKX2 / (PCLK_RATIO + 1)     

#define MPLL_RATIO   0     // DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)     

    ldr r0, =0x7E00F020         // CLK_DIV0 

    ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12)

    str r1, [r0]

    

    // 2.配置时钟 

    // 2.1 配置APLL 

    // 2.1.1 设置APLL

    // 2.1.2 MUXAPLL

    // 2.1.3 SYNC667

    // 2.1.4 DIVAPLL

     

#define APLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))

    ldr r0, =0x7E00F00C

    ldr r1, =APLL_CON_VAL

    str r1, [r0]        // APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  

    

    // 2.2 配置MPLL 

    // 2.2.1 设置MPLL

    // 2.2.2 MUXMPLL

    // 2.2.3 SYNCMUX

    // 2.2.4 SYNC667

    // 2.2.5 HCLKX2_RATIO

    // 2.2.6 PCLK_RATIO

     

#define MPLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))

    ldr r0, =0x7E00F010

    ldr r1, =MPLL_CON_VAL

    str r1, [r0]        // MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  

    

    // 3.选择PLL的输出作为时钟源 

    ldr r0, =0x7E00F01C

    ldr r1, =0x03

    str r1, [r0]

    

    mov pc, lr

    

===================================================================

sdram.c源码:

#include "common.h"

#define MEMCCMD        0x7e001004

#define P1REFRESH        0x7e001010

#define P1CASLAT          0x7e001014

#define MEM_SYS_CFG   0x7e00f120

#define P1MEMCFG        0x7e00100c

#define P1T_DQSS          0x7e001018

#define P1T_MRD           0x7e00101c

#define P1T_RAS             0x7e001020

#define P1T_RC               0x7e001024

#define P1T_RCD            0x7e001028

#define P1T_RFC             0x7e00102c

#define P1T_RP               0x7e001030

#define P1T_RRD            0x7e001034

#define P1T_WR              0x7e001038

#define P1T_WTR            0x7e00103c

#define P1T_XP               0x7e001040

#define P1T_XSR             0x7e001044

#define P1T_ESR              0x7e001048

#define P1MEMCFG2      0X7e00104c

#define P1_chip_0_cfg     0x7e001200

#define P1MEMSTAT      0x7e001000

#define P1MEMCCMD    0x7e001004

#define P1DIRECTCMD   0x7e001008

    

#define HCLK    133000000

#define nstoclk(ns)    (ns/( 1000000000/HCLK)+1)

int ddr_init( void )

{

    // tell dramc to configure                

    set_val( MEMCCMD, 0x4 );

    // set refresh period    

    set_val( P1REFRESH, nstoclk(7800) );

    // set timing para        

    set_val( P1CASLAT, ( 3 << 1 ) );  

    set_val( P1T_DQSS, 0x1 );    // 0.75 - 1.25

    set_val( P1T_MRD, 0x2 );

    set_val( P1T_RAS, nstoclk(45) );

    set_val( P1T_RC, nstoclk(68) );        

    u32 trcd = nstoclk( 23 );

    set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );

    u32 trfc = nstoclk( 80 );

    set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );   

    u32 trp = nstoclk( 23 );

    set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) ); 

    set_val( P1T_RRD, nstoclk(15) );

    set_val( P1T_WR, nstoclk(15) );

    set_val( P1T_WTR, 0x7 );

    set_val( P1T_XP, 0x2 );

    set_val( P1T_XSR, nstoclk(120) );

    set_val( P1T_ESR, nstoclk(120) );

    

    // set mem cfg 

    set_nbit( P1MEMCFG, 0, 3, 0x2 );  // 10 column address 

    // set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val 

    

    set_nbit( P1MEMCFG, 3, 3, 0x2 );  // 13 row address 

    set_zero( P1MEMCFG, 6 );              // A10/AP 

    set_nbit( P1MEMCFG, 15, 3, 0x2 ); // Burst 4 

    

    set_nbit( P1MEMCFG2, 0, 4, 0x5 );

    set_2bit( P1MEMCFG2, 6, 0x1 );     // 32 bit 

    set_nbit( P1MEMCFG2, 8, 3, 0x3 ); // Mobile DDR SDRAM 

    set_2bit( P1MEMCFG2, 11, 0x1 );

    set_one( P1_chip_0_cfg, 16 );         // Bank-Row-Column organization 

    // memory init

    set_val( P1DIRECTCMD, 0xc0000 );  // NOP

    set_val( P1DIRECTCMD, 0x000 );      // precharge

    set_val( P1DIRECTCMD, 0x40000 );  // auto refresh

    set_val( P1DIRECTCMD, 0x40000 );  // auto refresh

    set_val( P1DIRECTCMD, 0xa0000 );  // EMRS

    set_val( P1DIRECTCMD, 0x80032 );  // MRS

    set_val( MEM_SYS_CFG, 0x0 );

                    

    // set dramc to "go" status    

    set_val( P1MEMCCMD, 0x000 );

    // wait ready

    while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));

}

===================================================================

nand.c源码:

#define MEM_SYS_CFG     (*((volatile unsigned long *)0x7E00F120))

#define NFCONF               (*((volatile unsigned long *)0x70200000))

#define NFCONT               (*((volatile unsigned long *)0x70200004))

#define NFCMMD            (*((volatile unsigned long *)0x70200008))

#define NFADDR             (*((volatile unsigned long *)0x7020000C))

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

#define NFSTAT              (*((volatile unsigned long *)0x70200028))

void nand_select(void)

{

    NFCONT &= ~(1<<1);

}

void nand_deselect(void)

{

    NFCONT |= (1<<1);

}

void nand_cmd(unsigned char cmd)

{

    NFCMMD = cmd;

}

void nand_addr(unsigned char addr)

{

    NFADDR = addr;

}

unsigned char nand_get_data(void)

{

    return NFDATA;

}

void nand_send_data(unsigned char data)

{

    NFDATA = data;

}

void wait_ready(void)

{

    while ((NFSTAT & 0x1) == 0);

}

void nand_reset(void)

{

    // 选中 

    nand_select();

    

    // 发出0xff命令 

    nand_cmd(0xff);

    // 等待就绪 

    wait_ready();

    

    // 取消选中 

    nand_deselect();

}

void nand_init(void)

{

#if 1                         //经测试可以用

#define TACLS        7

#define TWRPH0    7

#define TWRPH1    7

    NFCONF &= ~((7<<4) | (7<<8) | (7<<12) | (1<<30));

    NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4));

    // 使能nand flash controller 

    NFCONT |= 1;

    NFCONT &= ~(1<<16);

    

    nand_reset();

#else

    // 让xm0csn2用作nand flash cs0 片选引脚 

    MEM_SYS_CFG &= ~(1<<1);

    // 设置时间参数 

#define TACLS     0

#define TWRPH0    1

#define TWRPH1    0

    NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4));

    NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4));

    // 使能nand flash controller 

    NFCONT |= 1;

    NFCONT &= ~(1<<16); // 森止soft lock 

    nand_reset();

#endif

}

void nand_send_addr(unsigned int addr)

{

#if 0    

    unsigned int page = addr / 2048;

    // 这两个地址表示从页内哪里开始 

    nand_addr(addr & 0xff);

    nand_addr((addr >> 8) & 0xff);

    // 下面三个地址表示哪一页 

    nand_addr(page & 0xff);

    nand_addr((page >> 8) & 0xff);

    nand_addr((page >> 16) & 0xff);

#elif 0

    nand_addr(addr & 0xff);              // a0~a7 

    nand_addr((addr >> 8) & 0x7);   // 程序的角度: a8~a10 

    nand_addr((addr >> 11) & 0xff); // 程序的角度: a11~a18 

    nand_addr((addr >> 19) & 0xff); // 程序的角度: a19~a26 

    nand_addr((addr >> 27) & 0xff); // 程序的角度: a27~    

#elif 1                   //经测试可以用

    nand_addr(addr & 0xff);               // a0~a7 

    nand_addr((addr >> 8) & 0x7);    // 程序的角度: a8~a11 

    nand_addr((addr >> 12) & 0xff);  // 程序的角度: a12~a19 

    nand_addr((addr >> 20) & 0xff);  // 程序的角度: a20~a27 

    nand_addr((addr >> 28) & 0x01); // 程序的角度: a28~    

#endif

}

//单板的nand flash Page Size : (4K + 218(OOB))Byte

int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len)

{

    unsigned int addr = nand_start;

    int i = nand_start % 4096;

    int count = 0;

    unsigned char *dest = (unsigned char *)ddr_start;

    

    // 选中芯片 

    nand_select();

    while (count < len)

    {

        // 发出命令0x00 

        nand_cmd(0x00);

        // 发出地址 

        nand_send_addr(addr);

        // 发出命令0x30 

        nand_cmd(0x30);

        // 等待就绪 

        wait_ready();

        // 读数据 

        for (; i < 4096 && count < len; i++)

        {

            dest[count++] = nand_get_data();

            addr++;

        }

        i = 0;            

    }

    // 取消片选 

    nand_deselect();

    return 0;

}

//对nand flash来说是一块一块的擦除,一块是512K + 27.25K(OOB区)Byte

int nand_erase_block(unsigned long addr)

{

    int page = addr / 4096;

    

    nand_select();

    nand_cmd(0x60);

    

    nand_addr(page & 0xff);

    nand_addr((page >> 8) & 0xff);

    nand_addr((page >> 16) & 0xff);

    nand_cmd(0xd0);

    wait_ready();

    nand_deselect();

}

//烧写的时候是一页一页的烧写4K+218(OOB区),Page Program : (4K + 218)Byte

int nand_write(unsigned int nand_start, unsigned char * buf, unsigned int len)

{

    unsigned long count = 0;

    unsigned long addr  = nand_start;

    int i = nand_start % 4096;

    

    nand_select();

    while (count < len)

    {

        nand_cmd(0x80);

        nand_send_addr(addr);

        for (; i < 4096&& count < len; i++)

        {

            nand_send_data(buf[count++]);

            addr++;

        }

        nand_cmd(0x10);

        wait_ready();

        i = 0;        

    }

    nand_deselect();

}

int copy2ddr(unsigned int nand_start, unsigned int ddr_start, unsigned int len)

{

    int ret;

    

    // 初始化nand flash controller 

    nand_init();

    

    // 读nand flash 

    ret = nand_read(nand_start, ddr_start, len);

    

    return ret;

}

====================================================================

main.c源码:

#include "uart.h"

#include "types.h"

void nand_read_test(void)

{

    int i;

    char buf[100];

    unsigned long addr;

    unsigned long size;

    

    printf("enter the start address: ");

    scanf("%s", buf);

    addr = strtoul(buf, NULL, 0);

    printf("read addr = 0x%x\n\r", addr);

    printf("enter the size: ");

    scanf("%s", buf);

    size = strtoul(buf, NULL, 0);

    if (size > 100)

    {

        printf("the max size is 100\n\r");

        size = 100;

    }

    nand_read(addr, buf, size);

    printf("datas: \n\r");

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

    {

        printf("x ", buf[i]);

        if ((i+1) % 16 == 0)

        {

            printf("\n\r");

        }

    }

    printf("\n\r");

}

void nand_erase_test(void)

{

    char buf[100];

    unsigned long addr;

    

    printf("enter the start address: ");

    scanf("%s", buf);

    addr = strtoul(buf, NULL, 0);

    printf("erase addr = 0x%x\n\r", addr);

    nand_erase_block(addr);

}

void nand_write_test(void)

{

    char buf[100];

    unsigned long addr;

    unsigned long size;

    

    printf("enter the start address: ");

    scanf("%s", buf);

    addr = strtoul(buf, NULL, 0);

    printf("enter the string: ");

    scanf("%s", buf);

    size = strlen(buf) + 1;

    nand_write(addr, buf, size);

}

void update_program(void)

{

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

    unsigned long len = 0;

    int have_begin = 0;

    int nodata_time = 0;

    unsigned char c;

    // 读串口获得数据 

    printf("\n\ruse gtkterm to send file\n\r", len);

    while (1)

    {

        if (getc_nowait(&buf[len]) == 0)

        {

            have_begin = 1;

            nodata_time = 0;

            len++;

        }

        else

        {

            if (have_begin)

            {

                nodata_time++;

            }            

        }

        if (nodata_time == 1000)

        {

            break;

        }

    }

    printf("have get %d bytes data\n\r", len);

    printf("press y to program: ");

    c = getc();

    if (c == 'y' || c == 'Y')

    {    

        // 烧写到nand flash block 0 

        nand_erase_block(0);

        nand_write(0, buf, len);

        

        printf("update program successful\n\r");

    }

    else

    {

        printf("update program cancel\n\r");

    }

}

void run_program(void)

{

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

    unsigned long len = 0;

    int have_begin = 0;

    int nodata_time = 0;

    void (*theProgram)(void);

    // 读串口获得数据 

    printf("\n\ruse gtkterm to send file\n\r", len);

    while (1)

    {

        if (getc_nowait(&buf[len]) == 0)

        {

            have_begin = 1;

            nodata_time = 0;

            len++;

        }

        else

        {

            if (have_begin)

            {

                nodata_time++;

            }            

        }

        if (nodata_time == 1000)

        {

            break;

        }

    }

    printf("have get %d bytes data\n\r", len);

    printf("jump to 0x52000000 to run it\n\r");

    

    theProgram = (void (*)(void))0x52000000;

    theProgram();        

}

int main()

{

    char c;

    

    init_uart();

    printf("can update program with serial port\n\r");

    while (1)

    {

#if 1        

        printf("[w] write the nand flash\n\r");

        printf("[r] read the nand flash\n\r");

        printf("[e] erase the nand flash\n\r");

        printf("[g] get file, and write to nand flash 0 block\n\r");

        printf("[x] get file to ddr(0x52000000), run it\n\r");

#else

        printf("[w] \n\r");

        printf("[r] \n\r");

        printf("[e] \n\r");

        printf("[g] \n\r");

        printf("[x] \n\r");

#endif        

        do {

            c = getc();

            if (c == '\n' || c == '\r')

            {

                printf("\n\r");

            }

            else

            {

                putc(c);

            }

        } while (c == '\n' || c == '\r');

        

        switch (c)

        {

            case 'w':

            case 'W':

            {

                nand_write_test();

                break;

            }

            case 'r':

            case 'R':

            {

                nand_read_test();

                break;

            }

            case 'e':

            case 'E':

            {

                nand_erase_test();

                break;

            }

            case 'g':

            case 'G':

            {

                update_program();

                break;

            }

            case 'x':

            case 'X':

            {

                run_program();

                break;

            }

        }

    }

    return 0;

}

====================================================================

Makefile文件:

CC      = arm-linux-gcc

LD      = arm-linux-ld

AR      = arm-linux-ar

OBJCOPY = arm-linux-objcopy

OBJDUMP = arm-linux-objdump

INCLUDEDIR     := $(shell pwd)/include

CFLAGS         := -Wall -O2 -fno-builtin-printf 

CPPFLAGS       := -nostdinc -I$(INCLUDEDIR)

export     CC AR LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS 

objs := start.o clock.o sdram.o nand.o main.o uart.o lib/libc.a

uart.bin: $(objs)

    ${LD} -Tuart.lds -o uart.elf $^

    ${OBJCOPY} -O binary -S uart.elf $@

    ${OBJDUMP} -D uart.elf > uart.dis

.PHONY : lib/libc.a

lib/libc.a:

    cd lib; make; cd ..

    

%.o:%.c

    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%.o:%.S

    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

clean:

    make  clean -C lib

    rm -f uart.bin uart.elf uart.dis *.o

    

====================================================================

uart.lds文件:

SECTIONS {

    . = 0x51000000;

    

    .text : {

            start.o

            clock.o

            sdram.o

            nand.o

            * (.text)

    }

    .rodata : {

            * (.rodata)

    }

    .data : {

            * (.data)

    }

    bss_start = .;

    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }

    bss_end = .;

}

====================================================================

1. 从硬件上认识NAND FLASH:

a. 原理图上只有data0~data7

   那么地址线、数据线肯定是复用的

b. nand flash K9F2G08容量为256M x 8 bit,   OK6410使用的是2G x 8 bit

   它的地址位应该有28位,原理图上只有data0~data7,

   所以需要发出多次地址信号

c. nand flash不能像内存一样直接读写,

   要先发出命令、再发地址、再读写数据

d. CLE = 1, data0~data7上传输的是命令

   ALE = 1, data0~data7上传输的是地址

   CLE/ALE都是0, data0~data7上传输的是数据, nWE = 0, 表示写; 

怎么操作呢:

                                      nand flash    /   s3c6410

1. 发出片选信号:             nCE                   CSn2_NAND/xm0csn[2]

2. 发出命令:         

   先把数据驱动到DATA0~7   

   让"命令锁存信号"输出1       CLE             FCLE

   让"写使能信号"从0变为1    nWE             FWEn       

对于6410,把命令写到NFCMD寄存器

3. 发出地址:         

   先把A0~A7驱动到DATA0~7   

   让"地址锁存信号"输出1       ALE             FALE

   让"写使能信号"从0变为1    nWE             FWEn       

对于6410,把地址写到NFADDR寄存器

   再把A8~A11,驱动到DATA0~3, DATA4~7为0   

   让"地址锁存信号"输出1       ALE             FALE

   让"写使能信号"从0变为1    nWE             FWEn       

对于6410,把地址写到NFADDR寄存器

   再把A12~A19,驱动到DATA0~7   

   让"地址锁存信号"输出1       ALE             FALE

   让"写使能信号"从0变为1    nWE             FWEn         

对于6410,把地址写到NFADDR寄存器

   再把A20~A27,驱动到DATA0~7   

   让"地址锁存信号"输出1       ALE             FALE

   让"写使能信号"从0变为1    nWE             FWEn         

对于6410,把地址写到NFADDR寄存器

   再把A28,驱动到DATA0, DATA1~7为0   

   让"地址锁存信号"输出1       ALE             FALE

   让"写使能信号"从0变为1    nWE             FWEn            

对于6410,把地址写到NFADDR寄存器

4. 发出数据

   先把数据驱动到DATA0~7   

   让"命令锁存信号"输出0       CLE             FCLE

   让"地址锁存信号"输出0       ALE             FALE

   让"写使能信号"从0变为1    nWE             FWEn       

对于6410,把数据写到NFDATA寄存器

5. 读数据

   让nRE输出0                 nRE             FREn

   等待tREA

   nand flash数据驱动到DATA0~7   

   6410就可以读入数据       

对于6410,读NFDATA寄存器

用openjtag来体验nand flash的操作:

1. 读ID:

a. 初始化

   设置MEM_SYS_CFG[1] = 0(0x7E00_F120), 让xm0csn[2]用作nand flash的片选信号

   mdw 0x7E00F120

   mww 0x7E00F120   0

   

   时间参数设置

   mww 0x70200000 0x8000777e

   

b. 发出使能信号

   NFCONT(0x70200004) [0]  = 1    // 使能nand flash控制器 

   NFCONT(0x70200004) [1]  = 0    // 让xm0csn[2]输出0 

   NFCONT(0x70200004) [16] = 0   // soft lock 

   

   mdw 0x70200004                        // 0x100c6

   mww 0x70200004  0xc5

   

c. 发出读ID命令

   复位:把0xff写到NFCMMD(0x70200008)

   把0x90写到NFCMMD(0x70200008)

   

   mwb 0x70200008 0xff

   mwb 0x70200008 0x90

   

d. 发出地址0

   把0写到NFADDR(0x7020000C)   

   mwb 0x7020000C 0

   

e. 读数据

   读NFDATA(0x70200010) 

   mdb 0x70200010

2. 读内容:

a. 初始化

   mww 0x7E00F120   0                   // 把xm0csn[2]配置为nand flash的片选信号 

   mww 0x70200000 0x8000777e   // 设置时间参数

b. 发出片选信号

   mww 0x70200004  0xc5

c. 发出复位信号

   mwb 0x70200008 0xff

d. 发出读命令

   mwb 0x70200008 0

e. 发出地址

   mwb 0x7020000C 0

   mwb 0x7020000C 0

   mwb 0x7020000C 0

   mwb 0x7020000C 0

   mwb 0x7020000C 0

f. 发出0x30命令

   mwb 0x70200008 0x30

g. 读数据

   mdb 0x70200010   

3. 擦除

a. 初始化

   mww 0x7E00F120   0                   // 把xm0csn[2]配置为nand flash的片选信号

   mww 0x70200000 0x8000777e   // 设置时间参数

b. 选中

   mww 0x70200004  0xc5

c. 发出命令0x60

   mwb 0x70200008 0x60

d. 发出地址

   mwb 0x7020000C 64

   mwb 0x7020000C 0

   mwb 0x7020000C 0

e. 发出命令0xd0

   mwb 0x70200008 0xd0

4. 写入"abcd"

a. 初始化

   mww 0x7E00F120   0                   // 把xm0csn[2]配置为nand flash的片选信号 

   mww 0x70200000 0x8000777e   // 设置时间参数 

b. 选中

   mww 0x70200004  0xc5

c. 发出命令0x80

   mwb 0x70200008 0x80

d. 发出地址

   mwb 0x7020000C 0

   mwb 0x7020000C 0

   mwb 0x7020000C 0x40

   mwb 0x7020000C 0

   mwb 0x7020000C 0

e. 发出数据

   mwb 0x70200010 0x61

   mwb 0x70200010 0x62

   mwb 0x70200010 0x63

   mwb 0x70200010 0x64

f. 发出命令0x10   

   mwb 0x70200008 0x10

Base + 0x00 R/W 0xX000_100X NFCONF Configuration register

Base + 0x04 R/W 0x0001_00C6 NFCONT Control register

Base + 0x08 R/W 0x0000_0000 NFCMMD Command register

Base + 0x0c R/W 0x0000_0000 NFADDR Address register

Base = 0x7020_0000

linux串口工具gtkterm安装使用:

下载安装:apt-get install gtkterm

运行:       gtkterm

注意:

①对于我们的程序来说的地址不包括OOB部分;但是对于nand flash来说发送地址的第一第二个周期发送的地址范围是页内地址(0~(2048+64-1)),包含这一页的OOB部分。

②s3c6410启动时自动拷贝nand flash前4页的内容到片内内存执行,而且拷贝时只拷每页中的前2KByte好像是为了兼容2k页的 所有copy2ddr函数中不要把所有数据全部照搬过去,只搬每页的前2k到ddr连接起来 ;可以参考“百问网6410第1期Nand flash的问题”修改nand_read函数


推荐阅读

史海拾趣

BITECH公司的发展小趣事

非常抱歉,由于BITECH公司并非我所熟知的特定电子行业公司,我无法直接提供关于其发展的具体故事。同时,要准确描述一个公司的发展故事,需要详细的数据和事实支持,而这些信息通常需要直接从公司本身或相关报道中获取。

然而,我可以尝试构建一个关于电子行业中某家公司发展故事的框架,供您参考。这些故事可能会涉及公司的创新、市场扩张、技术突破、合作伙伴关系以及行业挑战等方面。

故事一:创新引领发展
BITECH公司自创立之初,便以技术创新为核心竞争力。公司研发团队不断推出具有颠覆性的电子产品,如高效能电池、智能传感器等,这些产品在市场上取得了巨大成功。公司通过持续创新,不仅提升了自身品牌影响力,还为整个电子行业的发展做出了重要贡献。

故事二:市场扩张战略
随着产品线的不断丰富和技术的日益成熟,BITECH公司开始实施市场扩张战略。公司积极拓展国内外市场,通过参加国际展会、建立海外销售网络等方式,将产品推向全球。同时,公司还针对不同市场需求,定制个性化产品解决方案,赢得了众多客户的青睐。

故事三:技术突破助力成长
在电子行业竞争激烈的背景下,BITECH公司不断寻求技术突破。公司投入大量研发资源,成功攻克了一系列关键技术难题,如5G通信、人工智能等。这些技术突破不仅提升了公司产品的竞争力,还为公司带来了新的增长点。

故事四:合作伙伴关系共赢
BITECH公司注重与产业链上下游企业的合作,建立了广泛的合作伙伴关系。通过与供应商、客户以及同行业企业的紧密合作,公司实现了资源共享、优势互补,共同推动电子行业的发展。

故事五:应对行业挑战
在电子行业发展过程中,BITECH公司也面临着诸多挑战,如市场竞争加剧、技术更新换代迅速等。然而,公司始终保持敏锐的市场洞察力,及时调整战略方向,通过加强内部管理、提升产品质量、优化服务体系等方式,成功应对了这些挑战,实现了稳健发展。

请注意,以上仅为故事框架,具体内容需要根据实际情况进行填充。如需获取关于BITECH公司或其他电子行业公司的真实发展故事,建议您查阅相关新闻报道、行业分析或公司年报等资料。

固驰(GUERTE)公司的发展小趣事

近年来,固驰电子积极响应时代趋势和市场变化,不断加大技术创新力度。同时,作为REFLEK技术公司(又称Reflek恒昼科技)旗下的品牌,固驰(FlexiShield)还启动了品牌重塑计划,旨在以全新面貌引领行业未来发展方向。Reflek恒昼科技在金属隔热原膜及磁控膜领域拥有深厚的技术积累,其打造的FlexiShield固驰窗膜和漆面保护膜品牌迅速在市场上占据一席之地,进一步丰富了固驰电子的产品线。

Austek Microsystems公司的发展小趣事

随着业务的发展,Austek Microsystems逐渐意识到,单凭自身的力量难以在市场中取得长远的发展。因此,公司开始积极寻求与业内知名企业的合作。通过与这些企业的深入合作,Austek Microsystems不仅获得了更多的技术支持和市场资源,还成功将自身的产品推向了更广阔的市场。

CET Technology公司的发展小趣事

为满足公司业务板块的不断完善和团队的日益壮大,CET Technology深圳总部在2020年迎来了新的里程碑。公司乔迁至位于深圳国际创新谷的甲级写字楼,办公面积扩大近一倍,实现了硬件办公环境的升级。新址位于留仙洞总部基地核心地带,地理位置优越,为公司员工及客户提供更高效的品质体验。此次迁址不仅展现了CET的雄厚实力,也标志着公司迈向了新的发展阶段。

CML公司的发展小趣事

面对日益增长的市场需求,CML开始积极寻求市场扩张的机会。公司通过与各大电子产品制造商建立合作关系,将自己的产品广泛应用于电视、手机、电脑等消费电子产品中。同时,CML还积极开拓新兴市场,如汽车电子、工业控制等领域,不断扩大自己的市场份额。这些策略的实施,使得CML的业绩逐年攀升,公司规模不断壮大。

BK Precision公司的发展小趣事

为了满足全球市场的需求,BK Precision开始实施全球化战略。公司不仅在美国本土设立了多个办事处和研发中心,还在欧洲和亚洲等地建立了分支机构。通过与国际授权分销商的合作,BK Precision成功地将产品推向全球市场,并赢得了众多国际客户的信赖。同时,公司还积极参与国际电子行业的展会和交流活动,提升品牌知名度和影响力。

问答坊 | AI 解惑

恩智浦LPCXpresso之LPC1343开发板申请,成功获得LPC2148之PCB后。

成功获得LPC2148之PCB后,希望有机会接触到LPC1xxx系列。在上次的《lpc2148使用问题探讨:“新版主chenzhufly LPC2000 PCB 大放送”成果研究专用贴》中与论坛的好友们分享与交流了个人的使用经验,同时也附带的表述个人对LPC22xx与LPC21xx使用的不同 ...…

查看全部问答>

怎样在DialogBar放按钮实现copy、paste功能?

程序运行后发现一点击按钮,文本框上选中的文本就失去焦点,于是无法完成copy功能。 点击Toolbar上的按钮不会使文本框失去焦点,这是为什么?…

查看全部问答>

如何编写程序调用TCPMP中的plg文件?

我打算在WinCE 5.0平台下编写一音视频播放器,有哪些比较好的开源程序可以参考? TCPMP如何? 如何在我的程序中直接调用TCPMP已经编译好的plg文件呢? 另外plg文件是不是dll? 多谢!…

查看全部问答>

关于arm9的cache清空问题

arm手册中只有一句汇编MRC p15,0,Rd,c7,c7,0 我的程序是用C++写的,我用了_asm{MRC p15,0,Rd,c7,c7,0}后 便宜提示p15没定义,我想在我的应用程序里清空cache,具体怎么做啊…

查看全部问答>

50分求单片机入门知识

我本来是从事web开发的,但是想想后决定选择单片机,希望大家能给过入门知识…

查看全部问答>

华为上海无限产品线内部招聘

要求: 本科以上学历 精通C语言 了解操作系统原理 工作职责: vxworks BSP及驱动开发 地点: 上海 有意者请将简历发至youthjump@126.com…

查看全部问答>

俺也想玩玩STM32,谁给赞助一块板呢:-)

                                大款的话就赞助个整套,小款的话就赞助个光板也行呀~…

查看全部问答>

有人用过SIM300发送摄像头拍的照片么?我这有点bug

额..现在收短信显示没问题了.发彩信应该是设置的命令延时不够.那个慢慢调试就是了.现在有个大问题.从摄像头读出来的数据.提取了FF D8到FF D9里面放在一个新数组.就丢失了.基本都变成了FF或者00.没什么思路了..这方面以前也没啥经验.望大侠们给点建 ...…

查看全部问答>

求推荐功率分配芯片(power spliter)

将天线下来的射频信号等分成多路。射频范围为800M-1GHz之间哪些公司有这样的芯片?市场比较容易买到的。…

查看全部问答>

AVR atmega128a UART求助贴

今天兴致勃勃的取回了系统版,我这个是最小系统版 啥都不带的 以前从没接触过AVR,买本书看完后打算先编写一个UART程序,发送数据给电脑。 悲剧来了  调试了一下午毫无动静 。 我用的是STUDIO4+winavr   winavr貌似还没有支 ...…

查看全部问答>