1. 程式人生 > >Linux Arm上的RGB液晶屏驅動開發遇到的問題總結

Linux Arm上的RGB液晶屏驅動開發遇到的問題總結

(基於三星Exynos 4412 / iTop4412精英版開發板)

1. 開發前準備和核心編譯

將Linux核心iTop4412_Kernel_3.0_20180508.tar.gz複製到虛擬機器,解壓。

進入解壓後的資料夾,使用命令cp config_for_linux_scp_elite .config覆蓋配置檔案。

執行make zImage編譯核心。

注意:

​ 此處的編譯是必須的。否則在下面僅編譯模組的時候會報錯。

2. 第一個最簡驅動

2.1 驅動程式碼

mini_linux_module.c:

#include <linux/init.h>
//init.h - 包含初始化巨集定義的標頭檔案,程式碼中的函式module_init和module_exit在此檔案中 #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); //本定義必須,宣告GPL協議 MODULE_AUTHOR("TOPEET"); //宣告程式碼/驅動作者,懶得改了 static int hello_init(void) { printk(KERN_EMERG "HELLO WORLD enter!\n"); //向核心列印資訊,KERN_EMERG為優先順序最高的列印資訊,LVL:0 //預設級別為4
return 0; } static void hello_exit(void) { printk(KERN_EMERG "HELLO WORLD exit!\n"); } module_init(hello_init); //驅動載入(insmod)時執行的函式,引數為初始化函式的函式指標 module_exit(hello_exit); //驅動解除安裝(rmmod)時執行的函式,引數為驅動解除安裝函式的函式指標

可通過修改/proc/sys/kernel/printk來修改printk列印日誌的等級。

檔案內容及含義如下:

[root@iTOP-4412
]# cat /proc/sys/kernel/printk 7 4 1 7

控制檯日誌級別:優先順序高於該值的訊息將被列印至控制檯

預設的訊息日誌級別:將用該優先順序來列印沒有優先順序的訊息

最低的控制檯日誌級別:控制檯日誌級別可被設定的最小值(最高優先順序)

預設的控制檯日誌級別:控制檯日誌級別的預設值

數值越小,優先順序越高

2.2 Makefile

#!/bin/bash
#通知編譯器我們要編譯模組的哪些原始碼
#這裡是編譯itop4412_hello.c這個檔案編譯成中間檔案itop4412_hello.o
obj-m += mini_linux_module.o 

#原始碼目錄變數,這裡使用者需要根據實際情況選擇路徑
#注意:這裡的原始碼目錄下的原始碼必須編譯過一次!
KDIR := /home/clair/iTop4412_Kernel_3.0

#當前目錄變數
PWD ?= $(shell pwd)

#make命名預設尋找第一個目標
#make -C就是指呼叫執行的路徑
#$(KDIR)Linux原始碼目錄,這裡指的是/home/clair/iTop4412_Kernel_3.0
#$(PWD)當前目錄變數
#modules要執行的操作
all:
    make -C $(KDIR) M=$(PWD) modules

#make clean執行的操作是刪除字尾為o的檔案
clean:
    rm -rf *.o

2.3 編譯&載入驅動模組

將mini_linux_module.c和Makefile放在同一個目錄下,make clean;make進行編譯。

生成的檔案如下所示:

其中,ko檔案是需要載入的核心驅動模組檔案。

編譯時會自動生成mini_linux_module.mod.c檔案。

將ko檔案複製到開發板,使用insmod裝載驅動,可以看到執行了驅動中的函式:

lsmod檢視已裝載模組:

這裡寫圖片描述

rmmod解除安裝模組:

解除安裝模組時可能會出現錯誤,解決方法如圖所示,根據提示新建缺少的目錄即可。

3. 裝置驅動的註冊

首先,需要進入核心裝置平臺檔案(此處為iTop4412_Kernel_3.0/arch/arm/mach-exynos/mach-itop4412.c

新增自己的裝置驅動的platform_device結構體(這裡跳過了KConfig和Menuconfig相關的設定):

struct platform_device s3c_device_gpio_rgb_ctl = {
        .name   = "rgb_gpio_ctl",
        .id             = -1,
};

注意:這裡的.name與驅動的platform_driver.driver.name必須相同。

之後在同一個檔案的結構體static struct platform_device *smdk4x12_devices[] __initdata的定義中新增上述結構體的引用如下:

static struct platform_device *smdk4x12_devices[] __initdata = {
    ...
    #ifdef CONFIG_LEDS_CTL
            &s3c_device_leds_ctl,
    #endif
            &s3c_device_gpio_rgb_ctl, //add here

    #ifdef CONFIG_BUZZER_CTL
            &s3c_device_buzzer_ctl,
    #endif
}

編譯核心,生成zImage並燒錄zImage映象。

同理,在自己編寫的驅動中的裝置名稱也要定義為相同名稱:

#define DRIVER_NAME "rgb_gpio_ctl"   //這裡的name必須和核心中註冊的名字一樣!!!
...
struct platform_driver hello_driver = {
    .probe = hello_probe,    //insmod,設備註冊匹配成功後,自動執行該函式
    .remove = hello_remove,    //rmmod執行後,裝置反註冊成功後執行
    .shutdown = hello_shutdown,
    .suspend = hello_suspend,
    .resume = hello_resume,
    .driver = {
        .name = DRIVER_NAME,    //這裡的name必須和核心中註冊的名字一樣!!!
        .owner = THIS_MODULE,
    }
};

在驅動的init函式和exit函式裡,增加對裝置節點的註冊和反註冊:

static int hello_init(void)
{
    int DriverState;

    printk(KERN_EMERG "HELLO WORLD enter!\n");
    DriverState = platform_driver_register(&hello_driver);   //註冊裝置節點

    printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "HELLO WORLD exit!\n");

    platform_driver_unregister(&hello_driver);        //反註冊裝置節點
}

module_init(hello_init);
module_exit(hello_exit);

註冊和反註冊使用函式platform_driver_registerplatform_driver_unregister實現。

編譯ko後insmod,可以看到Linux已經把啟動匹配成功了,並且執行了驅動中的.probe對應的hello_probe函式:

static int hello_probe(struct platform_device *pdv){

    printk(KERN_EMERG "\tinitialized\n");

    return 0;
}

注意:

​ insmod時,Linux會將要載入的驅動的platform_driver.driver.name和核心裝置平臺檔案中所有註冊的platform_device結構體的.name進行匹配,並且僅在匹配成功的情況下,才執行.probe指向的函式。

​ 在本例中,若不修改核心,則insmod之後(準確點說是insmod之後,通過platform_driver_register函式註冊驅動時),系統無法匹配裝置,會出現成功insmod但是不執行probe函式的情況。

4. Misc device(雜項裝置)的裝置節點

雜項裝置能夠提供一個裝置節點(裝置檔案)供作業系統訪問,以實現對裝置的操作。

在程式中定義file_operations結構體和對應函式,以宣告該裝置檔案對應的操作:

static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){
    printk("cmd is %d,arg is %d\n",cmd,arg);
    return 0;
}

static int hello_release(struct inode *inode, struct file *file){
    printk(KERN_EMERG "hello release\n");
    return 0;
}

static int hello_open(struct inode *inode, struct file *file){
    printk(KERN_EMERG "hello open\n");
    return 0;
}

static struct file_operations hello_ops = {
    .owner = THIS_MODULE,
    .open = hello_open,         //使用open開啟裝置檔案時執行的操作
    .release = hello_release,   //使用close函式關閉裝置檔案執行的操作
    .unlocked_ioctl = hello_ioctl,  //使用ioctl操作裝置檔案時執行的操作
};

宣告結構體後,在probe和remove函式裡對節點進行註冊(misc_register)和反註冊(misc_deregister):

static int hello_probe(struct platform_device *pdv){
    printk(KERN_EMERG "\tinitialized\n");
    misc_register(&hello_dev);     //雜項裝置節點註冊
    return 0;
}

static int hello_remove(struct platform_device *pdv){
    printk(KERN_EMERG "\tremove\n");
    misc_deregister(&hello_dev);    //雜項裝置節點反註冊
    return 0;
}

5. GPIO的操作

5.1 從電路圖分析GPIO相關資訊

底板原理圖上找LCD相關的部分,確定引腳網路標號。

在對應的核心板原理圖上檢視對應的GPIO口和GPIO口供電電壓:

通過GPIO口供電電壓為VDDQ_LCD可以找到對應的電壓控制引腳是電源晶片的VDDIOAP_18:

搜尋可知,VDDIOAP_18的電壓由電壓晶片的VLDO3決定。

因此,若修改電源晶片的VLDO3電壓,就可以實現調整輸出電平。

實際測試時,修改Kernel下的相關內容會出錯,因此只能使用電平轉換晶片74ALVC164245實現1.8V到3.3V的轉換。

使用該晶片時,Vccb**必須**要大於Vcca。

5.2 GPIO口相關操作

5.2.1 GPIO口的定義

GPIO口相關的定義在arch\arm\mach-exynos\include\mach\gpio-exynos4.h下。

各GPIO口的定義對應關係如下:

例如,對應F2_0的GPIO的巨集定義是:EXYNOS4_GPF2(0)

5.2.2 GPIO請求和釋放

要操作GPIO,首先需要在系統中對GPIO進行申請,這樣就可以阻止其他驅動重複使用GPIO。

申請的函式如下:

int gpio_request(unsigned gpio, const char *label)

第一個引數是GPIO,第二個引數是給這個佔用起的名字。

例如:

static int rgb_lcd_gpios[] =
{
    EXYNOS4_GPF2(0), EXYNOS4_GPF1(7), EXYNOS4_GPF1(3), EXYNOS4_GPF1(2),
    EXYNOS4_GPF1(1), EXYNOS4_GPF1(0), EXYNOS4_GPF0(2), EXYNOS4_GPF0(1),
    EXYNOS4_GPF2(1), EXYNOS4_GPF2(2), EXYNOS4_GPF2(7), EXYNOS4_GPF3(0),
    EXYNOS4_GPF3(1)
};
//...
gpio_request(rgb_lcd_gpios[i], "LED");

返回值為0則操作成功。

在不使用GPIO時,需要進行釋放。

使用函式gpio_free實現:

for(i = 0; i < LED_NUM; i++)
{
    gpio_free(rgb_lcd_gpios[i]);
}

5.2.3 GPIO的方向、輸出、讀取、上下拉

GPIO的輸入輸出、模式選擇使用s3c_gpio_cfgpin設定。

例如,將F2_0設定為輸出:s3c_gpio_cfgpin(EXYNOS4_GPF2(0), S3C_GPIO_OUTPUT);

相關的選項定義如下:

#define S3C_GPIO_SPECIAL_MARK   (0xfffffff0)
#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x))

/* Defines for generic pin configurations */
#define S3C_GPIO_INPUT  (S3C_GPIO_SPECIAL(0))
#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))
#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))

#define s3c_gpio_is_cfg_special(_cfg) \
    (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)

GPIO的輸出電平使用函式gpio_set_value控制。

例如:gpio_set_value(EXYNOS4_GPF2(0), 1);輸出高電平。

GPIO讀取使用函式gpio_get_value實現。

例如:int gpio = gpio_get_value(EXYNOS4_GPF2(0))

GPIO的上下拉配置使用s3c_gpio_setpull實現。

例如設定為無上下拉:s3c_gpio_setpull(DATA_PORT[i],S3C_GPIO_PULL_NONE);

相關定義:

#define S3C_GPIO_PULL_NONE  ((__force s3c_gpio_pull_t)0x00)
#define S3C_GPIO_PULL_DOWN  ((__force s3c_gpio_pull_t)0x01)
#define S3C_GPIO_PULL_UP    ((__force s3c_gpio_pull_t)0x02)

6. 延時

Linux中提供了常用的延時函式:(忙等待)

包含標頭檔案:

#include <linux/delay.h>

秒級延時:delay(x)

毫秒延時:mdelay(x)

微秒延時:udelay(x)

納秒級別延時ndelay(x)和平臺標頭檔案相關,一般包含在include/asm-???/delay.h中。

除了delay類之外,還有sleep類函式也可以實現該效果。

相關推薦

Linux ArmRGB液晶驅動開發遇到的問題總結

(基於三星Exynos 4412 / iTop4412精英版開發板) 1. 開發前準備和核心編譯 將Linux核心iTop4412_Kernel_3.0_20180508.tar.gz複製到虛擬機器,解壓。 進入解壓後的資料夾,使用命令cp confi

Linux裝置驅動第一天學習筆記(如何將系統在開發執行起來、驅動開發基本步驟)

如何將系統在開發板上執行起來? 4.0 交叉編譯器的獲取?廠家提供 網上下載(廠家確認) 4.1 uboot進行操作? 1,解壓廠家原始碼 2,進入原始碼 3,make distclean 徹底刪除原始碼的目標、臨時檔案 4,make xxx_c

stm32驅動LCD12864液晶驅動程式,親測可行,複製直接能用!

廢話不多說,直接貼程式,你自己複製過去即可,免得我通過把工程上傳的方式,你下載還得需要c幣,這個現在很貴呀!!! 就兩個檔案,LCD12864.h和LCD12864.c,自己複製過去後,改一下引腳即可 (如果你連改引腳都不會,那你看來是初初學者,那你自己百度吧),微控制器

i.mx6 lvds介面的DE模式液晶驅動除錯

我這篇文章主要講述i.mx6 平臺下 採用DE模式的lvds液晶屏的驅動除錯, 閱讀該文章之前請先閱讀如下兩篇我轉載的文章,這兩篇文章是理解我這篇文章的基礎知識。 詳細閱讀並理解這兩篇文章之後,就會對液晶屏顯示的關鍵結構體的各個引數有一個詳細的瞭解。 Linux核心

如何快速搭建微控制器液晶介面開發速度

大家看見這個標題時候可不要誤認為我這有什麼所見只所得的小工具。 我是有次在網上看見人這樣使用的,也由於自己經常會用微控制器編寫介面,但是每次都要編譯下載。這個過程很浪費時間。 那我們能不能在VC++裡編寫一個模擬液晶屏介面在上面把介面和按鍵動作都調好,然後移植到微控制器裡,

HT1621B斷碼晶片液晶驅動程式

#include <reg51.H> #include <intrins.h> #define uchar unsigned char #define uint unsigned int #define _Nop() _nop_();_nop_(

Linux字元驅動開發學習總結

 linux驅動編寫(虛擬字元裝置編寫)     昨天我們說了一些簡單模組編寫方法,但是終歸沒有涉及到裝置的編寫內容,今天我們就可以瞭解一下相關方面的內容,並且用一個例項來說明在linux上面裝置是如何編寫的。 因為我們是在pc linux上學習驅動的,因此暫時沒有真實的

Linux + ARM驅動開發環境配置(核心配置與編譯)

要想編寫驅動,首先是建立核心目錄樹。 ** 1、檢視ARM開發板的核心版本 ** uname -a 我的arm開發板的版本是3.4.39 ** 2、安裝必要的軟體包 ** sudo apt-get install build-essentia

linux-arm筆記2:如何在ubuntu安裝ftp,並且用ftp向arm開發傳檔案

[email protected]:~$ ftp 192.168.1.109    //arm開發板ip Connected to 192.168.1.109. 220 FriendlyARM FTP server (Version 6.4/OpenBSD/Linux-ftpd-0.17) read

