历史上的今天
返回首页

历史上的今天

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

正在发生

2018年10月13日 | Tiny210裸机之LCD显示测试

2018-10-13 来源:eefocus

start.S源码:

.global _start 

_start:

    ldr sp, =0xD0030000  // 初始化栈,因为后面要调用C函数 

    bl clock_init                // 初始化时钟 

    bl ddr_init                   // 初始化内存 

    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              // 拷贝数据 

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, =0x3f000000    // 重新初始化栈,指向内存 

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

    

    // 设置分频系数

    // 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

#define DMC0_TIMINGA_REF        0x00000618      // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)

#define DMC0_TIMING_ROW         0x2B34438A      // TimingRow    for @200MHz

#define DMC0_TIMING_DATA        0x24240000      // TimingData   CL=3

#define DMC0_TIMING_PWR         0x0BDC0343      // TimingPower

#define    DMC1_MEMCONTROL        0x00202400    // MemControl    BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off

#define DMC1_MEMCONFIG_0    0x40F00313    // MemConfig0    512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed

#define DMC1_MEMCONFIG_1    0x00F00313    // MemConfig1

#define DMC1_TIMINGA_REF        0x00000618      // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)

#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)

{

    // 设置时间参数(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的区别 

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

}

// 读一页的函数 

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

    {

        // 发出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 "clock.h"

#include "uart.h"

#include "lib.h"

#include "nand.h"

#include "lcd.h"

int main(void)

{

    int i;

    

    uart_init(); // 初始化UART0 

    wy_printf("LCD initialize ...\n");

    lcd_init();

    

    while (1)

    {

        wy_printf("display red\n");

        lcd_clear_screen(0xff0000);

        for(i=50;i>0;i--)

            delay();

        wy_printf("display green\n");

        lcd_clear_screen(0x00ff00);

        for(i=50;i>0;i--)

            delay();

        wy_printf("display blue\n");

        lcd_clear_screen(0x0000ff);

        for(i=50;i>0;i--)

            delay();

        wy_printf("draw rectangle\n");

        Glib_Rectangle(33,33,555,400,0xff0000);

        Glib_Rectangle(55,55,666,422,0x00ff00);

        Glib_Rectangle(77,77,777,444,0xffffff);

        for(i=50;i>0;i--)

            delay();

    }

    return 0;

}

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

lcd.S源码:

#define GPF0CON        (*(volatile unsigned int *)0xE0200120)

#define GPF1CON        (*(volatile unsigned int *)0xE0200140)

#define GPF2CON        (*(volatile unsigned int *)0xE0200160)

#define GPF3CON        (*(volatile unsigned int *)0xE0200180)

#define GPD0CON        (*(volatile unsigned int *)0xE02000A0)

#define GPD0DAT        (*(volatile unsigned int *)0xE02000A4)

#define CLK_SRC1    (*(volatile unsigned int *)0xe0100204)

#define CLK_DIV1    (*(volatile unsigned int *)0xe0100304)

#define DISPLAY_CONTROL    (*(volatile unsigned int *)0xe0107008)

#define VIDCON0        (*(volatile unsigned int *)0xF8000000)

#define VIDCON1        (*(volatile unsigned int *)0xF8000004)

#define VIDTCON2     (*(volatile unsigned int *)0xF8000018)

#define VIDTCON3     (*(volatile unsigned int *)0xF800001c)

#define WINCON0     (*(volatile unsigned int *)0xF8000020)

#define WINCON2     (*(volatile unsigned int *)0xF8000028)

#define SHADOWCON     (*(volatile unsigned int *)0xF8000034)

#define VIDOSD0A     (*(volatile unsigned int *)0xF8000040)

#define VIDOSD0B     (*(volatile unsigned int *)0xF8000044)

#define VIDOSD0C     (*(volatile unsigned int *)0xF8000048)

#define VIDW00ADD0B0     (*(volatile unsigned int *)0xF80000A0)

#define VIDW00ADD1B0     (*(volatile unsigned int *)0xF80000D0)

#define VIDW00ADD2       (*(volatile unsigned int *)0xF8000100)

#define VIDTCON0     (*(volatile unsigned int *)0xF8000010)

#define VIDTCON1     (*(volatile unsigned int *)0xF8000014)

#define VSPW       9  

#define VBPD       13 

#define LINEVAL    479

#define VFPD       21 

#define HSPW       19 

#define HBPD       25 

#define HOZVAL     799

#define HFPD       209

#define LeftTopX     0

#define LeftTopY     0

#define RightBotX   799

#define RightBotY   479

#define SCR_XSIZE_TFT     (800)

#define SCR_YSIZE_TFT     (480)

volatile unsigned long LCD_BUFFER[SCR_YSIZE_TFT][SCR_XSIZE_TFT];

void lcd_init(void)

{

    // 1. 设置相关GPIO引脚用于LCD 

    GPF0CON = 0x22222222;        // GPF0[7:0]

    GPF1CON = 0x22222222;        // GPF1[7:0]

    GPF2CON = 0x22222222;        // GPF2[7:0]

    GPF3CON = 0x22222222;        // GPF3[7:0]

    // 使能LCD本身 

    GPD0CON |= 1<<4;

    GPD0DAT |= 1<<1;

    // 该寄存器是时钟相关

    // Display path selection 

    // 10: RGB=FIMD I80=FIMD ITU=FIMD

    DISPLAY_CONTROL = 2<<0;

    // 2. 初始化210的display controller 

    // 2.1 hsync,vsync,vclk,vden的极性和时间参数

    // 2.2 行数、列数(分辨率),象素颜色的格式

    // 2.3 分配显存(frame buffer),写入display controller

      

    // CLKVAL_F[13:6]:该值需要根据LCD手册做相应的修改

    //                  HCLKD=166.75MHz,DCLK(min) = 20ns(50MHz)

    //                VCLK = 166.75 / (4+1) = 33.35MHz

    // CLKDIR  [4]:1 = Divided by CLKVAL_F

    // ENVID   [1]:1 = Enable the video output and the Display control signal. 

    // ENVID_F [0]:1 = Enable the video output and the Display control signal.  

    VIDCON0 &= ~((3<<26) | (1<<18) | (0xff<<6)  | (1<<2));     // RGB I/F, RGB Parallel format,  

    VIDCON0 |= ((4<<6) | (1<<4) );

    // 设置极性(该值需要根据LCD手册做相应的修改)

    // IVDEN [4]:0 = Normal

    // IVSYNC[5]:1 = Inverted

    // IHSYNC[6]:1 = Inverted

    // IVCLK [7]:0 = Video data is fetched at VCLK falling edge

    VIDCON1 &= ~(1<<7);            // 在vclk的下降沿获取数据 

    VIDCON1 |= ((1<<6) | (1<<5));  // HSYNC极性反转, VSYNC极性反转 

    // 设置时序(需要修改) 

    VIDTCON0 = (VBPD << 16) | (VFPD << 8) | (VSPW << 0);

    VIDTCON1 = (HBPD << 16) | (HFPD << 8) | (HSPW << 0);

    // 设置屏幕的大小

    // LINEVAL[21:11]:多少行   = 480

    // HOZVAL [10:0] :水平大小 = 800

    VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);

    // WSWP_F   [15] :1    = Swap Enable(为什么要使能),很关键的一位,能够解决掉重影问题

    // BPPMODE_F[5:2]:1011 = unpacked 24 BPP (non-palletized R:8-G:8-B:8 )

    // ENWIN_F  [0]:  1    = Enable the video output and the VIDEO control signal.

    WINCON0 &= ~(0xf << 2);

    WINCON0 |= (0xB<<2)|(1<<15);

    // 窗口0,左上角的位置(0,0) 

    // 窗口0,右下角的位置(800,480) 

    VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);

    VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);

    // 大小 

    VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);

    VIDW00ADD0B0 = LCD_BUFFER;

    

    // VBASEL = VBASEU + (LINEWIDTH+OFFSIZE) x (LINEVAL+1) 

    //        = 0 + (800*4 + 0) * 479

    //        = 

    VIDW00ADD1B0 =  (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);

    //VIDW00ADD1B0 = FRAME_BUFFER + HOZVAL * LINEVAL * 4; // 新加的,是该这个吗? 

    SHADOWCON = 0x1; // 使能通道0 

    // LCD控制器开启 

    VIDCON0  |= 0x3; // 开启总控制器 

    WINCON0 |= 1;     // 开启窗口0 

}

