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

    bl ddr_init

    bl init_uart

    

// 清BSS 

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

clean_bss:

    ldr r0, =bss_start

    ldr r1, =bss_end

    mov r3, #0

    cmp r0, r1

    b copy_kernel

clean_loop:

    str r3, [r0], #4

    cmp r0, r1    

    bne clean_loop        

copy_kernel:

    mov r0, #0x200000

    ldr r1, =(0x50008000 - 64)

    mov r2, #0x500000

    bl copykernel2ddr    

    cmp r0, #0

    bne halt

    bl set_params

    mov r0, #0

    ldr r1, =1626

    ldr r2, =0x50000100

    ldr pc, =0x50008000

        

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, 0x3 );   // 14 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));

    return 0;

}

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

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

}

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;

}

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();

    return 0;

}

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();

    return 0;

}

int copykernel2ddr(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;

}

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

params.c源码:

#include "setup.h"

static struct tag *params;

static void setup_start_tag (void)

{

    params = (struct tag *)0x50000100;

    params->hdr.tag = ATAG_CORE;

    params->hdr.size = tag_size (tag_core);

    params->u.core.flags = 0;

    params->u.core.pagesize = 0;

    params->u.core.rootdev = 0;

    params = tag_next (params);

}

static void setup_memory_tags (void)

{

    params->hdr.tag = ATAG_MEM;

    params->hdr.size = tag_size (tag_mem32);

    params->u.mem.start = 0x50000000;

    params->u.mem.size = 256*1024*1024;

    params = tag_next (params);

}

char * strcpy(char * dest,const char *src)

{

    char *tmp = dest;

    

    while ((*dest++ = *src++) != '\0')

    // nothing ;

    return tmp;

}

int strlen(const char * s)

{

    const char *sc;

    

    for (sc = s; *sc != '\0'; ++sc)

    // nothing ;

    

    return sc - s;

}

static void setup_commandline_tag (void)

{

    char *commandline = "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200";

    params->hdr.tag = ATAG_CMDLINE;

    params->hdr.size = (sizeof (struct tag_header) + strlen (commandline) + 1 + 3) >> 2;

    strcpy (params->u.cmdline.cmdline, commandline);

    params = tag_next (params);

}

static void setup_end_tag (void)

{

    params->hdr.tag = ATAG_NONE;

    params->hdr.size = 0;

}

void set_params(void)

{

    setup_start_tag();

    setup_memory_tags();

    setup_commandline_tag();

    setup_end_tag();

}

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

uart.c源码:


#include "s3c6410_regs.h"

//#define ENABLE_FIFO

void init_uart(void)

{

    GPACON &= ~0xff;

    GPACON |= 0x22;

    

    // ULCON0 

    ULCON0 = 0x3;                 // 数据位:8, 无较验, 停止位: 1, 8n1 

    UCON0  = 0x5 | (1<<9);   // 使能UART发送、接收, tx interrupt request type = level 

#ifdef ENABLE_FIFO

    UFCON0 = 0x07 | (1<<6); // FIFO enable, tx fifo trigger level = 16 bytes     

#else

    UFCON0 = 0x00;               // FIFO disable 

#endif

    UMCON0 = 0;

    

    // 波特率 

    // DIV_VAL = (PCLK / (bps x 16 ) ) - 1 

    // bps = 57600

    // DIV_VAL = (66500000 / (115200 x 16 ) ) - 1 

    //         = 35.08

    UBRDIV0   = 35;

    // x/16 = 0.08

    // x = 1

     

    UDIVSLOT0 = 0x1;

}

unsigned char getc(void)

{

#ifdef ENABLE_FIFO

    while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0);

#else    

    while ((UTRSTAT0 & (1<<0)) == 0);

#endif

    return URXH0;

}

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

自己写bootloader启动内核,QT文件系统:

测试:把内核源码放到ubuntu先解压:

tar xzf linux-3.0.1-2012-09-23.tar.gz

cd linux-3.0.1-2012-09-23/

make uImage

会在arch/arm/boot/目录下生成uImage文件

把开发板设为SD卡启动,从SD卡启动后按空格键运行SD卡里的u-boot来烧写文件:

tftp 52000000 boot.bin

nand erase 0 200000

nand write 52000000 0 200000

tftp uImage 52000000

nand erase 200000 500000

nand write 52000000 200000 500000

断电把开发板设为nand flash启动,上电等uboot从nand flash中拷贝内核到DDR中再跳到DDR中运行即可看到内核启动信息,要提前用SD卡把QT文件系统烧写到nand flash中,内核才能挂载文件系统成功。


关键字:bootloader  OK6410 引用地址:自己写bootloader之OK6410

上一篇:OK6410启动自动挂载nfs文件系统
下一篇:OK6410裸机之LCD调色板

推荐阅读

