日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 嵌入式 > 嵌入式案例Show
[導讀]為了更好的理解安卓的層次關系,本文在RK3399的安卓系統(tǒng)上增加LED燈的外設,并使用APP打開關閉LED燈。以這樣一個最簡單的實例,來演示從上層到底層的調(diào)用過程。首先從最底層的kernel層開始。 一、驅(qū)動開發(fā) Kernel層就是要將LED硬件接入到系統(tǒng),完成驅(qū)動的開發(fā)

為了更好的理解安卓的層次關系,本文在RK3399的安卓系統(tǒng)上增加LED燈的外設,并使用APP打開關閉LED燈。以這樣一個最簡單的實例,來演示從上層到底層的調(diào)用過程。首先從最底層的kernel層開始。


一、驅(qū)動開發(fā)

Kernel層就是要將LED硬件接入到系統(tǒng),完成驅(qū)動的開發(fā)。Linux下的驅(qū)動是使用C語言進行開發(fā)的,可分為三類設備類型:字符設備,塊設備,網(wǎng)絡設備。每種類型的驅(qū)動都有他自有的驅(qū)動框架,學習驅(qū)動開發(fā)就是要熟悉各種驅(qū)動架構(gòu),并根據(jù)實際需求在框架內(nèi)添加內(nèi)容。LED的驅(qū)動我們選擇最簡單的雜項字符類設備驅(qū)動即可。

從原理圖中可以得到兩個GPIO:GPIO1_C7和GPIO1_D0,驅(qū)動三極管來使得LED燈亮滅。

圖:led燈原理圖


1)設備樹文件(kernel/arch/arm64/boot/dts/rockchip/rk3399-nanopi4-common.dtsi)

test-leds{compatible = "test,leds";led1-work = <&gpio1 23 GPIO_ACTIVE_LOW>;led2-work = <&gpio1 24 GPIO_ACTIVE_LOW>;status = "okay";};

2)  驅(qū)動文件(kernel/drivers/gpio/gpio-testled.c)

#include <linux/errno.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/input.h>#include <linux/init.h>#include <linux/serio.h>#include <linux/delay.h>#include <linux/clk.h>#include <linux/gpio.h>#include <linux/platform_device.h>#include <linux/miscdevice.h>#include <linux/of.h>#include <linux/of_device.h>#include <linux/of_address.h>#include <linux/of_platform.h>#include <linux/of_gpio.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/cdev.h>
MODULE_AUTHOR("embeddedtech");MODULE_LICENSE("Dual BSD/GPL");
#define LEDCTRL_MAGIC 'k'#define LED1CTRL_ON_CMD _IO (LEDCTRL_MAGIC, 1)#define LED1CTRL_OFF_CMD _IO (LEDCTRL_MAGIC, 2)#define LED2CTRL_ON_CMD _IO (LEDCTRL_MAGIC, 3)#define LED2CTRL_OFF_CMD _IO (LEDCTRL_MAGIC, 4)
struct led_data {int led1_pin; //led1引腳int led2_pin; //led2引腳};

struct led_data led_info;/** Open the device; in fact, there's nothing to do here.*/int testled_open (struct inode *inode, struct file *filp){return 0;}

ssize_t testled_read(struct file *file, char __user *buff, size_t count, loff_t *offp){return 0;}

ssize_t testled_write(struct file *file, const char __user *buff, size_t count, loff_t *offp){return 0;}

static long testled_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg){ switch (cmd) { case LED1CTRL_ON_CMD: { gpio_direction_output(led_info.led1_pin,1); break; } case LED1CTRL_OFF_CMD: { gpio_direction_output(led_info.led1_pin,0); break; } case LED2CTRL_ON_CMD: { gpio_direction_output(led_info.led2_pin,1); break;} case LED2CTRL_OFF_CMD: {gpio_direction_output(led_info.led2_pin,0); break;} default: { printk("testled compat Default %d\n",cmd); break;}}return 0;}

long testled_ioctl(struct file *file, unsigned int cmd, unsigned long arg){switch (cmd) {case LED1CTRL_ON_CMD: {gpio_direction_output(led_info.led1_pin,1);break;}case LED1CTRL_OFF_CMD: {gpio_direction_output(led_info.led1_pin,0);break;}case LED2CTRL_ON_CMD: {gpio_direction_output(led_info.led2_pin,1);break;}case LED2CTRL_OFF_CMD: {gpio_direction_output(led_info.led2_pin,0);break;}default: {printk("testled Default %d\n",cmd);break;}}return 0;

}

static int testled_release(struct inode *node, struct file *file){return 0;}

/** Our various sub-devices.*//* Device 0 uses remap_pfn_range */static struct file_operations testled_remap_ops = {.owner = THIS_MODULE,.open = testled_open,.release = testled_release,.read = testled_read,.write = testled_write,.unlocked_ioctl = testled_ioctl,.compat_ioctl = testled_compat_ioctl,};

static struct miscdevice testled_misc = {.minor = MISC_DYNAMIC_MINOR,.name = "test-led",.fops = &testled_remap_ops,};/** Module housekeeping.*/

static int testled_probe(struct platform_device *pdev){int ret;struct device_node *led_node = pdev->dev.of_node;//enum of_gpio_flags work_flags;

ret = misc_register(&testled_misc);if(ret < 0){pr_err("testled_misc_register fails!!!\n");return ret;}

led_info.led1_pin = of_get_named_gpio(led_node, "led1-work", 0);if(!gpio_is_valid(led_info.led1_pin)){pr_err("led1 pin invaild: %d",led_info.led1_pin);ret = -ENODEV;goto probe_fail;}

ret = gpio_request(led_info.led1_pin, "led1_pin");if(ret < 0){pr_err("led1 pin request failed.");goto probe_fail;}

led_info.led2_pin = of_get_named_gpio(led_node, "led2-work", 0);if(!gpio_is_valid(led_info.led2_pin)){pr_err("led2 pin invaild: %d",led_info.led2_pin);ret = -ENODEV;goto probe_fail;}

ret = gpio_request(led_info.led2_pin, "led2_pin");if(ret < 0){pr_err("led2 pin request failed.");goto probe_fail;}
printk("led1 pin is: %d,led2 pin is: %d",led_info.led1_pin,led_info.led2_pin);return 0;

probe_fail:

return ret;}