// 画一个像素点 

void PutPixel(unsigned long x,unsigned long y, unsigned long c )

{

    if ( (x < SCR_XSIZE_TFT) && (y < SCR_YSIZE_TFT) )

        LCD_BUFFER[(y)][(x)] = c;

}

// 清屏 

void lcd_clear_screen( unsigned long c)

{

    unsigned int x,y ;

        

    for( y = 0 ; y < SCR_YSIZE_TFT ; y++ )

    {

        for( x = 0 ; x < SCR_XSIZE_TFT ; x++ )

        {

            LCD_BUFFER[y][x] = c ;

        }

    }

}

// 用于黄直线:横线和竖线 

void Glib_Line(int x1,int y1,int x2,int y2,int color)

{

    int dx,dy,e;

    dx=x2-x1; 

    dy=y2-y1;

    

    if(dx>=0)

    {

        if(dy >= 0) // dy>=0

        {

            if(dx>=dy) // 1/8 octant

            {

                e=dy-dx/2;

                while(x1<=x2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){y1+=1;e-=dx;}    

                    x1+=1;

                    e+=dy;

                }

            }

            else        // 2/8 octant

            {

                e=dx-dy/2;

                while(y1<=y2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){x1+=1;e-=dy;}    

                    y1+=1;

                    e+=dx;

                }

            }

        }

        else           // dy<0

        {

            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 8/8 octant

            {

                e=dy-dx/2;

                while(x1<=x2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){y1-=1;e-=dx;}    

                    x1+=1;

                    e+=dy;

                }

            }

            else        // 7/8 octant

            {

                e=dx-dy/2;

                while(y1>=y2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){x1+=1;e-=dy;}    

                    y1-=1;

                    e+=dx;

                }

            }

        }    

    }

    else //dx<0

    {

        dx=-dx;        //dx=abs(dx)

        if(dy >= 0) // dy>=0

        {

            if(dx>=dy) // 4/8 octant

            {

                e=dy-dx/2;

                while(x1>=x2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){y1+=1;e-=dx;}    

                    x1-=1;

                    e+=dy;

                }

            }

            else        // 3/8 octant

            {

                e=dx-dy/2;

                while(y1<=y2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){x1-=1;e-=dy;}    

                    y1+=1;

                    e+=dx;

                }

            }

        }

        else           // dy<0

        {

            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 5/8 octant

            {

                e=dy-dx/2;

                while(x1>=x2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){y1-=1;e-=dx;}    

                    x1-=1;

                    e+=dy;

                }

            }

            else        // 6/8 octant

            {

                e=dx-dy/2;

                while(y1>=y2)

                {

                    PutPixel(x1,y1,color);

                    if(e>0){x1-=1;e-=dy;}    

                    y1-=1;

                    e+=dx;

                }

            }

        }    

    }

}

