`
isiqi
  • 浏览: 16870401 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Linux内核升级LCD驱动的更换(开发板)

阅读更多

Linux内核升级LCD驱动的更换(开发板)

关键字

内核升级 ,更换驱动 ,LCD

本文给出了将一个已有的LCD驱动添加进一个新的linux内核中的方法


一. 概述

本文搜集整理了Linux系统编译时的主要配置选项(make config)的详细说明,供Linux裁剪特别是设备驱动和模块功能增删时使用参考。需要注意的是,每个版本linux版本的config各选项意义,命名等都可能有所差异。

1、 修改内核根目录config文件

文本方式打开config文件,将LCD的几个编译开关添加进Frame buffer hardware drivers这一项目下,之后在make menuconfig中就可以看到。

#

# Frame buffer hardware drivers

#

CONFIG_FB_SIDSA=y

CONFIG_FB_TCM=y

# CONFIG_FB_SDRAM is not set

CONFIG_TFT_AT91=y

CONFIG_FB_SIDSA_DEFAULT_BPP=16

# CONFIG_FB_SIDSA_DEBUG is not set

在控制台显示驱动项目中将linux logo显示的编译开关打开,logo显示16色或其他均可。

#

# Console display driver support

#

CONFIG_LOGO=y

# CONFIG_LOGO_LINUX_MONO is not set

CONFIG_LOGO_LINUX_VGA16=y

添加好上述config选项后,使用make menuconfig打开该config文件,即可看到这些选项,一一进行确认:

LCD的配置项位于drivers->graphices support下 分别将frame buffer和logo的选项选中,才能使用逻辑屏和logo图片。Bootup logo中可选黑白图,16色图或256色图其中一种均可。

clip_image002

Frame buffer的设备驱动选中SIDSA控制器,目前逻辑屏比较小为QVGA,数据源选为TCM等选项。开发板具有内置大约1M多的SRAM,当逻辑屏比较大时,应选SDRAM.

clip_image004

2、 添加屏驱动源码到工程目录

Linux的屏驱动一般位于drivers\video 目录下,目前AT91SAM926开发板使用的LCD驱动是sidsafb.c和sidsafb.h,at91sam9261_lcdc.h三个文件,在标准的linux2.6.25上是没有的,从开发板源码包中复制过来放到该目录下(还要进行一些代码修改,后面的步骤会讲到)。

3、修改逻辑屏驱动模块的Makefile文件

打开drivers\video目录下的Makefile文件,在其中添加sidsafb.o文件的编译选项,依赖于编译开关CONFIG_FB_SIDSA,也可使用文件比较的方式和开发板同名makefile比较,将下图蓝色方框部分复制到你的makefile

clip_image006

4、修改模块的Kconfig文件

打开drivers\video目录下的Kconfig文件,添加FB_SIDSA, FB_TCM等几个编译开关的配置,也可使用文件比较器将开发板源码包下的同名Kconfig文件比较,将下图蓝色方框部分的几个编译开关选项复制添加到你的drivers\video\Kconfig中,如下图:

clip_image008

5、源代码的修改

移植驱动时有两种工作方式,一种是所有驱动同时一并移植,这样做的好处是各驱动模块公共文件如寄存器表,相关宏的头文件放置的比较合理,移植完后清晰,缺点是交叉错误多,调试工作量大,一两个人无法完成。另一种是单个模块串行一一移植,好处是调试比较好调,缺点是移植完代码可能比较乱。综合一下,个人认为驱动整合移植时先移植所有公共的头文件,公共的功能函数和宏,不添加具体模块,编译出一个基本版本,在此版本基础上在分头移植各个模块比较合理。

单驱动模块移植时,总结下来源代码的修改主要包括几个部分:

a) 驱动的依赖关系整理清楚,若本驱动还依赖其他驱动,则还需要先移植添加其他驱动模块

b) 理清所添加驱动对外部变量,函数,宏的引用关系,去除编译错误。

c) 修改虚拟地址->物理地址的映射函数为当前平台的映射函数,使寄存器map表映射正确。

d) 修改驱动的注册和加载部分。

具体改动如下:(此部分改动已有改好的版本在FTP,列举只是为了说明问题和给出方法)

模块依赖关系和编译错误的整理

由于本开发板的屏是RGB屏,所以实际驱动是由AT91所带的LCDC控制器来完成,因此屏的驱动主要工作是配置LCDC和管理Frame buffer两部分。LCDC依赖于另外两个模块:IO和CLOCK(即代码中的PIO和PMC模块),IO用来控制LCDC的电源,CLOCK用来给出LCDC时序的时基。所以先要添加PIO和PMC部分的代码.为了不至于要挂载整个PIO和PMC模块,开发板的BSP将一些简单的功能独立出来作为函数供其他模块调用。

从开发板源码中找到PIO的寄存器定义相关宏,拷贝出来添加到sidsafb.c头部或sidsafb.h,不嫌麻烦的话也可另建头文件,PIO的寄存器主要是这些宏:

#define PIO_PER (0x0000) /**< PIO Enable Register */

#define PIO_PDR (0x0004) /**< PIO Disable Register */

#define PIO_PSR (0x0008) /**< PIO Status Register */

#define PIO_OER (0x0010) /**< Output Enable Register */

#define PIO_ODR (0x0014) /**< Output Disable Registerr */

#define PIO_OSR (0x0018) /**< Output Status Register */

#define PIO_IFER (0x0020) /**< Input Filter Enable Register */

………

同样添加PMC模块的寄存器宏,主要是这些:

#define PMC_SCER (0x0000) /**< System Clock Enable Register */

#define PMC_SCDR (0x0004) /**< System Clock Disable Register */

#define PMC_SCSR (0x0008) /**< System Clock Status Register */

#define PMC_PCER (0x0010) /**< Peripheral Clock Enable Register */

#define PMC_PCDR (0x0014) /**< Peripheral Clock Disable Register */

#define PMC_PCSR (0x0018) /**< Peripheral Clock Status Register */

#define PMC_MOR (0x0020) /**< Main Oscillator Register */

……..

添加各模块寄存器读写的宏

#define readreg_pmc(offset) readl(AT91C_VA_BASE_PMC + offset)

#define writereg_pmc(value, offset) writel(value, (AT91C_VA_BASE_PMC + offset))

有了这些宏,对IO和CLOCK的操作函数基本就可以加进来编译,屏驱动中引用到的操作函数主要是:

at91_gpio_set_level

at91_gpio_periph_enable

at91_gpio_configure

at91_device_pio_setup

at91_enable_periph_clock

at91_disable_system_clock

at91_enable_system_clock

at91_lcdc_clock_enable

at91_lcdc_power_up

虚拟地址-物理地址转换函数的修改

去除上述产生的所有编译错误,将其他一些零碎的未定义的对象添加进来,基本就可以编译通过了。但还不能运行,一般地讲,两个linux版本的虚拟地址到物理地址的转换关系是不一致的,而驱动对寄存器的访问都是通过虚拟地址进行,因此要使驱动能在新的linux内核上运行,必须使用该linux的虚拟地址-物理地址转换公式,获取到正确的寄存器虚拟地址。

Linux系统的设备内存映射都映射到系统空间(0xc00000000-0xFFFFFFFF)的固定映射区之内,映射方式是线性、连续的,因此设备的物理地址和虚拟地址只相差一个常数偏移量,当物理内存小于896M时,高端映射区未用,固定映射区的首地址一般就是紧接在vmalloc区的后面,不同的版本不同的芯片体系中vmalloc区的尾地址定义有所不同,在vmalloc.h中定义:

Linux 2.6.15-AT91定义为

#define VMALLOC_END (0xFF000000 - 0x00200000)

Linux 2.6.25-AT91定义为

#define VMALLOC_END (AT91_VIRT_BASE & PGDIR_MASK)

在Linux2.6.15-AT91体系中,物理地址到虚拟地址的转换相差的常数依赖于VMALLOC_END(/include/asm-arm/arch-at91sam9261/hardware.h):

#define AT91C_IO_PHYS_BASE 0xFFFFF000

#define AT91C_IO_VIRT_BASE VMALLOC_END

/* Convert a physical IO address to virtual IO address */

#define AT91_IO_P2V(x) ((x) - AT91C_IO_PHYS_BASE + AT91C_IO_VIRT_BASE)

即物理地址转换为虚拟地址时,虚拟地址=物理地址-(0xFFFFF000- VMALLOC_END)

在Linux2.6.25-AT91体系中,IO物理地址到物理地址转换公式为:

#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)

但其物理基地址AT91_IO_PHYS_BASE和虚拟基地址AT91_IO_VIRT_BASE和Linux2.6.15版本均不同,(由于对其的长度不同,因此IO物理基地址可能不同版本都不同,但具体到任意一个寄存器的物理地址,最终换算出来基地址+OFFSET都是一样的),因此寄存器的访问,必须采用当前体系的基地址,当前体系的OFFSET,当前体系的映射方式AT91_IO_P2V,才能得到当前体系下对应的正确的虚拟地址。

代码中将旧的映射函数AT91_IO_P2V屏蔽不用,采用新版本同名的AT91_IO_P2V映射函数,并将所有使用到的寄存器基地址,偏移量修改为当前体系的值,此处只用到LCDC,PIO,PMC三片寄存器,将其基地址改为当前版本定义值:

#define AT91C_VA_BASE_PIOA AT91_IO_P2V(AT91C_BASE_PIOA)

#define AT91C_VA_BASE_PMC AT91_IO_P2V(AT91C_BASE_PMC)

改为

#define AT91C_VA_BASE_PIOA AT91_IO_P2V(AT91_PIOA)

#define AT91C_VA_BASE_PMC AT91_IO_P2V(AT91_PMC)

至此,在当前体系下寄存器的虚拟地址就可以正确地得到了,使用虚拟地址去配置寄存器,才不会产生分页错,data abort之类地内存错误,
设备注册和初始化的修改

设备的注册和初始化一般位于arch\arm\对应体系目录下,使用AT91芯片时,主要是at91sam9261.c,at91sam9261_devices.c和board-sam9261ek.c三个代码文件和一些.h文件,第一个at91sam9261.c负责总的调用和定义,第二个at91sam9261_devices.c负责主要片内控制器的定义,初始化,其中LCDC就包含在这里面。第三个board-sam9261ek.c负责片外板上设备的定义和初始化,同一款芯片不同的板子不同的硬件在这里区别。

在at91sam9261_devices.c中找到LCD的定义和初始化,标准Linux2.6.25使用的是CONFIG_FB_ATMEL,将其改为当前开发板对应的代码,主要是RGB屏时序的定义,FB的位置区域,和普通设备device不一样,LCDC属于平台标配设备,其类型为platform_device,需要定义对DMA的使用等,将其设备名改为sidsafb.c文件中定义的"sidsa-lcdc",这样启动时才能找到"sidsa-lcdc"并将其挂载。这样,LCD驱动就移植完毕,编译通过,烧写后启动即可亮屏,如果想修改logo图片,到drivers\video\logo目录下修改图片,或直接修改其对应的数组。

LCDC的设备是:

static struct platform_device at91_lcdc_device = {

.name = "sidsa-lcdc",

.id = 0,

.num_resources = ARRAY_SIZE(lcdc_resources),

.resource = lcdc_resources,

.dev = {

.dma_mask = &lcdc_dmamask,

.coherent_dma_mask = DMA_BIT_MASK(32),

.platform_data = &lcdc_data,

},

};

调试过程中可在关键的函数中使用printk添加一些打印语句,如:

init/main.c中的start_kernel函数是内核启动的第一个函数,在这里进行各项初始化,可在其中加一些打印观察情况;

at91sam9260.c和at91sam9261_devices.c中进行芯片设备的加载,可加一些打印,观察哪些设备加载成功,哪些加载失败。

观察所加的设备"sidsa-lcdc”是否被正常挂载,可在设备的初始化函数sidsafb_init中添加打印,观察是否进入其中初始化,且注册设备driver_register时返回的值是否正确等。

编译时,要使用AT91-SAM926的config文件,由于每个板子的内存基地址和长度不一样,因此要在config中定义,也可以在代码中定义:(include\asm-arm\arch-at91\hardware.h)

#define AT91_SDRAM_BASE 0x20000000

屏基本上可以亮了,但还有个bug,就是显示完logo后之后一会儿就灭掉了,这是因为Linux2.6.25版本上的默认BSP时钟使用情况和现有开发板不一致,LCD定义的CLOCK有冲突,将如下CLK定义宏暂时注销即可正常显示:

//#define AT91_PMC_HCK1(1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */

//lingzj remove

#define AT91_PMC_HCK1 (1 << 1) /* AHB Clock (LCD) [AT91SAM9261 only] */

—— 完 ——

分享到:
评论

相关推荐

    移植linux内核到tq2440开发板.zip

    本项目涉及的是将Linux内核移植到TQ2440开发板的过程,这是一块基于Samsung S3C2440处理器的嵌入式开发板。S3C2440是一款流行的ARM9微处理器,广泛应用于各种嵌入式设备中。 首先,理解Linux内核移植的基本概念至关...

    基于linux2.6.30.4 framebuffer移植LCD驱动到FL2440开发板

    ### 基于 Linux 2.6.30.4 Framebuffer 移植 LCD 驱动到 FL2440 开发板 #### 1. LCD 硬件及显示原理介绍 **1.1 东华 3.5 寸 LCD 硬件介绍** FL2440 开发板所搭载的东华 3.5 寸 LCD 模块型号为 WXCAT35-TG3,采用 ...

    Linxu 5.4版本内核 移植适配正点原子IMX6ULL(2.4版本)开发板

    Linux内核提供了丰富的图形驱动框架和接口,使得开发者可以利用这些资源在内核层面上实现对LCD显示设备的驱动支持。在进行Linux 5.4内核移植时,适配正点原子IMX6ULL开发板的LCD显示需要根据硬件手册和数据表来编写...

    基于S5PV210的Linux内核移植.pdf

    3. Linux内核移植为后续驱动程序和应用程序的开发提供了保证。 Linux内核移植的优点: 1. Linux开源、易于移植、资源丰富等优点,使得它在嵌入式领域越来越流行。 2. Linux内核移植可以满足嵌入式系统的专用性...

    lcd-driver.rar_6410_6410 lcd_linux lcd 驱动

    掌握Linux LCD驱动的编写和调试对于嵌入式系统的开发者来说至关重要,这涉及到对硬件接口的理解、Linux内核编程以及图形显示原理的知识。通过分析和实践这个驱动程序,可以深入了解6410开发板的显示特性,以及Linux...

    linux2.6.30.4_framebuffer移植LCD驱动

    "linux2.6.30.4_framebuffer移植LCD驱动" 基于 Linux 2.6.30.4 framebuffer 移植 LCD 驱动到 FL2440 开发板,涉及到 LCD 硬件及显示原理、s3c2440 LCD 控制器、Framebuffer 驱动机制、驱动移植、应用程序接口等方面...

    基于linux的嵌入式lcd驱动的毕业设计开题报告.doc

    4. LCD驱动程序的设计与实现:编写驱动程序以控制LCD的显示,包括初始化、颜色设置、刷新率管理等,然后将驱动集成到Linux内核中。 5. 测试与调试:通过在ARM9开发板上运行驱动,验证其功能,确保LCD能正常显示。 ...

    正点原子STM32P1开发板Linux驱动教程

    4. **LCD驱动**:开发液晶显示器(LCD)的驱动程序。 通过以上知识点的学习与实践,开发者可以全面掌握STM32MP1在Linux环境下的驱动开发技能,从而能够针对不同应用场景开发出高效稳定的驱动程序。

    LCDLCDLCDLCDLCD

    在IT行业中,理解和掌握LCD驱动对于硬件工程师、嵌入式系统开发者以及系统管理员来说至关重要。本篇将深入探讨Linux环境下的LCD驱动实验,旨在帮助读者理解LCD的工作原理、驱动程序的结构以及如何在Linux系统中实现...

    jz2440开发板实现视频监控

    例如,摄像头驱动、LCD驱动、网络驱动等。 通过以上四个步骤的详细讲解,可以看出从U-Boot的移植、Linux内核的定制到根文件系统的构建,每一步都紧密相关且不可或缺。这些步骤共同构成了在jz2440开发板上实现视频...

    万勇Tiny210开发板驱动源码

    1. 设备树(Device Tree):设备树是Linux内核在启动时获取硬件信息的一种方式,它描述了硬件的拓扑结构和资源配置。对于Tiny210开发板,我们需要编写相应的设备树文件,以供内核识别和配置硬件。 2. 驱动模块:每...

    嵌入式linux内核的编译与移植

    嵌入式 Linux 内核的编译与移植 嵌入式 Linux 内核的编译与移植是嵌入式系统开发的关键步骤。以下是关于嵌入式 Linux 内核编译与移植的过程和注意事项。 一、 获得 Linux 内核源码 首先,我们需要获得 Linux 内核...

    linux 内核: linux-2.6.32.24-20240320-work.gz, 支出mini2440 开发板

    总的来说,这个压缩包提供的Linux内核版本是为mini2440开发板量身定制的,包括了对P43 LCD屏幕的支持以及开发板上所有硬件驱动的集成。这使得开发人员能够在嵌入式系统开发过程中快速启动和运行,同时保证了系统的...

    Linux下的单片机LCD驱动的设计.doc

    接下来,文章深入探讨了使用Linux内核驱动LCD的方法。特别是基于framebuffer的驱动程序设计,framebuffer是Linux提供的一种图形设备接口,允许用户空间程序直接访问图形硬件。通过framebuffer,开发者可以创建一个...

    学习韦东山老师嵌入式Linux,基于IMX6ULL开发板的学习过程记录.zip

    在i.MX6ULL开发板上,我们可能需要为未被内核直接支持的硬件编写驱动程序,这需要对Linux内核机制有深入理解。例如,开发一个SPI设备驱动,我们需要理解SPI总线的工作原理,然后按照Linux驱动模型实现。 此外,系统...

    实验正点原子ARM板的LCD驱动

    2. **内核配置**:为了支持LCD驱动,我们需要在Linux内核配置阶段启用对应的驱动选项。这通常通过`make menuconfig`命令完成,找到与LCD屏相关的驱动模块,如“LCD驱动支持”或者特定的LCD控制器选项,并设置为启用...

    ARM Linux平台下LCD控制器的配置及驱动分析.pdf

    在Linux内核中,LCD驱动通常包含在图形子系统中,使用帧缓冲层(Framebuffer layer)来抽象硬件接口。通过设置framebuffer的参数,可以调整LCD的显示属性。同时,Linux内核提供了/dev/fb*设备节点,允许应用程序通过...

    Linux驱动_LCD1

    在Linux内核中,LCD驱动的架构通常基于平台设备模型(Platform Device Model)。LCD驱动程序的核心工作是注册一个平台设备,这在开发板相关的初始化函数`smdk2440_machine_init`中完成。在这个函数中,`s3c2440_...

    D1_Linux_LCD_开发指南1

    4.2.2 menuconfig配置:在Linux内核配置中选择或添加新的LCD驱动选项,以便编译进内核。 4.2.3 屏驱动分解:包括初始化函数、帧缓冲管理、时序设置、信号电平控制等部分。 4.2.4 至4.2.11分别详细解释了延时函数、...

Global site tag (gtag.js) - Google Analytics