tiny4412 裸机程序 八、重定位到DRAM及LCD实验

一、实验原理

上一章已经解释的很清楚了,如何将所要运行的user_bin程序定位到DRAM中,这一章要进行重定位到DRAM后运行LCD程序,实际上一章中BL2中程序可以不用改动,直接重写我们的USER目录下的程序即可,将USER目录下的LED灯闪烁程序用LCD程序替换就行,最后编译出的程序名字也叫user_bin.bin即可,这样也可以用上一章中的fast_fuse.sh进行烧写到SD卡运行。

1、LCD控制器

Exynos4412的LCD控制器可以通过编程支持不同LCD屏的要求,例如行和列像素数,数据总线宽度,接口时序和刷新频率等。LCD控制器的主要作用,是将定位在系统存储器中的显示缓冲区中的LCD图像数据传送到外部LCD驱动器,并产生必要的控制信号,例如RGB_VSYNC,RGB_HSYNC, RGB_VCLK等。

 

图8-1、Exynos4412 LCD控制器框图

(下面的部分来自网络翻译,规格书中的描述)

如上图8-1所示,在Exynos4412规格书中截图,LCD控制器的构成主要由VSFR,VDMA,VPRCS , VTIME和视频时钟产生器几个模块组成:

(1)、VSFR由121个可编程控制器组,一套gammaLUT寄存器组(包括64个寄存器),一套i80命令寄存器组(包括12个寄存器)和5块256*32调色板存储器组成,主要用于对lcd控制器进行配置。

(2)、VDMA是LCD专用的DMA传输通道,可以自动从系统总线上获取视频数据传送到VPRCS,无需CPU干涉。

(3)、VPRCS收到数据后组成特定的格式(如16bpp或24bpp),然后通过数据接口(RGB_VD, VEN_VD, V656_VD or SYS_VD)传送到外部LCD屏上。

(4)、VTIME模块由可编程逻辑组成,负责不同lcd驱动器的接口时序控制需求。VTIME模块产生 RGB_VSYNC, RGB_HSYNC, RGB_VCLK, RGB_VDEN,VEN_VSYNC等信号。

Exynos4412的LCD主要特性:

(1)、支持4种接口类型:RGB/i80/ITU601(656)/YTU444

(2)、支持单色、4级灰度、16级灰度、256色的调色板显示模式

(3)、支持64K和16M色非调色板显示模式

(4)、支持多种规格和分辨率的LCD

(5)、虚拟屏幕最大可达16MB

(6)、5个256*32位调色板内存

(7)、支持透明叠加

2、接口信号

LCD的FIMD显示控制器全部信号定义如下表8-1所示

表8-1、LCD接口信号表

Signal

I/O

Description

LCD Type

LCD_HSYNC

O

水平同步信号

 

 

RGB I/F

LCD_VSYNC

O

垂直同步信号

LCD_VDEN

O

数据使能

LCD_VCLK

O

视频时钟

LCD_VD[23:0]

O

LCD像素数据输出

SYS_OE

O

输出使能

VSYNC_LDI

O

Indirect i80接口,垂直同步信号

 

 

 

i80 I/F

SYS_CS0

O

Indirect i80接口,片选LCD0

SYS_CS1

O

Indirect i80接口,片选LCD1

SYS_RS

O

Indirect i80接口,寄存器选择信号

SYS_WE

O

Indirect i80接口,写使能信号

SYS_VD[23:0]

IO

Indirect i80接口,视频数据输入输出

SYS_OE

O

Indirect i80接口,输出使能信号

VEN_HSYNC

O

601接口水平同步信号

 

 

 

ITU 601/656 I/F

VEN_VSYNC

O

601接口垂直同步信号

VEN_HREF

O

601接口数据使能

V601_CLK

O

601接口数据时钟

VEN_DATA[7:0]

O

601接口YUV422格式数据输出

V656_DATA[7:0]