// 用于画方框 

void Glib_Rectangle(int x1,int y1,int x2,int y2,int color)

{

    Glib_Line(x1,y1,x2,y1,color);

    Glib_Line(x2,y1,x2,y2,color);

    Glib_Line(x1,y2,x2,y2,color);

    Glib_Line(x1,y1,x1,y2,color);

}

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

Makefeile文件:

uart.bin:start.s main.c uart.c clock.c lib.c nand.c lcd.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 lcd.c -o lcd.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 lcd.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 = .;

}

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

简单测试源码分析,以下为初始化LCD的代码:

void lcd_init(void)

{

    // 1. 设置相关GPIO引脚用于LCD 

    GPF0CON = 0x22222222;        // GPF0[7:0]

    GPF1CON = 0x22222222;        // GPF1[7:0]

    GPF2CON = 0x22222222;        // GPF2[7:0]

    GPF3CON = 0x22222222;        // GPF3[7:0]

    // 使能LCD本身 

    GPD0CON |= 1<<4;

    GPD0DAT |= 1<<1;

    // 该寄存器是时钟相关

    // Display path selection 

    // 10: RGB=FIMD I80=FIMD ITU=FIMD

     

    DISPLAY_CONTROL = 2<<0;

    // 2. 初始化210的display controller 

    // 2.1 hsync,vsync,vclk,vden的极性和时间参数

    // 2.2 行数、列数(分辨率),象素颜色的格式

    // 2.3 分配显存(frame buffer),写入display controller

     

    // CLKVAL_F[13:6]:该值需要根据LCD手册做相应的修改

    //                  HCLKD=166.75MHz,DCLK(min) = 20ns(50MHz)

    //                VCLK = 166.75 / (4+1) = 33.35MHz

    // CLKDIR  [4]:1 = Divided by CLKVAL_F

    // ENVID   [1]:1 = Enable the video output and the Display control signal. 

    // ENVID_F [0]:1 = Enable the video output and the Display control signal.  

     

    VIDCON0 &= ~((3<<26) | (1<<18) | (0xff<<6)  | (1<<2));     // RGB I/F, RGB Parallel format,  

    VIDCON0 |= ((4<<6) | (1<<4) );

    // 设置极性(该值需要根据LCD手册做相应的修改)

    // IVDEN [4]:0 = Normal

    // IVSYNC[5]:1 = Inverted

    // IHSYNC[6]:1 = Inverted

    // IVCLK [7]:0 = Video data is fetched at VCLK falling edge

     

    VIDCON1 &= ~(1<<7);   // 在vclk的下降沿获取数据 

    VIDCON1 |= ((1<<6) | (1<<5));  // HSYNC极性反转, VSYNC极性反转 

    // 设置时序(需要修改) 

    VIDTCON0 = (VBPD << 16) | (VFPD << 8) | (VSPW << 0);

    VIDTCON1 = (HBPD << 16) | (HFPD << 8) | (HSPW << 0);

    // 设置屏幕的大小

    // LINEVAL[21:11]:多少行   = 480

    // HOZVAL [10:0] :水平大小 = 800

     

    VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);

    // WSWP_F   [15] :1    = Swap Enable(为什么要使能),很关键的一位,能够解决掉重影问题

    // BPPMODE_F[5:2]:1011 = unpacked 24 BPP (non-palletized R:8-G:8-B:8 )

    // ENWIN_F  [0]:  1    = Enable the video output and the VIDEO control signal.

     

    WINCON0 &= ~(0xf << 2);

    WINCON0 |= (0xB<<2)|(1<<15);

    // 窗口0,左上角的位置(0,0) 

    // 窗口0,右下角的位置(800,480) 

    VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);

    VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);

    // 大小 

    VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);

    VIDW00ADD0B0 = FRAME_BUFFER;

    // VBASEL = VBASEU + (LINEWIDTH+OFFSIZE) x (LINEVAL+1) 

    //        = 0 + (800*4 + 0) * 479

    //        = 

     

    VIDW00ADD1B0 =  (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);

    //VIDW00ADD1B0 = FRAME_BUFFER + HOZVAL * LINEVAL * 4; // 新加的,是该这个吗? 

    SHADOWCON = 0x1; // 使能通道0 

    // LCD控制器开启 

    VIDCON0  |= 0x3; // 开启总控制器 

    WINCON0 |= 1;     // 开启窗口0 

}

