单片机
返回首页

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

2021-12-13 来源:eefocus

一、实验原理

上一章已经解释的很清楚了,如何将所要运行的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灯会一直闪烁。

 

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

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 开关电源的基本组成及工作原理

  • 用NE555制作定时器

    相关电子头条文章