O

656接口YUV422格式数据输出

V656_CLK

O

656接口数据时钟

VEN_FIELD

O

601接口域信号

 

其中主要的RGB接口信号:

(1)、LCD_HSYNC:行同步信号,表示一行数据的开始,LCD控制器在整个水平线(整行)数据移入LCD驱动器后,插入一个LCD_HSYNC信号;

(2)、LCD_VSYNC: 帧同步信号,表示一帧数据的开始,LCD控制器在一个完整帧显示完成后立即插入一个LCD_VSYNC信号,开始新一帧的显示;VSYNC信号出现的频率表示一秒钟内能显示多少帧图像,称为“显示器的频率”

(3)、LCD_VCLK:像素时钟信号,表示正在传输一个像素的数据;

(4)、LCD_VDEN:数据使能信号;

(5)、 LCD_VD[23:0]: LCD像素数据输出端口

3、RGB信号的时序

如下图8-2是LCD的RGB接口工作时序图,图中各时钟延时参数的含义如下,这些配置可以在所使用的LCD规格书中查取:

(1)、相关参数说明

VBPD(vertical back porch):表示在一帧图像开始时,垂直同步信号以后的无效的行数。

VFBD(vertical front porch):表示在一帧图像结束后,垂直同步信号以前的无效的行数。VSPW(vertical sync pulse width):表示垂直同步脉冲的宽度,用行数计算。

HBPD(horizontal back porch):表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数。

HFPD(horizontal front porth):表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数。

HSPW(horizontal sync pulse width):表示水平同步信号的宽度,用VCLK计算。

(2)、帧的传输过程

VSYNC信号有效时,表示一帧数据的开始,信号宽度为(VSPW +1)个HSYNC信号周期,即(VSPW +1)个无效行;

VSYNC信号脉冲之后,总共还要经过(VBPD+ 1)个HSYNC信号周期,有效的行数据才出现; 所以,在VSYNC信号有效之后,还要经过(VSPW +1  + VBPD + 1)个无效的行;

随即发出(LINEVAL+ 1)行的有效数据;

最后是(VFPD + 1)个无效的行。

(3)、行中像素数据的传输过程

HSYNC信号有效时,表示一行数据的开始,信号宽度为(HSPW+ 1)个VCLK信号周期,即(HSPW +1)个无效像素;

HSYNC信号脉冲之后,还要经过(HBPD +1)个VCLK信号周期,有效的像素数据才出现;

随后发出(HOZVAL+1)个像素的有效数据;

最后是(HFPD +1)个无效的像素。

(4)、将VSYNC、HSYNC、VCLK等信号的时间参数设置好之后,并将帧内存的地址告诉LCD控制器,它即可自动地发起DMA传输从帧内存中得到图像数据,最终在上述信号的控制下RGB数据出现在数据总线VD[23:0]上。用户只需要把要显示的图像数据写入帧内存中。

其实现实的图像有像素点组成行、行组成场、场组成动画、动画叠加也就是3D的出现,也就是我们所说的“点动成线、线动成面、面动成体”。


图8-2、LCD的RGB工作时序图

4、LCD的硬件接口


图8-3、LCD的部分硬件电路图

5、16M(24BPP)色的显示模式

由于我的Tiny4412所用屏幕是S07,是24bit(A888)显示模式,即用24位的数据来表示一个像素的颜色,每种颜色使用8位。 LCD控制器从内存中获得某个像素的24为颜色值后,直接通过VD[23:0]数据线发送给LCD;在内存中,使用4个字节(32位)来表示一个像素,其中的3个字节从高到低分别表示红、绿、蓝,剩余的1个字节无效;

以上内容是我从以前调试uboot中LCD显示查阅到的资料整合,其主要来自于网络,网络上还有各种介绍LCD的相交资料,有兴趣的朋友可以自己深究,也可以参考我即将整理的UBOOT相关文档。