注意:

1).该程序适用的LCD型号是S70,若为其他型号,请根据自己的LCD手册修改注有要修改字样的地方!!

2).该部分程序放在了"Tiny210学习日记_代码"目录下了,名为"10_lcd",该部分程序只是循环显示红,绿,蓝,画了几个框框而已!!

3).另外一个程序放在了"Tiny210学习日记_代码"目录下了,名为"11_lcd",该部分程序显示一张图片!!

注意:

测试"11_lcd"的程序时,图片需要单独烧写到nand的0xC00000处!!!


推荐阅读

史海拾趣

CUI Inc.公司的发展小趣事

自1989年成立以来,CUI Inc.一直站在电源设计的前沿。公司不断投资于研发,致力于开发出更高效、更环保的电源产品。通过引入先进的电源管理技术和创新的设计方法,CUI成功地帮助客户提高了应用的能效,减少了能源消耗。这种对电源技术的专注和创新,使CUI在竞争激烈的电子行业中脱颖而出,赢得了众多客户的信赖和好评。

Auris公司的发展小趣事

在不断追求技术创新的道路上,Auris公司并未止步。近年来,该公司正在积极研发柔性机器人技术,这种技术有望在治疗喉咙、肺和肠胃疾病方面发挥重要作用。柔性机器人的研发不仅展示了Auris在技术创新方面的持续努力,也为其在未来的医疗市场中抢占先机提供了有力支持。

这五个故事展示了Auris公司在电子行业中的发展历程,从创始人的科技愿景到技术突破获得认可,再到与强生的合作以及柔性机器人的研发,每一步都体现了Auris对于技术创新和市场拓展的不懈追求。这些事实性的故事不仅展现了Auris公司的成长轨迹,也反映了电子行业中技术创新和市场竞争的激烈态势。

Anritsu公司的发展小趣事

