十二、linux LED初始化
一、硬件原理圖 ??
????????我們今天的目標是將itop4412開發板上的兩個led燈控制起來。先看一下原理圖:
?
二、GPIO需要的接口和定義
1、Linux中申請GPIO的頭文件
????????– include/linux/gpio.h
主要提供一些GPIO操作函數:
2、三星平臺的GPIO配置函數頭文件
????????– arch/arm/plat-samsung/include/plat/gpio-cfg.h
? ? ? ? – 包括三星所有處理器的配置函數
3、三星平臺EXYNOS系列平臺,GPIO配置參數宏定義頭文件
????????– arch/arm/mach-exynos/include/mach/gpio.h
????????– GPIO管腳拉高拉低配置參數等等
????????– 配置參數的宏定義應該在arch/arm/plat-samsung/include/plat/gpio-cfg.h文件中
4、三星平臺4412平臺,GPIO宏定義頭文件(包含在頭文件gpio.h中)
????????– arch/arm/mach-exynos/include/mach/gpio-exynos4.h
????????– 包括4412處理器所有的GPIO的宏定義
三、GPIO驅動初始化代碼
? linuxGPIO申請函數和賦值函數
????????– gpio_request
????????– gpio_set_value
? 三星平臺配置GPIO函數
????????– s3c_gpio_cfgpin
? GPIO配置輸出模式的宏變量
????????– S3C_GPIO_OUTPUT
1、leds驅動程序 leds.c :
#include <linux/init.h> #include <linux/module.h>/*驅動注冊的頭文件,包含驅動的結構體和注冊和卸載的函數*/ #include <linux/platform_device.h> /*注冊雜項設備頭文件*/ #include <linux/miscdevice.h> /*注冊設備節點的文件結構體*/ #include <linux/fs.h>/*Linux中申請GPIO的頭文件*/ #include <linux/gpio.h> /*三星平臺的GPIO配置函數頭文件*/ /*三星平臺EXYNOS系列平臺,GPIO配置參數宏定義頭文件*/ #include <plat/gpio-cfg.h> #include <mach/gpio.h> /*三星平臺4412平臺,GPIO宏定義頭文件*/ #include <mach/gpio-exynos4.h>#define DRIVER_NAME "itop4412_led_ctl" #define DEVICE_NAME "itop4412_led_ctl" #define LED_NUM 2MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("TOPEET");static int led_gpios[LED_NUM] = {EXYNOS4_GPL2(0),EXYNOS4_GPK1(1), };static long itop4412_led_ioctl( struct file *files, unsigned int cmd, unsigned long arg){printk("cmd is %d,arg is %d\n", cmd, arg);if(cmd > 1){printk("cmd is 0 or 1\n");}if(arg >= LED_NUM){printk("arg is < %d\n",LED_NUM);}gpio_set_value(led_gpios[arg],cmd);return 0; }static int leds_open(struct inode *inode, struct file *file){printk(KERN_EMERG "leds open\n");return 0; }static int leds_release(struct inode *inode, struct file *file){printk(KERN_EMERG "leds release\n");return 0; }static struct file_operations leds_ops = {.owner = THIS_MODULE,.open = leds_open,.release = leds_release,.unlocked_ioctl = itop4412_led_ioctl, };static struct miscdevice leds_dev = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &leds_ops, };static int leds_probe(struct platform_device *pdv){int i;int ret;printk(KERN_EMERG "\t leds enter \n");for(i = 0; i < LED_NUM; i++){ret = gpio_request(led_gpios[i], "LED"); // 請求GPIOif (ret) {printk("%s: request GPIO %d for LED failed, ret = %d\n", DRIVER_NAME, i, ret);}else{s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);gpio_set_value(led_gpios[i], 1); }}misc_register(&leds_dev);if(ret<0){printk("leds:register device failed!\n");goto exit;}return 0;exit:misc_deregister(&leds_dev);return ret; }static int leds_remove(struct platform_device *pdv){printk(KERN_EMERG "\t remove\n");misc_deregister(&leds_dev);return 0; }static void leds_shutdown(struct platform_device *pdv){; }static int leds_suspend(struct platform_device *pdv,pm_message_t pmt){return 0; }static int leds_resume(struct platform_device *pdv){return 0; }struct platform_driver leds_driver = {.probe = leds_probe,.remove = leds_remove,.shutdown = leds_shutdown,.suspend = leds_suspend,.resume = leds_resume,.driver = {.name = DRIVER_NAME,.owner = THIS_MODULE,} };static int leds_init(void) {int DriverState;printk(KERN_EMERG "leds_init enter!\n");DriverState = platform_driver_register(&leds_driver);printk(KERN_EMERG "\tDriverState is %d\n",DriverState);return 0; }static void leds_exit(void) {printk(KERN_EMERG "leds_exit exit!\n");platform_driver_unregister(&leds_driver); }module_init(leds_init); module_exit(leds_exit);2、驅動配套Makefile,內核源碼路徑和模塊名稱記得改成匹配你自己的情況,然后把這1、2放一起,make一下。生成leds.ko
#!/bin/bash #通知編譯器我們要編譯模塊的哪些源碼 #這里是編譯itop4412_hello.c這個文件編譯成中間文件itop4412_hello.o obj-m += leds.o #源碼目錄變量,這里用戶需要根據實際情況選擇路徑 #作者是將Linux的源碼拷貝到目錄/home/topeet/android4.0下并解壓的 KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0#當前目錄變量 PWD ?= $(shell pwd)#make命名默認尋找第一個目標 #make -C就是指調用執行的路徑 #$(KDIR)Linux源碼目錄,作者這里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0 #$(PWD)當前目錄變量 #modules要執行的操作 all:make -C $(KDIR) M=$(PWD) modules#make clean執行的操作是刪除后綴為o的文件 clean:rm -rf *.o3、調用驅動程序的應用代碼 leds_app.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h>#include <string.h>#define LEDS 2int main(int argc, char *argv[]){int fd, i, cmd = 2, led = 2;char *led_ctl_node = "/dev/itop4412_led_ctl";char *led0 = "0"; char *led1 = "1";char *cmd0 = "0"; char *cmd1 = "1";if(strcmp(argv[1], led0) == 0){led = 0;printf("led is 0!\n");}if(strcmp(argv[1], led1) == 0){led = 1;printf("led is 1!\n");}if(strcmp(argv[2], cmd0) == 0){cmd = 0;printf("cmd is 0!\n");}if(strcmp(argv[2], cmd1) == 0){cmd = 1;printf("cmd is 1!\n");}/*O_RDWR只讀打開,O_NDELAY非阻塞方式*/ if((fd = open(led_ctl_node, O_RDWR | O_NDELAY)) < 0){printf("app open %s failed!\n", led_ctl_node);}else{printf("app open %s success!\n", led_ctl_node);ioctl(fd, cmd, led);printf("app ioctl %s ,led is %d,cmd is %d!\n", led_ctl_node, led, cmd);}close(fd); }通過arm-none-linux-gnueabi-gcc -o leds_app leds_app.c -static編譯一下。生成leds_app。
4、在drivers/char/Kconfig添加一個menuconfig選項
????????具體看<linux內核驅動裁剪>。
?5、配置menuconfig
?6、設備注冊
?????????在arch/arm/mach-exynos/mach-itop4412.c下,添加如下代碼,具體看《linux虛擬平臺設備注冊》
?7、編譯內核,重新下載內核文件zImage
?8、掛載leds.ko模塊,記得一定要先掛載。
9、運行leds_app。如下:
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的十二、linux LED初始化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 十二、linux GPIO初始化
- 下一篇: 十三、linux 内核驱动模块传参数