二、程序说明

下面对程序进行简要说明,这时我只对USER目录下的程序实现过程进行必要说明,其他相关细节,请自行对照手册来分析程序,这一章的程序我也进行必要的注释,

首先来看一下Makefile和sdram.lds start.S几个文件

1、USER/Makefile sdram.lds start.S

上面三个程序的说明请参考上一章,其主要作用就是将user_bin.bin中的而start.s链接地址设置为0X43E00000让程序重定们DRAM中时,就执行这个程序,而start.s唯一做的事就是跳转到main.c中的main函数执行。

2、USER/main.c

Mian函数很清楚,一开始调用lcd_init();然后调用lcd_clear_screen(0x000000)清屏,接着画一个十字,再画了几条水平线和一条垂直线,最后让LDE灯一直闪烁。

3、USER/LCD.C

首先需要说明的一点时,这个程序我参考了网上很多人关于S5PV210的写法,但或多或少总存在一些问题,最后在FriendlyARM的BBS的论坛上一个ID号为“赵远远”提供的lcd_chinese_char程序,这个程序初始化流程可以很好的工作。所以,这个程序里的初始化部分主要取自于此!

lcd_init()

3.1、寄存器设置方法

如下面两句话所示:

#define LCDBLK_CFG (*(volatile unsigned int *)0x10010210)

LCDBLK_CFG = a;

语句中0x10010210是寄存器LCDBLK_CFG的地址,(volatileunsigned int *)0x10010210是将此0x10010210值强制转换成一个指向unsigned int的指针,volatile作用是防止编译器优化,再在外面加一个*就是取0x10010210地址处的值了,所以用LCDBLK_CFG就可改写0x10010210处的数据,

下面来按着LCD的初始化顺序进行说明。

3.2、定义IO引脚功能为RGB接口。

由上图8-3所示,所用的GPIO口分别是GPIO的F口的0/1/2/3四组,查看手册可知要想将其设置为LCD的RGB接口,只需要将其设置为2即可。同时将其IO口设置成为内部上拉,且将其驱动能力设置为最强代码如下:

GPF0CON = 0x22222222;                                    

GPF1CON = 0x22222222;

GPF2CON = 0x22222222;

GPF3CON = 0x00222222;

// Set pull-up,down disable

GPF0PUD = 0x0000FFFF;

GPF1PUD = 0x0000FFFF;

GPF2PUD = 0x0000FFFF;

GPF3PUD = 0x00000FFF;

 

//MAX drive strength---------//

GPF0DRV = 0x0000FFFF;

GPF1DRV = 0x0000FFFF;

GPF2DRV = 0x0000FFFF;

GPF3DRV = 0x00000FFF;

3.3、接着设置LCD相关时钟寄存器

这一步主要设置选择LCD时钟输入源为MPLL,且不对其进行分频,同时设置LCDBLK_CFG使其使用FIMD接口,且设置LCDBLK_CFG2使其PWM输出使能,其实,LCDBLK_CFG2可以不用设置。

3.4、清除Fram Buffer处的数据

这里调用一个Memset()函数,对地址0x54000000处,0X200000大小的DRAM进行初始化为统一值,一开始我设置为,后来为了调试,我将其设置为0xff00,即可以显示为绿色。

3.5、设置VIDCONx,设置接口类型,时钟分频,极性以及使能LCD控制器等

A、VIDCON0参考数据手册,这一个寄存器主要设置接口类型和时钟分频,这里仅仅设置了其时钟分频值。参考S07的手册,找到时像素时钟。由于我们的MPLL为800MHZ,所以这里设置值,根据手册进行计算,要得到33.3MHZ左右的像素时钟,所以寄存器第6~13bit设置为23.其他都保持为0即可。

代码如下:

VIDCON0 = (23 << 6);

此代码中也给出了如下代码风格的写法,后面很多寄存器配置我也均写好相类似风格的代码,但我要遗憾的说一声,这种风格的写法且总不能执行成功,LCD像是初始化成功,但且不能将图形给画出,这在此比对代码比对了很久,也没有找出原由来,所以这里代码中可运行的部分是受高手唾弃的一种写作风格,同时也给出了另一种写作风格的代码,希望细心的网友能发现其中那里我设置有差别,而让后一种风格的代码能正常运行。

// #define EXYNOS_VIDCON0_CLKVAL_F(x)                       (((x) & 0xff) << 6)

//VIDCON0 = EXYNOS_VIDCON0_CLKVAL_F(23);  //not use this method ,it does not work???

B、VIDCON1主要设置像表时钟信号一直存在,且高电平有效,而IHSYNC=1,极性反转IVSYNC=1,极性反转,这是由于S07的时序图中VSYNC和HSYNC都是低脉冲有效,而Exynos4412芯片手册时序图,如上图8-2所示:VSYNC和HSYNC都是高脉冲有效,所以需要反转。

C、VIDTCONx用来设置时序和长宽等参数,这里就主要设置VBPD(vertical back porch)、 VFBD(vertical frontporch)、VSPW(vertical sync pulse width)、HBPD(horizontal backporch)、 HFPD(horizontal sync pulse width)等参数,参数的意义前面已有简要说明,这里简单用图片的方式说明如何取值。

如下图8.4所示是VIDTCON0取值过程,VIDTCON0设置帧同步时序。



图8-4、VIDTCON0寄存器取值参考图

VBPDE与RGB接口无关,不用关心,所以其代码设置如下:

VIDTCON0 = (22 << 16) | (21 << 8) | (0);

如下图8.5所示是VIDTCON1取值过程,VIDTCON1设置像素同步时序。



图8-5、VIDTCON1寄存器取值参考图

VFPDE与RGB接口无关,不用关心,所以其代码设置如下:

VIDTCON1 = (45 << 16) | (209 << 8) | (0);

如下图8-6所示,为寄存器VIDTCON2设置取值要点:


图8-6、VIDTCON2寄存器取值参考图

VIDTCON2 = (479 << 11) | 799;

D、设置WINCON0寄存器,即设置数据格式。

Exynos4412的LCD控制器有overlay功能,它支持5个window。这里只使用window0,设置其代码RGB模式为24bit(A888)且使能window0,其相关的代码设置如下:

WINCON0 = (11 << 2) | 1;

E、设置VID0SD0A/B/C,即设置Window0的坐标系。

相关代码如下:

VIDOSD0A = 0;

VIDOSD0B = (799 << 11) | 479;

VIDOSD0C = 480 * 800;

F、配置VIDW00ADD0B0和VIDW00ADD1B0,设置framebuffer的地址;

相关代码如下:

VIDW00ADD0B0 = LCD_VIDEO_ADDR;

VIDW00ADD1B0 = LCD_VIDEO_ADDR + VIDOSD0C * 4;

G、配置SHADOWCON和WINCHMAP2、选择使能DMA通道0。由于我们使用的是Window0,所以需要使能DMA通道0;

相关代码如下:

SHADOWCON |= 1;

 

WINCHMAP2 &= ~(7 << 16);

WINCHMAP2 |= 1 << 16;

WINCHMAP2 &= ~7;

WINCHMAP2 |= 1;

H、最后设置VIDCON0低两位使能LCD,代码如下:

VIDCON0 |= 3;

我们不需要使用很强大的功能,所有只需设置这几个寄存器即可。

lcd_draw_pixel()

经过lcd_init()初始化LCD控制器之后,我们就可以在LCD上描绘图形了,代码里的所有绘制图形的函数都是基于lcd_draw_pixel()这个函数,它的作用是在LCD上描绘一个点,通过描绘一个个的点最终会可以组成图形了。在LCD上描点的本质就是往Frame Buffer中写入颜色值而已。LCD控制器自己会去读所定义的Frame Buffer内存位置处读取数据,然后输出到LCD。