在不断追求技术创新的道路上,Auris公司并未止步。近年来,该公司正在积极研发柔性机器人技术,这种技术有望在治疗喉咙、肺和肠胃疾病方面发挥重要作用。柔性机器人的研发不仅展示了Auris在技术创新方面的持续努力,也为其在未来的医疗市场中抢占先机提供了有力支持。

这五个故事展示了Auris公司在电子行业中的发展历程,从创始人的科技愿景到技术突破获得认可,再到与强生的合作以及柔性机器人的研发,每一步都体现了Auris对于技术创新和市场拓展的不懈追求。这些事实性的故事不仅展现了Auris公司的成长轨迹,也反映了电子行业中技术创新和市场竞争的激烈态势。

DLG Hanbit公司的发展小趣事

为了保证产品的品质,DLG Hanbit公司建立了严格的质量管理体系,并引进了国际先进的质量检测设备。公司还积极参与国际标准制定,与全球知名电子企业建立了合作关系。通过不断提升产品品质和服务水平,DLG Hanbit公司的产品在国际市场上获得了认可,公司也逐渐实现了国际化战略。

Asia Electronics Ind Co Ltd公司的发展小趣事

Asia Electronics Ind Co Ltd自成立以来,一直致力于电子技术的研发与创新。公司投入大量资源用于研发,不断推出具有市场竞争力的新产品。其中,公司成功开发的一款高效能、低功耗的电子产品,在市场上获得了广泛的认可。这款产品不仅满足了消费者对性能的需求,还顺应了绿色环保的发展趋势,为公司赢得了良好的口碑。

Broadband公司的发展小趣事

随着科技的不断进步,BJB公司意识到技术创新的重要性。因此,公司加大了研发投入,积极引进先进的技术和设备,致力于照明配件产品的创新和升级。经过不懈的努力,BJB成功研发出具有高效节能、环保低碳特点的照明配件产品,不仅提升了产品的性能和质量,也满足了客户对绿色照明的需求。

问答坊 | AI 解惑

论坛来了一位新版主,A_P!!

热烈欢迎A_P,大家有什么问题不要客气啊,这位可是技术大牛~~~~       有请斑竹A_P登场…… ;P 不知道什么时候这位版主才能来,先欢迎下:)…

查看全部问答>

赛灵思的XPS开发环境关键文件

  赛灵思的XPS开发环境关键文件简介:   MHS文件:描述硬件结构的,在图形界面对任何一个硬件的更改都是对这个文件的改动,不建议手动修改这个文件,还是用图形界面吧。其文件结构主要分为   1)参数版本定义: PARAMETER VE ...…

查看全部问答>

扩内存的奇怪现象----64M->128M

硬件:bank6接2片64M SDRAM,BA0接A25,BA1接26 Bootloader:ok2440提供的 今天焊接了器件之后在ADS下用AXD调试 b        ResetHandler ResetHandler         ldr        r0,=W ...…

查看全部问答>

串口几个问题 急!!!

RS422的几个引脚分别做什么用的,R+ R-什么区别,如果连接两个RS422,引脚怎么对接?R+连T+,R-连R+吗?RS232是全双工还是半双工? 呵呵,问题挺多的,内行人士多多指教,回答多多益善啊!!…

查看全部问答>

ffmpeg arm加速问题

本人想在wince系统下开发视频软件。目前porting 完成ffmpeg. 发现ffmpeg中有armv4,armv5,armv6的有关idct部分的代码,    armv4,armv5部分通过config已经编译通过,但是发现好像没有地方使用,不知道这部分的代码是否可以使用在ffmpeg ...…

查看全部问答>

gsm modem 电路原理图

有过这方面电路设计经验的请与我联系 qq:602199326…

查看全部问答>

SHT21 温湿度传感器多少钱一个?

SHT21 温湿度传感器多少钱一个?北京哪里可以找到销售?…

查看全部问答>

FLASH存储数据?

请问怎样将数据存放在0X10000后的FLSAH里?…

查看全部问答>

鑫海宝贝紧急求救(悬赏100金币)

  【DSP应用系统设计 】  (赵勇,甘泉 著) 【TMS320C54XX DSP实用技术】第2版 (汪安民 陈明欣 朱明 著) 【TMS320C54X DSP 结构、原理及应用】第2版 (戴明桢  周建江 著) 各位大哥谁有这三本书的电子档,万分感谢了 ...…

查看全部问答>

十二相整流变压器的结构是什么

谁能告诉我十二相整流变压器的结构是什么?…

查看全部问答>