static int testled_remove(struct platform_device *pdev){pr_err("testled_misc_remove!!!\n");misc_deregister(&testled_misc);return 0;}

static struct of_device_id testled_table[] = {{ .compatible = "test,leds",}, //Compatible node must match dts{ },};

static struct platform_driver testled_driver = {.probe = testled_probe,.remove = testled_remove,.driver = {.name = "test_leds",.owner = THIS_MODULE,.of_match_table = testled_table,}};

static int testled_init(void){int ret;ret = platform_driver_register(&testled_driver);if(ret < 0)pr_err("platform_register_driver fails!!!\n");pr_err("platform_register_driver succeeds :ret=%d!!!\n",ret);return ret;}



static void testled_cleanup(void){platform_driver_unregister(&testled_driver);}

module_init(testled_init);module_exit(testled_cleanup);

3)Makefile文件(kernel/drivers/gpio/Makefile)

obj-$(CONFIG_GPIO_TEST_LED) += gpio-testled.o

4) Kconfig文件 (kernel/drivers/gpio/Kconfig)

config GPIO_TEST_LEDbool "select test leds"default y

5)驅(qū)動配置文件(kernel/arch/arm64/configs/nanopi4_nougat_defconfig)

CONFIG_GPIO_TEST_LED=y

6)修改節(jié)點權(quán)限(device/rockchip/common/ueventd.rockchip.rc)

/dev/test_leds 0666 system system
設備驅(qū)動文件在與 dts匹配的關鍵字是 compatible 屬性。即比較驅(qū)動文件中 of_device_id 結(jié)構(gòu)體元素的 .compatible 成員變量和 dts 文件中 node 中 compatible 屬性兩個字符串,匹配成功之后會進行probe,驅(qū)動就被加載進內(nèi)核了。Dts文件可以放入一些數(shù)據(jù)、屬性等,驅(qū)動文件加載是可以來讀取,這樣如果更改硬件管腳等就不需要改動驅(qū)動文件,只改設備樹文件即可,使得驅(qū)動移植和維護更加方便。
Makefile文件、Kconfig文件和驅(qū)動配置文件使得gpio-testled.c的驅(qū)動可以被編譯進內(nèi)核,簡易調(diào)試也可以只在Makefile文件添加 obj-y += gpio-testled.o就行。
驅(qū)動加載成功的標志是在設備的dev/目錄下生成了test-led的設備文件節(jié)點,后面的上層就是以此文件來調(diào)用led驅(qū)動的。


二、驅(qū)動測試

驅(qū)動完成后要測試一下驅(qū)動對外的接口函數(shù)是否正常,可以寫一個簡易的測試代碼。
  1. 測試代碼gpioleds_test.c

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <linux/ioctl.h>
#define LEDCTRL_MAGIC 'k'#define LED1CTRL_ON_CMD _IO (LEDCTRL_MAGIC, 1)#define LED1CTRL_OFF_CMD _IO (LEDCTRL_MAGIC, 2)#define LED2CTRL_ON_CMD _IO (LEDCTRL_MAGIC, 3)#define LED2CTRL_OFF_CMD _IO (LEDCTRL_MAGIC, 4)

int main(){int i = 0;int dev_fd;dev_fd = open("/dev/test-led",O_RDWR | O_NONBLOCK);if ( dev_fd == -1 ) {printf("Cann't open file /dev/test-led\n");exit(1);}printf("Led1 on\n");ioctl (dev_fd, LED1CTRL_ON_CMD,0);getchar();ioctl (dev_fd, LED1CTRL_OFF_CMD,0);printf("led1 off\n");
printf("Led2 on\n");ioctl (dev_fd, LED2CTRL_ON_CMD,0);getchar();ioctl (dev_fd, LED2CTRL_OFF_CMD,0);printf("led2 off\n");
close(dev_fd);return 0;}

2)Android.mkLOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \gpioleds_test.c

LOCAL_SHARED_LIBRARIES := \liblog \libc \libutils \libcrypto \libhardware \

LOCAL_MODULE := gpioleds_test

LOCAL_MODULE_TAGS :=

LOCAL_MODULE_PATH := $(LOCAL_PATH)

LOCAL_CFLAGS +=-D_FORTIFY_SOURCE=0

LOCAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0

include $(BUILD_EXECUTABLE

3)編譯成可執(zhí)行文件

在安卓目錄external/下新建gpioleds_test目錄,將gpioleds_test.c和Android.mk拷貝進目錄,編譯此目錄。
mmm external/gpioleds_test/

完成在目錄下生成二進制文件gpioleds_test??截愡M安卓設備。


4)測試

二進制文件拷貝進安卓設備后,賦予777權(quán)限,然后運行。
Chmod 777 /data/user/gpioleds_test./ data/user/gpioleds_test


掃碼關注我們

看更多嵌入式案例



喜歡本篇內(nèi)容請給我們點個再看

免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅(qū)動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅(qū)動性能的關鍵。

關鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質(zhì)量和效率直接關系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關鍵字: LED 驅(qū)動電源 開關電源

LED驅(qū)動電源是把電源供應轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅(qū)動電源
關閉