lcd_draw_pixel()这个函数以及后面几个画水平线、垂直线和十字的函数我完成COPY了《Linux平台下Mini210S裸机程序开发指南》里的代码,下面我们仅仅COPY说明一下此函数,其代码如下:

void lcd_draw_pixel(int row, int col, intcolor)

{

unsigned long * pixel = (unsigned long *)LCD_VIDEO_ADDR;

*(pixel + row * COL + col) = color;

}

其中LCD_VIDEO_ADDR = 0x54000000,即framebuffer的基地址,这个值只要是DRAM中,一块可分配16M大小的DRAM的一个地址即可。row和col用来决定偏移,color是颜色值,只要在framebuffer中对应的地址处写入颜色值就可以在LCD上描绘出该点。

后面其他函数很简单,这里就不费时间做过多说明。

三、完整的烧写过程

已将SD卡插入电脑,假设linux识别了SD卡,其识别号为sdb。执行下面命令:

# chmod 777 –R 7_sdram_LCD

# cd 7_sdram_LCD

# make

# ./ fast_fuse /dev/sdb

四、上电实验

将sd卡插入Tiny4412中,选择sd卡启动,和电脑能过串口0连接好,打开一个串口调试助手,然后上电,可以看到以下现象:

串口助手中会显示一些信息,LCD初始化完成后,LCD屏幕首先会显示一整幅的绿色背景。 一两秒钟后,会显示Mian()函数中所画的几条横线和一条竖线以及一个十字,板上的LED灯会一直闪烁。

 