佳能将于2018年10月下旬起正式发售FPD(Flat Panel Display)曝光设备新品,型号为“MPAsp-H1003T”。该产品针对第8代玻璃基板尺寸※1研发,实现了运用2.0μm(L/S※2)的解析度对65英寸液晶面板进行一次曝光的技术。 随着平板电视的普及,今后的电视市场需求方向,将向以65英寸为主的大尺寸、搭载4K和8K技术的高精细化、以及以有机EL面板为代表的获...
一、串行通信的通信方式1.同步通信:带时钟同步信号传输,有一根线是同步时钟。例如SPI(全双功)、IIC(半双工)通信接口2.异步通信:不带时钟同步信号,必须约定好波特率。例如UART(全双功)二、STM32的串口通信接口UART:通用异步收发器。USART:通用同步异步收发器。STM32F10x系列包含3个USART和2个UART。都是TTL电平交叉相连即可与PC机可以使用USB-T...
北京时间下周三凌晨1点(10月14日),苹果将举办线上新品活动,在iPad Air 4和iPad 8已经揭晓的前提下,此次活动的主角将完全落在iPhone 12上。按照德国爆料大神Roland Quandt援引零售商的说法,iPhone 12系列包括四款,颜色与存储配置分别如下:iPhone 12 mini有64GB、128GB和256GB,配色可选绿色、天蓝色、(玫瑰)金色、深空灰色和银色。iPhone...
早前,台积电董事长刘德音接受专访时表示,对于芯片短缺问题,台积电努力用前所未有的方式解决,不过送到工厂的芯片比用于产品多,代表供应链有人囤积芯片!刘德音指出,因车用芯片短缺造成车厂大幅减产,很多车厂指责台积电供应不足,但他们想对车厂说,你是我客户的客户的客户,台积电怎么会「优先考虑其他人」而不给你芯片?为了解决车用芯片短缺,台积...

史海拾趣

问答坊 | AI 解惑

单片机学习

单片机学习应该先学硬件还是软件啊???哪位好大哥知道一下…

查看全部问答∨

嵌入式软件的设计题目.请高手给出出主意.

eeworld的各位高手.我想问问下面这个问题. 我将面临着一个设计课程的学习;我想问下面的哪个设计的题目更简单. A 1) step motor的界面与控制. 2) 摄像头的模块界面 3) FPG-A(可编程门阵列)的界面与程序 4) USB界面 B 引导程序与开发 1) 引 ...…

查看全部问答∨

高分求 在Windows CE下模拟触摸笔在触摸屏固定位置点击功能

   问题: 我在Windows CE下开发,屏幕为触摸屏,在程序中,我需要使用代码来模拟指针在触摸屏上按下此功能,     我以前的做法是先将指针移动到某位置,然后再模拟指针按下消息,代码如下    //利用鼠标模拟消息   ...…

查看全部问答∨

关于arm9 2440的问题(用过S3C2440的请进!)

最近刚学嵌入式,买了一块板回来,什么都不懂,试着下程序,结果用USB下程序时,下到中途,电脑蓝屏了,板子上自带的程序没了!请问大家是我的程序被檫掉了,还是bootloader被檫掉了啊?我的电脑没有并口,真不希望是第二种情况啊!…

查看全部问答∨

寻wince6.0 USB摄像头驱动

请问哪位朋友做过wince6.0 带USB摄像头的产品?能否推荐一下摄像头模组供应商,可以提供wince6驱动的?感谢。…

查看全部问答∨

很多文件打不开!

电脑里面的PBP 文件BIN 文件LO 文件SAV 文件GBA 文件CUP 文件ASP 文件ACV 文件 DDS文件等等都打不开,是不是我不小心删什么什么东西?请大家帮忙想想办法,很急!谢谢叻…

查看全部问答∨

大家的Ulink2都是在哪买的,可否推荐一下

                                 大家的Ulink2都是在哪买的,可否推荐一下…

查看全部问答∨

avr16 1602LCD

#include<iom16.h>#define uchar unsigned char #define uint  unsigned int#define rs1 PORTB|=1#define rs0 PORTB&=~1#define rw1 PORTB|=2#define rw0 PORTB&=~2#define en1 PORTB|=4#define en0 PORTB&=~4 //============== ...…

查看全部问答∨

msp430的BSL下载程序原理及硬件电路设计

&nbsp;本人现在刚接触msp430单片机,其下载方式似乎都要用仿真器实现,除了JTAG下载,还有BSL的方法,而JTAG方法中都要用到仿真器,什么UIF,PIF等,上网查了一下,挺贵的,最近买了一块开发板,上面用的是BSL下载的,但不知道电 ...…

查看全部问答∨

[求助] ARM觀念請教

各位前輩們好,小弟在這裡有幾個問題想要請教大家 1. ARM目前最新的版本是Cortex-M4嗎?新的版本跟舊的版本之間的主要差異是什麼?如果我學新版的ARM,觀念是可以完全套用於舊版的ARM嗎? 2. 在TI的ARM9系統的程式可以不經修改就轉移其他的ARM9系 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved