基於JZ2440的LED平臺驅動寫法
驅動分層分離
在前面介紹的輸入子系統中,核心層
input.c
,裝置層button.c
包含硬體相關程式碼,軟體層cdev.c
純軟體處理部分。
linux
驅動中有很多類似的驅動形式,例如匯流排驅動platform
平臺裝置模型
platform.c
屬於核心層級別,裝置層device
包含硬體相關程式碼,driver
層包含驅動層相關程式碼屬於比較固化穩定的軟體程式碼,裝置發生改變只要改變裝置層程式碼,規則上只要滿足驅動層程式碼規則要求,理論上完全不用修改驅動層程式碼。裝置層與軟體層分離的好處就是當裝置發生改變時,只需要修改裝置對應部分程式碼,軟體處理部分不用修改。
平臺裝置模型的一般寫法:
- 構造裝置層結構體
- 註冊裝置結構體
- 構造驅動層結構體
- 註冊驅動結構體
- 核心層進行裝置層與驅動層的匹配
- 匹配成功呼叫相關函式進行兩者掛接
基於JZ2440的LED的平臺裝置框架
驅動層
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <asm/gpio.h>
/* 分配/設定/註冊一個platform_driver */
static int __devinit led_probe(struct platform_device *pdev)
{
/* 根據platform_dev資源進行ioremap */
/* 註冊字元裝置 */
printk("led_probe,found led\n");
return 0;
}
static int __devexit led_remove(struct platform_device *pdev)
{
/* 根據platform_dev資源進行iounmap */
/* 登出字元裝置 */
printk("led_remove,remove led\n");
return 0;
}
struct platform_driver led_drv = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "myled",
}
};
static int led_drv_init(void)
{
platform_driver_register(&led_drv);
return 0;
}
static void led_drv_exit(void)
{
platform_driver_unregister(&led_drv);
}
module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
裝置層
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
#include <asm/arch/gpio.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
/* 分配/設定/註冊一個platform_device */
void led_release(struct device *dev)
{
}
static struct resource led_resource[] = {
[0]=
{
.start = 0x56000050,
.end = 0x56000050 + 8 - 1,
.flags = IORESOURCE_MEM,
},
[1]=
{
.start = 4,
.end = 4,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device led_dev = {
.name = "myled",
.id = 0,
.dev = { .release=led_release,
},
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
};
static int led_dev_init(void)
{
platform_device_register(&led_dev);
return 0;
}
static void led_dev_exit(void)
{
platform_device_unregister(&led_dev);
}
module_init(led_dev_init);
module_exit(led_dev_exit);
MODULE_LICENSE("GPL");
程式碼執行效果:
[root@JZ2440 015platform]# insmod led_dev.ko
[root@JZ2440 015platform]# insmod led_drv.ko
led_probe,found led
[root@JZ2440 015platform]# rmmod led_drv.ko
led_remove,remove led
[root@JZ2440 015platform]# rmmod led_dev.ko
[root@JZ2440 015platform]#
將功能豐富完整後的驅動
驅動層
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define DEVICENAME "myled"
static unsigned int major=0;
unsigned int pin=0;
static struct class *myclass=NULL;
static struct class_device *mydev;
static volatile unsigned long *gpfcon=NULL;
static volatile unsigned long *gpfdat=NULL;
#define GPFCON *gpfcon
#define GPFDAT *gpfdat
static int led_open(struct inode *inode, struct file *file)
{
//配置LED管腳模式
GPFCON &=~(0x3<<(pin*2));
GPFCON |= (0x1<<(pin*2));
//預設燈全部關閉
GPFDAT |= ((7<<4));
return 0;
}
static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val;
copy_from_user(&val, buf, count); // copy_to_user();
if (val == 1)
{
// 點燈
GPFDAT &= ~(1<<pin);
}
else
{
// 滅燈
GPFDAT |= (1<<pin);
}
return 0;
}
static struct file_operations my_dev_fops = {
.owner = THIS_MODULE, /* 這是一個巨集,推向編譯模組時自動建立的__this_module變數 */
.open = led_open,
.write = led_write,
};
/* 分配/設定/註冊一個platform_driver */
static int __devinit led_probe(struct platform_device *pdev)
{
/* 根據platform_dev資源進行ioremap */
struct resource *res;
res = platform_get_resource(pdev,IORESOURCE_MEM,0);
gpfcon = ioremap(res->start,res->end-res->start+1);
gpfdat=gpfcon+1;
res=platform_get_resource(pdev,IORESOURCE_IRQ,0);
pin=res->start;
/* 註冊字元裝置 */
major = register_chrdev(0,DEVICENAME, &my_dev_fops); // 註冊, 告訴核心
myclass = class_create(THIS_MODULE,DEVICENAME);
mydev=class_device_create(myclass, NULL, MKDEV(major,0), NULL, "led");
printk("led_probe,found led\n");
return 0;
}
static int __devexit led_remove(struct platform_device *pdev)
{
/* 根據platform_dev資源進行iounmap */
/* 登出字元裝置 */
iounmap(gpfcon);
class_device_unregister(mydev);
class_destroy(myclass);
unregister_chrdev(major, DEVICENAME); // 解除安裝
printk("led_remove,remove led\n");
return 0;
}
struct platform_driver led_drv = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "myled",
}
};
static int led_drv_init(void)
{
platform_driver_register(&led_drv);
return 0;
}
static void led_drv_exit(void)
{
platform_driver_unregister(&led_drv);
}
module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
裝置層
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
#include <asm/arch/gpio.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
/* 分配/設定/註冊一個platform_device */
void led_release(struct device *dev)
{
}
static struct resource led_resource[] = {
[0]=
{
.start = 0x56000050,
.end = 0x56000050 + 8 - 1,
.flags = IORESOURCE_MEM,
},
[1]=
{
.start = 4,
.end = 4,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device led_dev = {
.name = "myled",
.id = 0,
.dev = { .release=led_release,},
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
};
static int led_dev_init(void)
{
platform_device_register(&led_dev);
return 0;
}
static void led_dev_exit(void)
{
platform_device_unregister(&led_dev);
}
module_init(led_dev_init);
module_exit(led_dev_exit);
MODULE_LICENSE("GPL");
app
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
int main()
{
int fd;
char tmp1='0',tmp2;
fd = open("/dev/led",O_RDWR);
if(fd<0)
printf("led open is fail\n");
else
printf("led open success\n");
write(fd,&tmp1,1);
sleep(2);
write(fd,&tmp2,1);
close(fd);
return 0;
}
相關推薦
基於JZ2440的LED平臺驅動寫法
驅動分層分離 在前面介紹的輸入子系統中,核心層input.c,裝置層button.c包含硬體相關程式碼,軟體層cdev.c純軟體處理部分。 linux驅動中有很多類似的驅動形式,例如匯流排驅動platform平臺裝置模型 platform.c
SylixOS 基於STM32平臺的GPIO模仿I2C總線的驅動開發流程
STM32 GPIO模仿I2C 1.概述 本文檔以STM32F767平臺為例,詳細介紹SylixOS上GPIO模仿I2C總線的驅動開發流程。 2.初始化 GPIO模仿的I2C總線的初始化,實際上是I2C總線的SDA和SCL的GPIO管腳初始化。初始化流程如圖 2.1所示。 圖 2.1 I2C初始化流程
基於arm平臺linux下USB音效卡驅動安裝和使用
核心配置 <*> Advanced Linux Sound Architecture —> usb音效卡安裝 1.apt-get install alsa-base 2
基於qualcomm平臺的camera 驅動詳解
前言: 一、Android camera架構 在framework中,camera主要是通過以下庫來協同工作的: libandroid_runtime.so、libui.so、libcamerase
基於335X平臺的UBOOT中交換芯片驅動移植
-m 驅動移植 暫時 time 函數 down appears avi 使用 基於335X平臺的UBOOT中交換芯片驅動移植 一、軟硬件平臺資料 1、開發板:創龍AM3359核心板,網口采用RMII形式。 2、UBOOT版本:U-Boot-2016.05,
基於.NET平臺常用的框架整理
open producer oauth isp mps exce too cms table 自從學習.NET以來,優雅的編程風格,極度簡單的可擴展性,足夠強大開發工具,極小的學習曲線,讓我對這個平臺產生了濃厚的興趣,在工作和學習中也積累了一些開源的組件,就目前想到的先整理
阿裏雲平臺微信告警(基於收費平臺)
設置 登陸 用戶 升級 div 不能 ges 郵箱 es2017 基於現在大多數人使用微信的眾多性,並且發現當阿裏雲發生告警時,郵箱的報警數太多,(像本人zabbix有郵箱告警,zabbix分經典網絡和專有網絡的報警,還有物理機的告警,都是分開平臺監控的。)所以想到能不能把
圖像處理(二十一)基於數據驅動的人臉卡通動畫生成-Siggraph Asia 2014
ssi 原來 大於 搜索 nbsp details 一起 fontsize man http://blog.csdn.net/garfielder007/article/details/50582018 在現實生活中,我們經常會去評價一個人,長得是否漂亮、是不是帥哥美女,然
基於windows平臺的命令行軟件安裝工具Chocolatey的安裝
rsh 運行 如果 安裝軟件 安裝 mark web nload install 本文介紹Chocolatey的安裝和使用 Chocolatey 這是基於.NET Framework 4以上的windows安裝軟件的命令行工具 安裝 第一步,打開你的powershell.
基於Zynq平臺的EtherCAT主站方案實現
硬件架構 pan nop sdp 裏的 GC inline 高精 class 作者:陳秋苑 謝曉鋒 陳海煥 廣州虹科電子科技有限公司 摘 要:EtherCAT 是開放的實時以太網通訊協議,由德國倍福自動化有限公司研發。EtherCAT 具有高性能、低成本、容易使用
MapReduce編程模型詳解(基於Windows平臺Eclipse)
lib read 找到 lin @override ext logs 設置 otf 本文基於Windows平臺Eclipse,以使用MapReduce編程模型統計文本文件中相同單詞的個數來詳述了整個編程流程及需要註意的地方。不當之處還請留言指出。 前期準備 hadoop集群
基於代碼驅動:處理有依賴關系接口
gist 這樣的 equal 測試框架 return user 影響 RR 字段 數據驅動和代碼驅動的區別: 使用數據驅動好處: - 代碼復用率高。同一測試邏輯編寫一次,可以被多條測試數據復用,提高了測試代碼的復用率,同時可以提高測試腳本的編寫效率。 -
platform 平臺驅動——設備的寫作流程
vim num 編譯 說明 rds clas config compile HA 說明:在內核源碼裏會有很多已經實現的驅動,對於我們來說只需要寫好設備文件即可,但是我們如何知道驅動需要那些數據,以及有哪些驅動呢? 解決: 1.首先在內核源碼目錄下執行執行菜單配置命令:
基於Impala平臺打造交互查詢系統
來講 結合 Planner cnblogs 穩定 文件的 表數據 執行 原創 本文來自網易雲社區 原創: 蔣鴻翔 DataFunTalk 本文根據網易大數據蔣鴻翔老師DataFun Talk——“大數據從底層處理到數據驅動業務”中分享的《基於Impala平臺打造交互
基於Android平臺的圖書管理系統的制作(1)
teacher stat load over sta ews 來講 androi 管理系 在學習了郭神的第一行代碼前半段之後,想通過一次實踐來完成對已學知識的鞏固。於是碼下了這個圖書管理系統客戶端。 IDE Android studio,語言 JAVA、XML; 在剛開始設
基於Android平臺的圖書管理系統的制作(3)
所有 .lib break raw gravity 要點 () 功能介紹 錯誤 前兩篇介紹了主頁面和Student,這一篇來講Book類和工作人員。 Book是圖書管理系統的核心,查書,借書,還書,增加書都與Book類息息相關。Book類的設計很簡單:包含信息:名稱、作者、
基於.NET平臺常用的框架整理(轉)
god mat 訂閱 socket 丟失 訪問性 pdf 分布式系 雲計 自從學習.NET以來,優雅的編程風格,極度簡單的可擴展性,足夠強大開發工具,極小的學習曲線,讓我對這個平臺產生了濃厚的興趣,在工作和學習中也積累了一些開源的組件,就目前想到的先整理於此,如果再想到,就
46.Linux-分析rc紅外遙控平臺驅動框架,修改內核的NEC解碼函數BUG(1)
進入 checksum 開始 紅外遙控 中斷函數 height clas margin 復習 內核版本 : Linux 3.10.14 rc紅外接收類型: GPIO 類型的NEC紅外編碼 本章內容 1) rc體系結構分析 2)
ASoC平臺驅動程式
ASoC平臺驅動程式 ASoC平臺驅動程式類可分為音訊DMA驅動程式,SoC DAI驅動程式和DSP驅動程式。平臺驅動程式僅針對SoC CPU,並且必須沒有特定於板的程式碼。 音訊 平臺DMA驅動程式可選擇支援以下ALSA操作: - / * SoC音訊操作* / struct snd
創龍基於C66x平臺DSP與FPGA通信測試
roc 步驟 pcie 進入 完成後 圖片 process afa 打開 本文為基於創龍TL665xF-EasyEVM開發板的DSP與FPGA通信測試。TL665xF-EasyEV開發板的簡介紹如下:由核心板+底板構成。核心板DSP端采用單核TMS320C6655或雙核TM