历史上的今天
今天是: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函数
上一篇:OK6410裸机之异常处理
史海拾趣
|
恩智浦LPCXpresso之LPC1343开发板申请,成功获得LPC2148之PCB后。 成功获得LPC2148之PCB后,希望有机会接触到LPC1xxx系列。在上次的《lpc2148使用问题探讨:“新版主chenzhufly LPC2000 PCB 大放送”成果研究专用贴》中与论坛的好友们分享与交流了个人的使用经验,同时也附带的表述个人对LPC22xx与LPC21xx使用的不同 ...… 查看全部问答> |
|
怎样在DialogBar放按钮实现copy、paste功能? 程序运行后发现一点击按钮,文本框上选中的文本就失去焦点,于是无法完成copy功能。 点击Toolbar上的按钮不会使文本框失去焦点,这是为什么?… 查看全部问答> |
|
我打算在WinCE 5.0平台下编写一音视频播放器,有哪些比较好的开源程序可以参考? TCPMP如何? 如何在我的程序中直接调用TCPMP已经编译好的plg文件呢? 另外plg文件是不是dll? 多谢!… 查看全部问答> |
|
arm手册中只有一句汇编MRC p15,0,Rd,c7,c7,0 我的程序是用C++写的,我用了_asm{MRC p15,0,Rd,c7,c7,0}后 便宜提示p15没定义,我想在我的应用程序里清空cache,具体怎么做啊… 查看全部问答> |
|
要求: 本科以上学历 精通C语言 了解操作系统原理 工作职责: vxworks BSP及驱动开发 地点: 上海 有意者请将简历发至youthjump@126.com… 查看全部问答> |
|
额..现在收短信显示没问题了.发彩信应该是设置的命令延时不够.那个慢慢调试就是了.现在有个大问题.从摄像头读出来的数据.提取了FF D8到FF D9里面放在一个新数组.就丢失了.基本都变成了FF或者00.没什么思路了..这方面以前也没啥经验.望大侠们给点建 ...… 查看全部问答> |
|
今天兴致勃勃的取回了系统版,我这个是最小系统版 啥都不带的 以前从没接触过AVR,买本书看完后打算先编写一个UART程序,发送数据给电脑。 悲剧来了 调试了一下午毫无动静 。 我用的是STUDIO4+winavr winavr貌似还没有支 ...… 查看全部问答> |




