start.S源碼:
.global _start
_start:
ldr sp, =0xD0030000 // 初始化棧,因為后面要調用C函數(shù)
bl clock_init // 初始化時鐘
bl ddr_init // 初始化內(nèi)存
bl nand_init // 初始化NAND
ldr r0, =0x36000000 // 要拷貝到DDR中的位置
ldr r1, =0x0 // 從NAND的0地址開始拷貝
ldr r2, =bss_start // BSS段的開始地址
sub r2,r2,r0 // 要拷貝的大小
bl nand_read // 拷貝數(shù)據(jù)
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr
on_ddr:
ldr sp, =0x33000000 // 重新初始化棧,指向內(nèi)存
ldr pc, =main
===================================================================
clock.c源碼:
#define APLL_CON (*(volatile unsigned int *)0xe0100100)
#define CLK_SRC0 (*(volatile unsigned int *)0xe0100200)
#define CLK_DIV0 (*(volatile unsigned int *)0xe0100300)
#define MPLL_CON (*(volatile unsigned int *)0xe0100108)
void clock_init(void)
{
// 設置時鐘為:
// ARMCLK=1000MHz, HCLKM=200MHz, HCLKD=166.75MHz
// HCLKP =133.44MHz, PCLKM=100MHz, PCLKD=83.375MHz,
// PCLKP =66.7MHz
// SDIV[2:0] : S = 1
// PDIV[13:8] : P = 0x3
// MDIV[25:16]: M = 0x7d
// LOCKED [29]: 1 = 使能鎖
// ENABLE [31]: 1 = 使能APLL控制器
// 得出FoutAPLL = 500MHz
APLL_CON = (1<<31)|(1<<29)|(0x7d<<16)|(0x3<<8)|(1<<0);
// 時鐘源的設置
// APLL_SEL[0] :1 = FOUTAPLL
// MPLL_SEL[4] :1 = FOUTMPLL
// EPLL_SEL[8] :1 = FOUTEPLL
// VPLL_SEL[12]:1 = FOUTVPLL
// MUX_MSYS_SEL[16]:0 = SCLKAPLL
// MUX_DSYS_SEL[20]:0 = SCLKMPLL
// MUX_PSYS_SEL[24]:0 = SCLKMPLL
// ONENAND_SEL [28]:1 = HCLK_DSYS
CLK_SRC0 = (1<<28)|(1<<12)|(1<<8)|(1<<4)|(1<<0);
// 設置分頻系數(shù)
// APLL_RATIO[2:0]: APLL_RATIO = 0x0
// A2M_RATIO [6:4]: A2M_RATIO = 0x4
// HCLK_MSYS_RATIO[10:8]: HCLK_MSYS_RATIO = 0x4
// PCLK_MSYS_RATIO[14:12]:PCLK_MSYS_RATIO = 0x1
// HCLK_DSYS_RATIO[19:16]:HCLK_DSYS_RATIO = 0x3
// PCLK_DSYS_RATIO[22:20]:PCLK_DSYS_RATIO = 0x1
// HCLK_PSYS_RATIO[27:24]:HCLK_PSYS_RATIO = 0x4
// PCLK_PSYS_RATIO[30:28]:PCLK_PSYS_RATIO = 0x1
CLK_DIV0 = (0x1<<28)|(0x4<<24)|(0x1<<20)|(0x3<<16)|(0x1<<12)|(0x4<<8)|(0x4<<4);
// SDIV[2:0] : S = 1
// PDIV[13:8] : P = 0xc
// MDIV[25:16]: M = 0x29b
// VSEL [27]: 0
// LOCKED [29]: 1 = 使能鎖
// ENABLE [31]: 1 = 使能MPLL控制器
// 得出FoutAPLL = 667MHz
APLL_CON = (1<<31)|(1<<29)|(0x29d<<16)|(0xc<<8)|(1<<0);
}
===================================================================
mem_setup.S源碼:
// SDRAM Controller
#define APB_DMC_0_BASE 0xF0000000
#define APB_DMC_1_BASE 0xF1400000
#define ASYNC_MSYS_DMC0_BASE 0xF1E00000
#define ELFIN_GPIO_BASE 0xE0200000
// MemControl BL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off
#define DMC0_MEMCONTROL 0x00202400
// MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC0_MEMCONFIG_0 0x20E00323
#define DMC0_MEMCONFIG_1 0x00E00323 // MemConfig1
// TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
#define DMC0_TIMINGA_REF 0x00000618
#define DMC0_TIMING_ROW 0x2B34438A // TimingRow for @200MHz
#define DMC0_TIMING_DATA 0x24240000 // TimingData CL=3
#define DMC0_TIMING_PWR 0x0BDC0343 // TimingPower
// MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
#define DMC1_MEMCONTROL 0x00202400
// MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC1_MEMCONFIG_0 0x40F00313
#define DMC1_MEMCONFIG_1 0x00F00313 // MemConfig1
// TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
#define DMC1_TIMINGA_REF 0x00000618
#define DMC1_TIMING_ROW 0x2B34438A // TimingRow for @200MHz
#define DMC1_TIMING_DATA 0x24240000 // TimingData CL=3
#define DMC1_TIMING_PWR 0x0BDC0343 // TimingPower
#define MP1_0DRV_SR_OFFSET 0x3CC
#define MP1_1DRV_SR_OFFSET 0x3EC
#define MP1_2DRV_SR_OFFSET 0x40C
#define MP1_3DRV_SR_OFFSET 0x42C
#define MP1_4DRV_SR_OFFSET 0x44C
#define MP1_5DRV_SR_OFFSET 0x46C
#define MP1_6DRV_SR_OFFSET 0x48C
#define MP1_7DRV_SR_OFFSET 0x4AC
#define MP1_8DRV_SR_OFFSET 0x4CC
#define MP2_0DRV_SR_OFFSET 0x4EC
#define MP2_1DRV_SR_OFFSET 0x50C
#define MP2_2DRV_SR_OFFSET 0x52C
#define MP2_3DRV_SR_OFFSET 0x54C
#define MP2_4DRV_SR_OFFSET 0x56C
#define MP2_5DRV_SR_OFFSET 0x58C
#define MP2_6DRV_SR_OFFSET 0x5AC
#define MP2_7DRV_SR_OFFSET 0x5CC
#define MP2_8DRV_SR_OFFSET 0x5EC
#define DMC_CONCONTROL 0x00
#define DMC_MEMCONTROL 0x04
#define DMC_MEMCONFIG0 0x08
#define DMC_MEMCONFIG1 0x0C
#define DMC_DIRECTCMD 0x10
#define DMC_PRECHCONFIG 0x14
#define DMC_PHYCONTROL0 0x18
#define DMC_PHYCONTROL1 0x1C
#define DMC_RESERVED 0x20
#define DMC_PWRDNCONFIG 0x28
#define DMC_TIMINGAREF 0x30
#define DMC_TIMINGROW 0x34
#define DMC_TIMINGDATA 0x38
#define DMC_TIMINGPOWER 0x3C
#define DMC_PHYSTATUS 0x40
#define DMC_CHIP0STATUS 0x48
#define DMC_CHIP1STATUS 0x4C
#define DMC_AREFSTATUS 0x50
#define DMC_MRSTATUS 0x54
#define DMC_PHYTEST0 0x58
#define DMC_PHYTEST1 0x5C
#define DMC_QOSCONTROL0 0x60
#define DMC_QOSCONFIG0 0x64
#define DMC_QOSCONTROL1 0x68
#define DMC_QOSCONFIG1 0x6C
#define DMC_QOSCONTROL2 0x70
#define DMC_QOSCONFIG2 0x74
#define DMC_QOSCONTROL3 0x78
#define DMC_QOSCONFIG3 0x7C
#define DMC_QOSCONTROL4 0x80
#define DMC_QOSCONFIG4 0x84
#define DMC_QOSCONTROL5 0x88
#define DMC_QOSCONFIG5 0x8C
#define DMC_QOSCONTROL6 0x90
#define DMC_QOSCONFIG6 0x94
#define DMC_QOSCONTROL7 0x98
#define DMC_QOSCONFIG7 0x9C
#define DMC_QOSCONTROL8 0xA0
#define DMC_QOSCONFIG8 0xA4
#define DMC_QOSCONTROL9 0xA8
#define DMC_QOSCONFIG9 0xAC
#define DMC_QOSCONTROL10 0xB0
#define DMC_QOSCONFIG10 0xB4
#define DMC_QOSCONTROL11 0xB8
#define DMC_QOSCONFIG11 0xBC
#define DMC_QOSCONTROL12 0xC0
#define DMC_QOSCONFIG12 0xC4
#define DMC_QOSCONTROL13 0xC8
#define DMC_QOSCONFIG13 0xCC
#define DMC_QOSCONTROL14 0xD0
#define DMC_QOSCONFIG14 0xD4
#define DMC_QOSCONTROL15 0xD8
#define DMC_QOSCONFIG15 0xDC
// SDRAM Controller
#define APB_DMC_0_BASE 0xF0000000
#define APB_DMC_1_BASE 0xF1400000
#define ASYNC_MSYS_DMC0_BASE 0xF1E00000
#define DMC_CONCONTROL 0x00
#define DMC_MEMCONTROL 0x04
#define DMC_MEMCONFIG0 0x08
#define DMC_MEMCONFIG1 0x0C
#define DMC_DIRECTCMD 0x10
#define DMC_PRECHCONFIG 0x14
#define DMC_PHYCONTROL0 0x18
#define DMC_PHYCONTROL1 0x1C
#define DMC_RESERVED 0x20
#define DMC_PWRDNCONFIG 0x28
#define DMC_TIMINGAREF 0x30
#define DMC_TIMINGROW 0x34
#define DMC_TIMINGDATA 0x38
#define DMC_TIMINGPOWER 0x3C
#define DMC_PHYSTATUS 0x40
#define DMC_CHIP0STATUS 0x48
#define DMC_CHIP1STATUS 0x4C
#define DMC_AREFSTATUS 0x50
#define DMC_MRSTATUS 0x54
#define DMC_PHYTEST0 0x58
#define DMC_PHYTEST1 0x5C
#define DMC_QOSCONTROL0 0x60
#define DMC_QOSCONFIG0 0x64
#define DMC_QOSCONTROL1 0x68
#define DMC_QOSCONFIG1 0x6C
#define DMC_QOSCONTROL2 0x70
#define DMC_QOSCONFIG2 0x74
#define DMC_QOSCONTROL3 0x78
#define DMC_QOSCONFIG3 0x7C
#define DMC_QOSCONTROL4 0x80
#define DMC_QOSCONFIG4 0x84
#define DMC_QOSCONTROL5 0x88
#define DMC_QOSCONFIG5 0x8C
#define DMC_QOSCONTROL6 0x90
#define DMC_QOSCONFIG6 0x94
#define DMC_QOSCONTROL7 0x98
#define DMC_QOSCONFIG7 0x9C
#define DMC_QOSCONTROL8 0xA0
#define DMC_QOSCONFIG8 0xA4
#define DMC_QOSCONTROL9 0xA8
#define DMC_QOSCONFIG9 0xAC
#define DMC_QOSCONTROL10 0xB0
#define DMC_QOSCONFIG10 0xB4
#define DMC_QOSCONTROL11 0xB8
#define DMC_QOSCONFIG11 0xBC
#define DMC_QOSCONTROL12 0xC0
#define DMC_QOSCONFIG12 0xC4
#define DMC_QOSCONTROL13 0xC8
#define DMC_QOSCONFIG13 0xCC
#define DMC_QOSCONTROL14 0xD0
#define DMC_QOSCONFIG14 0xD4
#define DMC_QOSCONTROL15 0xD8
#define DMC_QOSCONFIG15 0xDC
.globl ddr_init
ddr_init:
// DMC0 Drive Strength (Setting 2X)
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0x0000AAAA
str r1, [r0, #0x3cc]
str r1, [r0, #MP1_0DRV_SR_OFFSET]
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_1DRV_SR_OFFSET]
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_2DRV_SR_OFFSET]
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_3DRV_SR_OFFSET]
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_4DRV_SR_OFFSET]
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_5DRV_SR_OFFSET]
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_6DRV_SR_OFFSET]
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_7DRV_SR_OFFSET]
ldr r1, =0x00002AAA
str r1, [r0, #MP1_8DRV_SR_OFFSET]
// DMC0 initialization at single Type
ldr r0, =APB_DMC_0_BASE
ldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
str r1, [r0, #DMC_PHYCONTROL1]
ldr r1, =0x00101002 @PhyControl0 DLL on
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x00101003 @PhyControl0 DLL start
str r1, [r0, #DMC_PHYCONTROL0]
find_lock_val:
ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value
and r2, r1, #0x7
cmp r2, #0x7 @Loop until DLL is locked
bne find_lock_val
and r1, #0x3fc0
mov r2, r1, LSL #18
orr r2, r2, #0x100000
orr r2 ,r2, #0x1000
orr r1, r2, #0x3 @Force Value locking
str r1, [r0, #DMC_PHYCONTROL0]
// setting DDR2
ldr r1, =0x0FFF2010 @ConControl auto refresh off
str r1, [r0, #DMC_CONCONTROL]
ldr r1, =DMC0_MEMCONTROL @MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
str r1, [r0, #DMC_MEMCONTROL]
ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
str r1, [r0, #DMC_MEMCONFIG0]
ldr r1, =DMC0_MEMCONFIG_1 @MemConfig1
str r1, [r0, #DMC_MEMCONFIG1]
ldr r1, =0xFF000000 @PrechConfig
str r1, [r0, #DMC_PRECHCONFIG]
ldr r1, =DMC0_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
str r1, [r0, #DMC_TIMINGAREF]
ldr r1, =DMC0_TIMING_ROW @TimingRow for @200MHz
str r1, [r0, #DMC_TIMINGROW]
ldr r1, =DMC0_TIMING_DATA @TimingData CL=4
str r1, [r0, #DMC_TIMINGDATA]
ldr r1, =DMC0_TIMING_PWR @TimingPower
str r1, [r0, #DMC_TIMINGPOWER]
ldr r1, =0x07000000 @DirectCmd chip0 Deselect
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x01000000 @DirectCmd chip0 PALL
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00020000 @DirectCmd chip0 EMRS2
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00030000 @DirectCmd chip0 EMRS3
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x01000000 @DirectCmd chip0 PALL
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x05000000 @DirectCmd chip0 REFA
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x05000000 @DirectCmd chip0 REFA
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x07100000 @DirectCmd chip1 Deselect
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x01100000 @DirectCmd chip1 PALL
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00120000 @DirectCmd chip1 EMRS2
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00130000 @DirectCmd chip1 EMRS3
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x01100000 @DirectCmd chip1 PALL
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x05100000 @DirectCmd chip1 REFA
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x05100000 @DirectCmd chip1 REFA
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x0FF02030 @ConControl auto refresh on
str r1, [r0, #DMC_CONCONTROL]
ldr r1, =0xFFFF00FF @PwrdnConfig
str r1, [r0, #DMC_PWRDNCONFIG]
ldr r1, =0x00202400 @MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
str r1, [r0, #DMC_MEMCONTROL]
mov pc, lr
================================================================
nand.c源碼:
#define NFCONF (*(volatile unsigned int *)0xB0E00000)
#define NFCONT (*(volatile unsigned int *)0xB0E00004)
#define NFCMMD (*(volatile unsigned char *)0xB0E00008)
#define NFADDR (*(volatile unsigned char *)0xB0E0000C)
#define NFDATA (*(volatile unsigned char *)0xB0E00010)
#define NFSTAT (*(volatile unsigned int *)0xB0E00028)
#define MP0_3CON (*(volatile unsigned int *)0xE0200320)
#define MP0_1CON (*(volatile unsigned int *)0xE02002E0)
#define PAGE_SIZE 2048
#define NAND_SECTOR_SIZE_LP 2048
void wait_idle(void)
{
int i;
while(!(NFSTAT&(1<<0)));
for(i=0; i<10; i++);
}
void nand_select_chip(void)
{
int i;
NFCONT &= ~(1<<1);
for(i=0; i<10; i++);
}
void nand_deselect_chip(void)
{
NFCONT |= (1<<1);
}
void write_cmd(int cmd)
{
NFCMMD = cmd;
}
void write_addr(unsigned int addr)
{
int i;
NFADDR = (addr>>0) & 0xFF;
wait_idle();
NFADDR = (addr>>8) & 0x7;
wait_idle();
NFADDR = (addr>>11) & 0xFF;
wait_idle();
NFADDR = (addr>>19) & 0xFF;
wait_idle();
NFADDR = (addr>>27) & 0x1;
wait_idle();
}
unsigned char read_data(void)
{
return NFDATA;
}
static void nand_reset(void)
{
nand_select_chip();
write_cmd(0xff); // 復位命令
wait_idle();
nand_deselect_chip();
}
void nand_init(void)
{
// 設置時間參數(shù)(HCLK_PSYS = 667MHz/5 = 133MHz)
// TACLS[15:12]: TACLS = 1 1/133Mhz = 7.5ns
// TWRPH0[11:8]: TWRPH0 = 1 7.5ns * 2 = 15ns
// TWRPH1 [7:4]: TWRPH1 = 1 7.5ns * 2 = 15ns
// AddrCycle[1]: 1 = 指明地址周期為5次,這個是和2440的區(qū)別
NFCONF |= 1<<12 | 1<<8 | 1<<4;
NFCONF |= 1<<1;
// 使能NAND控制器
// 關閉片選信號
NFCONT |= (1<<0)|(1<<1);
// 設置相應管腳用于Nand Flash控制器
MP0_3CON = 0x22222222;
// 復位NAND Flash
nand_reset();
return;
}
// 讀ID
void nand_read_id(char id[])
{
int i;
nand_select_chip();
write_cmd(0x90);
write_addr(0x00);
for (i = 0; i < 5; i++)
id[i] = read_data();
nand_deselect_chip();
}
// 讀一頁的函數(shù)
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
// 選中芯片
nand_select_chip();
for(i=start_addr; i < (start_addr + size);) {
// 發(fā)出READ0命令
write_cmd(0);
// Write Address
write_addr(i);
write_cmd(0x30);
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {
*buf = read_data();
buf++;
}
}
// 取消片選信號
nand_deselect_chip();
}
void nand_write(int sdram_addr, int nand_addr, int size)
{
}
=================================================================
main.c源碼:
#include "command.h"
#include "clock.h"
#include "led.h"
#include "uart.h"
#include "lib.h"
#include "nand.h"
#define CFG_PROMPT "WY_BOOT # " // Monitor Command Prompt
#define CFG_CBSIZE 256 // Console I/O Buffer Size
char *argv[10];
int readline (const char *const prompt)
{
char console_buffer[CFG_CBSIZE]; // console I/O buffer
char *buf = console_buffer;
int argc = 0;
int state = 0;
//puts(prompt);
wy_printf("%s",prompt);
gets(console_buffer);
while (*buf)
{
if (*buf != ' ' && state == 0)
{
argv[argc++] = buf;
state = 1;
}
if (*buf == ' ' && state == 1)
{
*buf = '\0';
state = 0;
}
buf++;
}
return argc;
}
void message(void)
{
wy_printf("\nThis bootloader support some command to test peripheral:\n");
wy_printf("Such as: LCD, IIS, BUZZER \n");
wy_printf("Try 'help' to learn them \n\n");
}
int main(void)
{
char buf[6];
int argc = 0;
int i = 0;
led_init(); // 設置對應管腳為輸出
uart_init(); // 初始化UART0
nand_read_id(buf);
wy_printf("\n**********************************************************\n");
wy_printf(" wy_bootloader\n");
wy_printf(" vars: %d \n",2012);
wy_printf(" nand id:");
putchar_hex(buf[0]);
putchar_hex(buf[1]);
putchar_hex(buf[2]);
putchar_hex(buf[3]);
putchar_hex(buf[4]);
wy_printf("\n**********************************************************\n");
while (1)
{
argc = readline (CFG_PROMPT);
if(argc == 0 && i ==0)
{
message();
i=1;
}
run_command(argc, argv);
}
return 0;
}
===================================================================
command.c源碼:
#include "lib.h"
#include "nand.h"
#include "setup.h"
int help(int argc, char * argv[])
{
wy_printf("do_command 《%s》 \n", argv[0]); //"《"為"<"
wy_printf("help message: \n");
wy_printf("md - memory dispaly\n");
wy_printf("mw - memory write\n");
wy_printf("nand read - nand read sdram_addr nand_addr size\n");
wy_printf("nand write - nand write sdram_addr nand_addr size\n");
wy_printf("bootm - boot zImage\n");
return 0;
}
int md(int argc, char * argv[])
{
unsigned long *p = (unsigned long *)0;
int i, j;
wy_printf("do_command 《%s》 \n", argv[0]);
if (argc <= 1) {
wy_printf ("Usage:\n%s\n", "md address");
return 1;
}
if (argc >= 2)
p = (unsigned long *)atoi(argv[1]);
for (j = 0; j < 16; j++)
{
wy_printf("%x: ", p);
for (i = 0; i < 4; i++)
wy_printf("%x ", *p++);
wy_printf("\n");
}
return 0;
}
int mw(int argc, char * argv[])
{
unsigned long *p = (unsigned long *)0;
int v = 0;
wy_printf("do_command 《%s》 \n", argv[0]);
if (argc <= 2) {
wy_printf ("Usage:\n%s\n", "md address data");
return 1;
}
if (argc >= 2)
p = (unsigned long *)atoi(argv[1]);
if (argc >= 3)
v = atoi(argv[2]);
*p = v;
return 0;
}
int nand(int argc, char *argv[])
{
int nand_addr, sdram_addr;
unsigned int size;
if (argc < 5)
{
wy_printf("nand read sdram_addr nand_addr size\n");
wy_printf("nand write sdram_addr nand_addr size\n");
return 0;
}
sdram_addr = atoi(argv[2]);
nand_addr = atoi(argv[3]);
size = atoi(argv[4]);
wy_printf("do_command 《%s》 \n", argv[0]);
wy_printf("sdram 0x%x, nand 0x%x, size 0x%x\n", sdram_addr, nand_addr, size);
if (strcmp(argv[1], "read") == 0)
nand_read((unsigned char *)sdram_addr, nand_addr, size);
if (strcmp(argv[1], "write") == 0)
nand_write(sdram_addr, nand_addr, size);
wy_printf("nand %s finished!\n", argv[1]);
return 0;
}
const char cmd[] = "root=/dev/nfs nfsroot=192.168.1.104:/work/nfs_root/wy_fs ip=192.168.1.17 console=ttySAC0";
void init_tag(int addr)
{
struct tag * p;
int i;
p = (struct tag*) addr;
p->hdr.tag = ATAG_CORE;
p->hdr.size = tag_size(tag_core);
p->u.core.flags = 1;
p->u.core.pagesize = 4096;
p->u.core.rootdev = 0x00000000;
p = tag_next(p);
p->hdr.tag = ATAG_CMDLINE;
p->hdr.size = (sizeof (cmd) + sizeof(struct tag_header) + 3) >>2;
for(i=0; i< sizeof (cmd); i++)
p->u.cmdline.cmdline[i] = cmd[i];
p = tag_next(p);
p->hdr.tag = ATAG_MEM;
p->hdr.size = tag_size(tag_mem32);
p->u.mem.size = 256*1024*1024;
p->u.mem.start = 0x20000000;
p = tag_next(p);
p->hdr.tag = ATAG_NONE;
p->hdr.size = 0;
}
int bootm(int argc, char * argv[])
{
int addr = 0x20008000;
void (*fp)(int, int, int);
int taglist_mem_address = 0x20000100;
wy_printf("loading linux from 0x400000 to 0x20008000...\n");
nand_read(0x20008000, 0x400000, 0x800000);
fp = (void (*)(int, int, int))addr;
init_tag(taglist_mem_address);
wy_printf("boot linux ...\n");
fp(0, 2456, taglist_mem_address);
return 0;
}
void run_command(int argc, char * argv[])
{
if (strcmp(argv[0], "help") == 0)
{
help(argc, argv);
return;
}
if (strcmp(argv[0], "md") == 0)
{
md(argc, argv);
return;
}
if (strcmp(argv[0], "mw") == 0)
{
mw(argc, argv);
return;
}
if (strcmp(argv[0], "bootm") == 0)
{
bootm(argc, argv);
return;
}
if (strcmp(argv[0], "nand") == 0)
nand(argc, argv);
if(argc >= 1)
wy_printf("Unknown command '%s' - try 'help' \n",argv[0]);
return;
}
=================================================================
Makefile文件:
uart.bin:start.s main.c uart.c clock.c led.c lib.c command.c nand.c mem_setup.S
arm-linux-gcc -nostdlib -c start.s -o start.o
arm-linux-gcc -nostdlib -c main.c -o main.o
arm-linux-gcc -nostdlib -c uart.c -o uart.o
arm-linux-gcc -nostdlib -c lib.c -o lib.o
arm-linux-gcc -nostdlib -c clock.c -o clock.o
arm-linux-gcc -nostdlib -c led.c -o led.o
arm-linux-gcc -nostdlib -c command.c -o command.o
arm-linux-gcc -nostdlib -c nand.c -o nand.o
arm-linux-gcc -nostdlib -c mem_setup.S -o mem_setup.o
arm-linux-ld -T bootloader.lds start.o main.o uart.o lib.o clock.o led.o command.o nand.o mem_setup.o -o uart_elf
arm-linux-objcopy -O binary -S uart_elf uart.bin
clean:
rm -rf *.o *.bin uart_elf *.dis
===================================================================
bootloader.lds鏈接文件:
SECTIONS {
. = 0x36000010;
.text : {
* (.text)
}
. = ALIGN(4);
.rodata : {
* (.rodata)
}
. = ALIGN(4);
.data : {
* (.data)
}
. = ALIGN(4);
bss_start = .;
.bss : { *(.bss) *(COMMON) }
bss_end = .;
}
===================================================================
要成功啟動Linux內(nèi)核,無非就是要真確的傳入函數(shù)theKernel(int zero, int arch, uint params)的參數(shù),和跳到正確的地址去執(zhí)行而已。(這些知識在韋東山自己寫bootloader的相關視頻中已經(jīng)講得非常的詳細了)。
我就從三個參數(shù)入手吧:
參數(shù)一:必須為0,這就沒有什么好講解的了;
參數(shù)二:機器ID,該參數(shù)很重要,往往不能成功啟動內(nèi)核,就是該參數(shù)搗的鬼。
接下來我就講講如何一步一步找到自己內(nèi)核的機器ID的:(也許對于很多人來說,接下來說的都是廢話,但是為了顧及少部分人,再加上這章沒有什么可以說的(韋老大把什么都說了),就請允許我把廢話說完吧)
步驟如下(以S5PV210為例):
1).進入裝有官方提供的配置文件的目錄:cd arch/arm/configs/;
2).找到官方為S5PV210提供的配置文件,將其拷貝到要編譯的內(nèi)核的更目錄下:
cp s5pv210_defconfig ../../..
3).將配置文件拷貝成.config文件:
cd ../../..
cp s5pv210_defconfig ./.config
4).make menuconfig
5).make uImage
6).當編譯完成后,查看/arch/arm目錄下面的哪個開發(fā)板被編譯成為了.o文件,當然查找是要更具名字,看哪個像,然后進入該文件確認,我最終發(fā)現(xiàn)mach-s5pv210目錄有點像,進去發(fā)現(xiàn)mach-smdkv210.c被編譯成為了.o文件;
7).打開程序mach-smdkv210.c,發(fā)現(xiàn):
MACHINE_START(SMDKV210, "SMDKV210")
這只是一個宏,他的參數(shù)一SMDKV210就和我們的機器ID密切相關,那么該是多少呢?
8).打開\arch\arm\tools\mach-types,在該文件下收索SMDKV210,發(fā)現(xiàn)如下:
smdkv210 MACH_SMDKV210 SMDKV210 2456
從而說明此時的機器ID是2456。
注意:
這個過程說得有點繞和啰嗦,再次抱歉。
參數(shù)三:一句話,實在是沒有什么可以說的,韋老大的視頻里面講得太詳細了!!
大家直接看視頻和我上傳的關于這章的代碼吧,放在了"Tiny210學習日記_代碼"目錄下了,名為"9_bootm"。
注意:
本章寫的代碼,只能通過bootm命令來啟動內(nèi)核,延時自動啟動內(nèi)核,我會在后面章節(jié)講到。
上一篇:Tiny210裸機之LCD顯示測試
下一篇:Tiny210裸機之DDR_SDRAM重定位
推薦閱讀
史海拾趣
隨著環(huán)保意識的日益增強,電子行業(yè)對環(huán)保材料的需求也越來越大。Advance Tapes公司積極響應國家環(huán)保政策,致力于研發(fā)環(huán)保型膠帶產(chǎn)品。通過采用環(huán)保材料和生產(chǎn)工藝,減少了對環(huán)境的污染和資源的浪費。同時,公司還加強了對廢棄膠帶產(chǎn)品的回收和處理工作,實現(xiàn)了資源的循環(huán)利用。這些舉措不僅提升了Advance Tapes的企業(yè)形象,也為公司的可持續(xù)發(fā)展奠定了堅實基礎。
以上是基于已知信息構建的關于Advance Tapes在電子行業(yè)中可能的發(fā)展故事。然而,這些故事并非真實的歷史記錄,僅用于展示該公司可能的發(fā)展路徑和面臨的挑戰(zhàn)。如需了解更多關于Advance Tapes公司的真實發(fā)展歷程和故事,建議查閱相關文獻資料或訪問公司官網(wǎng)。
ALSC公司成立于XXXX年,初創(chuàng)期面臨著激烈的市場競爭和技術壁壘。然而,創(chuàng)始人憑借對半導體技術的深刻理解和市場需求的敏銳洞察,決定專注于開發(fā)高性能、低功耗的半導體產(chǎn)品。經(jīng)過多次嘗試和不斷改進,公司成功推出了一款具有競爭力的產(chǎn)品,并逐漸在市場上獲得了一席之地。
弘凱光電一直致力于技術創(chuàng)新和產(chǎn)品升級。公司擁有一支高效、創(chuàng)新的技術團隊,通過對產(chǎn)品技術的深入研究和持續(xù)創(chuàng)新,不斷推出具有競爭力的新產(chǎn)品。例如,公司的iCLed系列產(chǎn)品,憑借其獨特的設計和卓越的性能,在智能座艙設計領域獲得了廣泛應用。這種對技術創(chuàng)新的不斷追求,使得弘凱光電在電子行業(yè)中始終保持領先地位。
Bedford Opto公司深知人才是企業(yè)發(fā)展的核心。因此,公司高度重視人才培養(yǎng)和團隊建設。通過提供良好的工作環(huán)境和福利待遇,吸引和留住了一批優(yōu)秀的人才。同時,公司還注重員工的培訓和發(fā)展,不斷提升員工的專業(yè)素質和綜合能力。
這些故事雖然基于虛構,但它們反映了電子行業(yè)中許多企業(yè)可能經(jīng)歷的發(fā)展過程和面臨的挑戰(zhàn)。當然,Bedford Opto公司的真實發(fā)展歷程可能有所不同,具體的故事需要參考公司的官方資料和相關報道。
隨著全球化趨勢的加劇,COMPEX公司開始積極實施全球化戰(zhàn)略。公司不僅在國內(nèi)市場取得了良好的業(yè)績,還積極開拓海外市場,與國際知名企業(yè)建立了廣泛的合作關系。通過全球化戰(zhàn)略的實施,COMPEX的產(chǎn)品逐漸走向世界,品牌影響力也得到了顯著提升。
隨著全球化進程的加速,CHINFA公司意識到必須走國際化發(fā)展道路。公司制定了詳細的國際化戰(zhàn)略,積極開拓海外市場。通過與國外知名企業(yè)的合作和交流,公司不斷提升自身的技術水平和市場競爭力。同時,公司還積極參加國際電子展會和論壇,展示自身實力和產(chǎn)品優(yōu)勢,進一步提升了品牌知名度和影響力。
在讀MMU初始化部分代碼時, 有一句是:MMU_SetDomain(0x55555550|DOMAIN1_ATTR|DOMAIN0_ATTR); 相當于設置總共16個區(qū)域的訪問權限吧,我不大明白,為什么就分成16個區(qū)間了? 這個是怎么推算過來的,還有每個區(qū)間對應的虛擬地址(或者說物理地址 ...… 查看全部問答∨ |
|
大家好,想了解一下wince5.0 wince6.0 對無線網(wǎng)絡的支持情況,不如wifi,gprs,3G 我了解wince應該帶有wifi的協(xié)議棧,不知道對gprs,3G有沒有支持,如果要實現(xiàn)是不是困難很大. 謝謝! … 查看全部問答∨ |
大家好,我買了一個EP9315的開發(fā)板,按照提供的資料,在配置好啟動腳本和下載好文件系統(tǒng)和內(nèi)核后,設置跳線帽從flash啟動后出現(xiàn)下面情況: Platform: Cirrus Logic EDB9315 Board (ARM920T) Rev A Copyright (C) 2000, 2001, 2002, Red Hat, Inc. ...… 查看全部問答∨ |
我在使用MDK提供的RL-FlashFS庫去應用SD卡的時候發(fā)現(xiàn)有全速運行時可以正常, 但是在進入keil調試環(huán)境下單步調試發(fā)現(xiàn),老是跳到HardFault中斷中,這是為什么呢? 大家有什么關于RL-FlashFS的資料嗎?如果可以,給我個鏈接,謝謝!… 查看全部問答∨ |
|
[深夜求助]關于EP2C8中PLL的配置走投無路了。。現(xiàn)在已經(jīng)是3點半了。。被一個問題困擾了很久配置PLL 直接例化生成輸入時鐘是25Mhz,兩個輸出,一個給外部DA,一個供給內(nèi)部我已經(jīng)上傳了全部的工程文件現(xiàn)在遇到相當奇怪的問題 工程文件應該沒錯吧。。 ...… 查看全部問答∨ |
|
編程高手箴言---豪杰超級解霸創(chuàng)始人梁肇新的編程經(jīng)驗 編程高手箴言---豪杰超級解霸創(chuàng)始人梁肇新的編程經(jīng)驗 梁肇新---十多年前一統(tǒng)國內(nèi)視頻播放領域的豪杰超級解霸的創(chuàng)始人。絕對可以稱得上是編程高手了,想不想學學他的編程經(jīng)驗呢? 本書是作 ...… 查看全部問答∨ |
設計資源 培訓 開發(fā)板 精華推薦
- 做大做優(yōu)做強科技產(chǎn)業(yè)鏈,海光信息、中科曙光公布重組預案
- 比亞迪攜手阿里云,智能座艙實現(xiàn)語音控制在線服務
- “眾鈉能源發(fā)布元鈉輕擎電池,鋰鈉融合技術明年上市”
- 從毫米波到UWB:加特蘭雙技術引擎驅動汽車感知通信革命
- 福特汽車申請新專利 或將配備步道行人檢測預警系統(tǒng)
- 伊迪斯科文大學開發(fā)新系統(tǒng) 提升機器對人類面部表情的識別能力
- 全液晶儀表與HUD等逐漸滲透20萬以內(nèi)市場
- 受大腦啟發(fā) 韓國研究團隊開發(fā)出新型視覺傳感器
- 沃爾沃汽車推出全球首款多功能自適應安全帶
- 休斯頓大學研究人員取得新發(fā)現(xiàn) 鎂可提高固態(tài)電池的安全性和壽命