ARM開發板的嵌入式linux系統執行的QT程式,必須得要在linux裡用QT編嗎

最近在做有關嵌入式的東西,很多不懂。 1、想在板子上執行用QT編好的程式,必須要在PC的linux系統裡用QT編嗎? 2、在windows系統裡編好的QT程式,經過交叉編譯後能直接執行在板子上嗎?還是板子需要弄個QT環境啥的?就是往裡面安個相同版本的QT? 謝謝。。。。。

如何在ARM開發板的嵌入式linux系統執行的QT程式

最近在做有關嵌入式的東西,很多不懂。 1、想在板子上執行用QT編好的程式,必須要在PC的linux系統裡用QT編嗎? 2、在windows系統裡編好的QT程式,經過交叉編譯後能直接執行在板子上嗎?還是板子需要弄個QT環境啥的?就是往裡面安個相同版本的QT? 謝謝。。。。。

stm32f4開發驅動LCD液晶的個人總結

研究了幾天的F4的FSMC方式驅動觸控式螢幕,得到一些認識,現在列舉如下,流水帳般沒有組織的記錄僅供自己以後參考 使用的是一款叫微雪電子的F407的開發板,但是他們的客服卻不太願解答使用者提出的問題。 觸控式螢幕是以前購買火牛的時候帶的一塊LCD屏,屏上有HY32D字樣

《Linux4.0裝置驅動開發詳解》筆記--第十八章:ARM Linux裝置樹

18.1 ARM裝置樹簡介 裝置舒適一種描述印鑑的資料結構,它起源於OpenFirmware(OF) 採用裝置樹前後對比: 採用裝置樹之前:ARM架構的板極硬體細節過多的被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx中

linux驅動開發之蜂鳴器驅動源碼分析(一)

linux 蜂鳴器 驅動 蜂鳴器的驅動源碼在/driver/char/buzzer/x210-buzzer.c文件中,源碼如下#include <linux/module.h> #include <linux/kernel.h> #include <linux

linux驅動開發之framebuffer應用編程實踐(一)

linux驅動開發之framebuffer驅動 1、framebuffer應用編程 (1)打開設備文件 (2)獲取設備信息 宏定義的命令在/linux/fb.h中 不可變信息FSCREENINFO,使用ioctl參數有FBIOGET_FSCREENINFO宏名,表示用ioctl從

linux驅動開發記錄

when off ide def pos inux adc version red inode: include/linux/fs.h 1 /* 2 * Keep mostly read-only and often accessed (especially for

Hasen的linux設備驅動開發學習之旅--時鐘

interval 好的 mask 再次 ask 中斷處理程序 eas 中斷 基礎 /** * Author:hasen * 參考 :《linux設備驅動開發具體解釋》 * 簡單介紹:android小菜鳥的linux * 設備驅動開發學習之

VS2017開發Linux平臺的程序

開發環境 聯機 targe 由於 線程庫 聽說 pan 裝包 參數 重裝系統後安裝VS2015時卡住了,於是試試看VS2017怎樣,聽說還支持調Linux。發現VS2017跟12/13/15又有了新的飛躍,竟然支持模塊化下載,對於我這種主要寫C++簡直是個福音,勾了Linu

linux驅動開發:用戶空間操作LCD顯示簡單的圖片【轉】

res fin blue var chang uil print views statistic 轉自:http://blog.csdn.net/changliang7731/article/details/53074616 上一章我們簡單介紹了LCD的一些基本原

Linux內核(17) - 高效學習Linux驅動開發

橋梁 是我 href 即使 搭建 技術分享 來看 probe 通信 這本《Linux內核修煉之道》已經開賣(網上的鏈接為: 卓越、當當、china-pub ),雖然是嚴肅文學,但為了保證流暢性,大部分文字我還都是斟詞灼句,反復的念幾遍才寫上去的,盡量考慮到寫上去的每段話能夠