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裸機之異常處理
下一篇:OK6410裸機之DDR片外內存訪問
推薦閱讀
史海拾趣
在取得初步成功后,Concurrent Logic開始擴展其產品線。他們不僅開發了多款針對不同應用場景的并行處理芯片,還進軍了與并行計算緊密相關的其他硬件領域,如高性能的服務器和存儲設備。這些新產品的研發和上市,進一步增強了公司在市場上的競爭力。
隨著電子技術的不斷發展,EG & G Inc公司不斷進行技術創新和產品升級。公司投入大量資源進行研發,成功推出了一系列具有競爭力的電子產品。其中,某款高精度測量儀器在市場上獲得了廣泛認可,成為了公司的明星產品。此外,公司還積極開拓新的應用領域,將電子技術應用于醫療、環保等多個領域,為公司帶來了新的增長點。
作為一家有社會責任感的企業,成都成電硅海公司始終將社會責任放在首位。公司積極參與各種公益活動和社會捐贈活動,為社會的和諧穩定貢獻自己的力量。同時,公司還注重環保和可持續發展的問題,在生產過程中采用了環保材料和節能技術,努力降低對環境的影響。這種對社會責任的擔當和履行,使得成都成電硅海公司在行業中樹立了良好的企業形象。
請注意,這些故事是虛構的,用于滿足您的信息需求。成都成電硅海公司的真實發展歷程和故事可能與之有所不同。
隨著電子行業的不斷發展和市場需求的日益多樣化,Flextronics(Flexxon Pte Ltd)開始實施多元化戰略,積極拓展新的業務領域。公司不僅繼續深耕消費電子、通信設備等傳統市場,還積極涉足汽車電子、醫療電子、物聯網等新興領域。通過并購、合作等多種方式,Flextronics不斷拓寬產品線和服務范圍,為客戶提供更加全面和專業的解決方案。這一戰略調整不僅為公司帶來了新的增長點,也進一步提升了公司的市場競爭力。
ffmpeg已變成多媒體處理領域最有影響力的開源組件,接近50萬行源代碼的工程對ARM模擬器來說是個巨大的挑戰,但多年的穩定性給了我很大信心。整個過程比較順利,前后大約花2個半小時,包括在ARM開發板上驗證。ffmpeg0.6的移植成 ...… 查看全部問答∨ |
|
微積分電路分析(終級討論)——電工必知20個電路之二四(eeworld 獨家大討論 說明: “ 電子工程師必須掌握的20個電路 ” 在網上誕生了好長時間了,但是確從來沒有人詳細的給出答案或者分析。現在終于有了這個機會讓咱們來個徹底的討論,希望在eeworld的支持下吸引 更多的牛人來參與討論。等咱們全都討論完后,咱們把他 ...… 查看全部問答∨ |
本人特別菜,老師給我一個lm3s811的板子,讓我用matlab模擬一組電壓電流數據,導出到一個文件中,應該是txt文件吧,然后用keil調用這些數據,算出有功無功功率等等,最后再把結果輸出到電腦上。由于這個只是我的任務中小小的一部分,我不可能去深入 ...… 查看全部問答∨ |