前面说过,这一章中留有一点问题,就是两种写法,同样的设置,为什么第二种代码风格却不能运行,我自己用人眼对比了好多次,也没有发现代码那里有问题,没办法人眼排查,只能试着将串口重新初始化,然后打印出相关信息,找出原因吧。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 嵌入式Linux点灯实验通常涉及以下步骤: 1. 准备硬件:选择一个嵌入式开发板,例如Tiny4412,连接电源和串口线,以便通过终端程序与开发板进行交互。 2. 下载和编译内核:从开发板制造商的网站上下载适用于该板的内核源代码,并使用交叉编译工具链编译内核。在内核配置时,需要确保启用GPIO子系统以及相关的GPIO驱动程序。 3. 编写应用程序:使用C或Python等编程语言编写一个简单的应用程序,用于点亮或熄灭开发板上的LED灯。该应用程序可以使用GPIO用户空间API来控制GPIO引脚。 4. 将应用程序复制到开发板上:使用FTP或SCP等工具将编译好的应用程序复制到开发板上,并在终端上运行该应用程序。 5. 调试:通过查看终端输出,可以检查应用程序是否正确地控制了LED灯。如果出现问题,可以使用GDB等调试工具进行排查。 需要注意的是,嵌入式开发需要具备一定的硬件和软件知识,建议在实验前先学习相关的嵌入式Linux开发知识。 ### 回答2: 嵌入式系统是指将计算机技术与其他领域相结合,设计出适应特定应用领域的硬件系统和软件系统。其中,Linux系统是嵌入式系统中使用最多的操作系统之一。本篇文章将介绍如何使用Linux系统进行嵌入式设备的点灯Tiny4412实验。 首先,需要先了解一下Tiny4412开发板的一些基本信息。Tiny4412是一款基于ARM Cortex-A9的嵌入式开发板,具有4核CPU,1GB内存和8GB扩展存储空间。该开发板还集成了多种外设,如4.3英寸液晶屏、USB接口、以太网口等,可以满足各种嵌入式系统的应用需求。 接着,我们需要对Tiny4412开发板进行连接和配置。首先将开发板连接到计算机端,并使用串口线连接开发板和计算机、通过串口终端对开发板进行配置。启动开发板后,进入系统终端,创建一个新的文件夹用来存放程序。cd ~ // 进入主目录,输入mkdir tiny4412_led // 创建新文件夹,输入cd tiny4412_led // 进入新文件夹,输入 接下来,下载并安装软件工具链。需要先下载安装arm-linux-gcc-4.4.3工具链,这个工具链是基于 ARM926EJ-S 架构的版本。输入以下命令下载并安装: sudo apt-get install zlib1g-dev libncurses5-dev libssl-dev sudo apt-get install gcc-arm-linux-gnueabi 安装完成后,我们就可以编写点灯程序了。首先,在tiny4412_led文件夹下新建一个C语言文件led.c,需要注意的是,由于Tiny4412采用了GPIO作为点灯的控制接口,因此需要引入头文件gpio.h、stdio.h、stdlib.h和unistd.h。代码如下: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "gpio.h" #define LED5 110 int main(void) { GPIO_Handle gpio; int led = LED5; gpio = GPIO_Init(); if (gpio == NULL) { fprintf(stderr, "GPIO_Init failed\n"); return 1; } GPIO_SetDir(gpio, led, GPIO_OUTPUT); while (1) { GPIO_SetValue(gpio, led, 1); sleep(1); GPIO_SetValue(gpio, led, 0); sleep(1); } GPIO_Fini(gpio); return 0; } 上面的代码定义了一个引脚(LED5)来控制灯的亮灭,通过GPIO_SetDir函数设置该引脚为输出模式,进入一个无限循环,每隔1秒钟,将LED5的输出电平设置为高电平和低电平,实现LED灯的闪烁。 编写完程序后,使用命令行编译该程序: arm-linux-gnueabi-gcc -o led led.c 然后,将编译生成的可执行文件(led)拷贝到Tiny4412开发板上: cp led /mnt/nfs/root/tiny4412_led/ 最后,在Tiny4412的终端输入以下命令运行程序: ./led 由于程序是一个无限循环,因此,LED灯会一直闪烁,知道我们手动停止该程序。通过上述方式,我们成功实现了使用Linux系统进行嵌入式设备的点灯Tiny4412实验。 ### 回答3: 嵌入式系统是指在电子设备中嵌入的小型计算机系统,用于控制或监控设备的运行。Linux是一种自由、开放源代码的类Unix操作系统,广泛应用于服务器和嵌入式系统中。点灯实验是一项基础实验,通过控制LED点亮和熄灭,来了解嵌入式系统的基本操作和控制。 本文将介绍如何在嵌入式系统中运行Linux操作系统,并通过点灯实验控制LED灯的点亮和熄灭。 实验材料: - Tiny4412板子 - USB转串口模块 - 文本编辑器 - Linux交叉编译工具链 - LED灯 步骤1. 安装Linux操作系统 首先需要在Tiny4412板子中安装Linux操作系统。可以通过交叉编译工具链将Linux内核和根文件系统交叉编译到SD卡中,然后将SD卡插入到Tiny4412板子中,并启动板子。 步骤2. 连接USB转串口模块 接下来需要将USB转串口模块连接到Tiny4412板子上,然后通过串口工具连接到板子。 步骤3. 编写LED控制程序 使用文本编辑器编写LED控制的C程序。通过控制GPIO口实现控制LED点灯。LED灯连接到Tiny4412板子上的GPIO口。 步骤4. 交叉编译程序 使用交叉编译工具链将程序交叉编译到Linux系统中。将编译生成的ELF文件拷贝到Tiny4412板子中。 步骤5. 运行程序 使用命令行启动编译生成的ELF文件。此时就可以通过程序控制LED的点亮和熄灭了。 总结 通过上述步骤,我们就可以在Tiny4412嵌入式系统中实现Linux操作系统和点灯实验。这些步骤并不是非常困难,只需要一点编程基础和嵌入式系统相关的知识即可。嵌入式开发是一门非常有前景的技术,希望本文对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值