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处!!!
上一篇:Tiny210裸机之LCD显示图片
下一篇:Tiny210裸机之bootm命令启动内核
推荐阅读
史海拾趣
随着技术的不断进步和市场需求的增长,DSMI Electronics SA公司开始寻求与国际知名品牌的合作。通过与多家国际大公司的合作,DSMI不仅提升了自身的技术水平和生产能力,还扩大了市场份额。特别是在嵌入式系统领域,DSMI的产品得到了广泛应用,成为了行业内的重要供应商之一。
Chenmoun Enterprise Ltd深知技术创新是企业发展的核心动力。因此,公司每年都会投入大量的资金用于研发新的电子产品和技术。通过不断的技术创新和产品升级,Chenmoun在行业内保持了领先地位,并实现了持续稳健的发展。
人才是企业发展的核心。Compostar Technology Co Ltd深知这一点,因此一直注重人才培养和团队建设。公司建立了完善的人才培训体系,为员工提供了广阔的职业发展空间。同时,公司还积极营造良好的企业文化氛围,激发员工的创新精神和团队合作精神。这些举措使得公司拥有一支高素质、高效率的员工队伍,为公司的持续发展提供了有力保障。
随着市场的不断发展,AVA电子意识到只有不断创新才能在竞争中保持领先。于是,公司加大了在研发方面的投入,引进了一批高素质的研发人才,并与多所高校和研究机构建立了合作关系。经过数年的努力,AVA电子成功研发出了一系列具有自主知识产权的电子产品,这些产品在性能、稳定性和用户体验等方面都达到了行业领先水平。这些创新产品的推出,不仅提升了公司的市场地位,也为公司带来了可观的利润。
随着环保意识的不断提高,绿色、环保、低碳已成为全球经济发展的重要趋势。DURATOOL公司积极响应这一趋势,致力于研发和生产绿色环保的电子工具产品。公司采用环保材料和工艺生产产品,减少了对环境的污染和破坏。同时,公司还积极开展环保宣传和公益活动,引导消费者树立绿色消费观念。这些举措不仅提升了DURATOOL公司的社会形象,也为其在未来的市场竞争中赢得了先机。
DURATOOL公司自成立以来,一直致力于电子工具的技术创新。在20世纪90年代,公司研发出了一款具有革命性的数字万用表,该产品在精确度、稳定性和操作便捷性方面均大幅超越当时的市场主流产品。这一创新不仅为DURATOOL公司赢得了大量忠实用户,也为其在电子测量工具市场树立了技术领先的形象。随后,DURATOOL公司不断加大研发投入,推出了一系列具有竞争力的新产品,逐步巩固了其在电子工具行业的领先地位。
mdkarm3.05问题target not created 初学arm,用keil老生成不了目标文件,请高手指教,怎么解决啊 build target \'lpc2106\' assembling startup.s... /cygdrive/c/cygnus/arm-tools/bin/../lib/gcc-lib/arm-thunb-elf/3.3.1/../../../../arm-thumb-elf/bin/ld: warning:cannot fin ...… 查看全部问答∨ |
|
2. 印刷电子 能快速印刷出多个导体/绝缘体或半导体层以形成电路的技术,可望催生比目前采用传统制程生产之IC成本更低芯片。通常印刷半导体意味着使用性能与硅大不相同 的有机材料,甚至所生产之组件尺寸也能超越硅材料的 ...… 查看全部问答∨ |
我想在cygwin下编译基于目标cpu i960的交叉编译工具链 在编译bootrap gcc的时候遇到一个libgcc1.a的问题 mv libgcc1.a libgcc1.cross || (echo You must find a way to make libgcc1.a; false) mv: cannot stat `libgcc1.a\': No such file or d ...… 查看全部问答∨ |
准备上个项目,人手不够,打算找人合作。 杭州有产品经验,有业余时间,熟悉工业级ARM,51,tcp/ip,RTOS等之一的技术便可。 有兴趣的回个贴。 技术专长,业余时间,要求等。 sssbang@163.com … 查看全部问答∨ |
本帖最后由 jameswangsynnex 于 2015-3-3 19:54 编辑 用头戴式耳机,尤其是小型耳机听音乐,总感到音乐味不够足,在低频段的效果更差。因此用本机增强耳机的低频特性,并采用立体声反相合成的办法,加上内藏简易矩阵环绕声电路,能获得强劲的低音 ...… 查看全部问答∨ |
是不是现在支持STM32F的GCC编译器开发环境都是命令行模式的 我下载了一个WINARM20080331里面没找到XP可以运行的程序CodeSourcery 里面用的好象也是命令行模式 … 查看全部问答∨ |
求一个基于MSP430F149或F449芯片的LCD键盘显示系统的完整C程序 求一个基于MSP430F149或F449芯片的LCD键盘显示系统的完整C程序 说明:本人刚开始学习MSP430,想用MSP430做一个键盘LCD显示控制系统 求一个完整的C程序,来学习和模仿下。 控制系统要求:1,键盘是3*4列的行列式扫描键盘。LCD最好用truely(信利公 ...… 查看全部问答∨ |