Rk3568驅動開發_GPIO點亮LED_12

需求:

用配置寄存器方式控制點燈非常原始,現在采用更方便的Linux提供的pctrl和gpio子系統編寫字符驅動

1.設備樹配置:
在這里插入圖片描述
現將開發板中呼吸燈關閉掉防止占用到我需要使用的引腳

在這里插入圖片描述

	/* Narnat 2025-5-29 RK3568 GPIO 無需設置pinctrl*/gpioled{compatible = "atkrk3568-gpio-led";led-gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;status = "okay";};

下圖為設備樹中GPIO0的地址
在這里插入圖片描述

在設備樹根節點下添加gpioled節點,標明引腳,配置完設備樹后將kernel單獨編譯,將生成的boot.img燒到設備中可以看到如下節點:
在這里插入圖片描述
可以用cat讀取相關信息

2.驅動編寫:

驅動中需要讀取上述gpioled設備節點找到對應的引腳,向內核申請這個引腳的使用權gpio_request(gpioled.led_gpio, “LED-GPIO”);這樣能防止多個驅動程序搶奪一個引腳問題,申請使用權成功后就能使用Linux自帶的GPIO函數了ret = gpio_direction_output(gpioled.led_gpio, 0);然后就是在/dev目錄下創建設備節點了,創建設備節點分為:創建設備號、初始化并添加字符驅動、創建類、創建設備

驅動代碼:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define GPIOLED_CNT    1   // 設備號數目
#define GPIOLED_NAME   "gpioled" // 名字
#define LEDOFF         0 // 關燈
#define LEDON          1 // 開燈struct gpioled_dev{  // 設備結構體dev_t devid;       // 設備號int major;         // 主設備號int minor;         // 次設備號struct cdev cdev;  // 字符設備struct class* class; // 類struct device_node* nd; // 設備節點struct device* device; // 設備int led_gpio;  // led所使用的編號
};struct gpioled_dev gpioled; // led設備static int led_open(struct inode* inode, struct file* filp){filp->private_data = &gpioled; // 設置私有數據return 0;
}static ssize_t led_read(struct file* filp, char __user* buf, size_t cnt, loff_t* offt){return 0;
}static ssize_t led_write(struct file* filp, const char __user* buf, size_t cnt, loff_t* offt){int retvalue;unsigned char databuf[1];unsigned char ledstat;struct gpioled_dev* dev = filp->private_data;retvalue = copy_from_user(databuf, buf, cnt);if(retvalue < 0){printk("kernel write failed \r\n");return -1;}ledstat = databuf[0];if(ledstat == LEDON){gpio_set_value(dev->led_gpio, 1); // 打開LED}else if(ledstat == LEDOFF){gpio_set_value(dev->led_gpio, 0); // 關燈}return 0;
}static int led_release(struct inode* inode, struct file* filp){return 0;
}static struct file_operations gpioled_fops = { // 設備操作函數.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release =  led_release,
};static int __init led_init(void){int ret = 0;const char* str;/* 設置LED所使用的GPIO */// 1.獲取設備節點gpioled.nd = of_find_node_by_path("/gpioled");if(gpioled.nd == NULL){printk("gpioled node not find \r\n");return -1;}// 2.讀取status屬性ret = of_property_read_string(gpioled.nd, "status", &str);if(ret < 0){printk("read status error \r\n");return -1;}if(strcmp(str, "okay")){printk("status is not okay \r\n");return -1;}// 3.讀取compatible屬性值ret = of_property_read_string(gpioled.nd, "compatible", &str);if(ret < 0){printk("read compatible error \r\n");return -1;}if(strcmp(str, "atkrk3568-gpio-led")){printk("compatible is not atkrk3568-gpio-led \r\n");return -1;}//4.獲取設備樹中的gpio屬性,得到LED所使用的LED編號gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpio", 0); // 0取第一個if(gpioled.led_gpio < 0){printk("cant get led-gpio \r\n");return -1;}printk("led-gpio num = %d \r\n", gpioled.led_gpio);//5.向gpio子系統申請使用GPIO 當前驅動獨自占有此驅動ret = gpio_request(gpioled.led_gpio, "LED-GPIO");if(ret){printk("request led-gpio failed \r\n");return -1;}//6.設置GPIO為輸出,并且輸出低電平,關閉LED燈ret = gpio_direction_output(gpioled.led_gpio, 0);if(ret < 0){printk("cant set gpio \r\n");return -1;}/* 注冊字符設備驅動 */// 1.創建設備號if(gpioled.major){gpioled.devid = MKDEV(gpioled.major, 0);ret = register_chrdev_region(gpioled.devid, GPIOLED_CNT, GPIOLED_NAME); // 注冊字符設備號if(ret < 0){gpio_free(gpioled.led_gpio);printk("cant register %s char driver ret = %d \r\n", GPIOLED_NAME, ret);return -1;}}else{ret = alloc_chrdev_region(&gpioled.devid, 0, GPIOLED_CNT, GPIOLED_NAME);  // 申請設備號if(ret < 0){gpio_free(gpioled.led_gpio);printk("cant alloc_chrdev_region %s, ret = %d \r\n", GPIOLED_NAME, ret);return -1;}gpioled.major = MAJOR(gpioled.devid);gpioled.minor = MINOR(gpioled.devid); // 獲取主次設備號}printk("%s gpioled major = %d, minnor=%d \r\n", GPIOLED_NAME, gpioled.major, gpioled.minor);// 2.初始化字符驅動gpioled.cdev.owner = THIS_MODULE;cdev_init(&gpioled.cdev, &gpioled_fops);// 3.添加一個字符驅動cdev_add(&gpioled.cdev, gpioled.devid, GPIOLED_CNT);if(ret < 0){  // 添加失敗unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注銷掉設備號gpio_free(gpioled.led_gpio);return -1;}// 4.創建類gpioled.class = class_create(THIS_MODULE, GPIOLED_NAME);if(IS_ERR(gpioled.class)){ // 創建類失敗cdev_del(&gpioled.cdev); // 刪掉字符驅動unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注銷掉設備號gpio_free(gpioled.led_gpio);return -1;}// 5.創建設備gpioled.device = device_create(gpioled.class, NULL, gpioled.devid, NULL, GPIOLED_NAME);if(IS_ERR(gpioled.device)){ // 設備創建失敗class_destroy(gpioled.class); // 刪掉類cdev_del(&gpioled.cdev); // 刪掉字符驅動unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注銷掉設備號gpio_free(gpioled.led_gpio);return -1;}return 0;
}static void __exit led_exit(void){device_destroy(gpioled.class, gpioled.devid); // 注銷設備class_destroy(gpioled.class); // 刪掉類cdev_del(&gpioled.cdev); // 刪掉字符驅動unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注銷掉設備號gpio_free(gpioled.led_gpio);
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Narnat");

在這里插入圖片描述

應用層代碼:略

開燈關燈命令:

在這里插入圖片描述
效果圖:略

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/83860.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83860.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83860.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

阿里云ACP云計算備考筆記 (3)——云存儲RDS

目錄 第一章 云存儲概覽 1、云存儲通用知識 ① 發展歷史 ② 云存儲的優勢 2、云存儲分類 3、文件存儲業務場景 第二章 塊存儲 1、塊存儲分類 2、云盤的優勢 3、創建云盤 4、管理數據盤 ① 格式化數據盤 ② 掛載數據盤 ③ 通過 API 掛載云盤 5、管理系統盤 ① 更…

亞矩陣云手機實測體驗:穩定流暢背后的技術邏輯?

最近在測試一款云手機服務時&#xff0c;發現亞矩陣的表現出乎意料地穩定。作為一個經常需要多設備協作的開發者&#xff0c;我對云手機的性能、延遲和穩定性要求比較高。經過一段時間的體驗&#xff0c;分享一下真實感受&#xff0c;避免大家踩坑。 ??1. 云手機能解決什么問…

STM32H562----------ADC外設詳解

1、ADC 簡介 STM32H5xx 系列有 2 個 ADC,都可以獨立工作,其中 ADC1 和 ADC2 還可以組成雙模式(提高采樣率)。每個 ADC 最多可以有 20 個復用通道。這些 ADC 外設與 AHB 總線相連。 STM32H5xx 的 ADC 模塊主要有如下幾個特性: 1、可配置 12 位、10 位、8 位、6 位分辨率,…

【Android】雙指旋轉手勢

一&#xff0c;概述 本文參考android.view.ScaleGestureDetector&#xff0c;對雙指旋轉手勢做了一層封裝&#xff0c;采用了向量計算法簡單實現&#xff0c;筆者在此分享下。 二&#xff0c;實例 如下&#xff0c;使用RotateGestureDetector即可委托&#xff0c;實現旋轉手…

B站的視頻怎么下載下來——Best Video下載器

B站&#xff08;嗶哩嗶哩&#xff09;作為國內最受歡迎的視頻平臺之一&#xff0c;聚集了無數優質內容&#xff1a;動漫番劇、游戲實況、學習課程、紀錄片、Vlog、鬼畜剪輯……總有那么些視頻讓人想反復觀看、離線觀看&#xff0c;甚至剪輯創作。 但你是否遇到過這樣的煩惱&am…

基于SFC的windows系統損壞修復程序

前言 在平時使用Windows操作系統時會遇到很多因為系統文件損壞而出現的錯誤 例如:系統應用無法打開 系統窗口(例如開始菜單)無法使用 電腦藍屏或者卡死 是如果想要修復很多人只能想到重裝系統。但其實Windows有一個內置的系統文件檢查器可以修復此類錯誤。 原理 SFC命令…

智紳科技 —— 智慧養老 + 數字健康,構筑銀發時代安全防護網

在老齡化率突破 21.3% 的當下&#xff0c;智紳科技以 "科技適老" 為核心理念&#xff0c;構建 "監測 - 預警 - 干預 - 照護" 的智慧養老閉環。 其自主研發的七彩喜智慧康養平臺&#xff0c;通過物聯網、AI 和邊緣計算技術&#xff0c;實現對老年人健康與安…

用函數實現模塊化程序設計(適合考研、專升本)

函數 定義&#xff1a;本質上是一段可以被連續調用、功能相對獨立的程序段 c語言是通過“函數”實現模塊化的。根據分類標準不同函數分為以下幾類。 用戶角度&#xff1a;庫函數、自定義函數 函數形式&#xff1a;有參函數、無參函數 作用域&#xff1a;外部函數、內部函數 …

OpenCV 滑動條調整圖像亮度

一、知識點 1、int createTrackbar(const String & trackbarname, const String & winname, int * value, int count, TrackbarCallback onChange 0, void * userdata 0); (1)、創建一個滑動條并將其附在指定窗口上。 (2)、參數說明: trackbarname: 創建的…

vcs仿真產生fsdb波形的兩種方式

目錄 方法一&#xff1a; 使用verilog自帶的系統函數 方法二&#xff1a; 使用UCLI command 2.1 需要了解什么是vcs的ucli&#xff0c;怎么使用ucli&#xff1f; 2.2 使用ucli dump波形的方法 使用vcs仿真產生fsdb波形有兩種方式&#xff0c;本文參考《vcs user guide 20…

【前端】每日一道面試題6:解釋Promise.any和Promise.allSettled的使用場景及區別。

Promise.any() 和 Promise.allSettled() 是 JavaScript 中用于處理異步操作的兩種不同策略的 Promise 組合器&#xff0c;它們的核心區別在于邏輯目標與結果處理方式&#xff1a; 1. Promise.any() 使用場景&#xff1a; 需要獲取 首個成功結果&#xff08;類似競速成功優先&…

數據鏈路層__

文章目錄 數據鏈路層基本概念&#xff08;1&#xff09;鏈路管理&#xff1a;面向連接的服務&#xff08;2&#xff09;幀同步&#xff1a;成幀1、字符計數法2、字符填充法&#xff08;帶填充的首尾界符法&#xff09;3、帶填充的首位標志法4、物理層編碼違例法 &#xff08;3&…

coze智能體后端接入問題:

是否一定要按照coze官方API文檔格式調用&#xff1f; 不一定&#xff1a;以下面代碼為例(給了注釋) app.route(/compare_models, methods[POST]) def compare_models():print("收到 compare_models 請求&#xff01;") #begin-這一部分代碼作用&#xff1a;從前端接…

如何輕松、安全地管理密碼(新手指南)

很多人會為所有賬戶使用相同、易記的密碼&#xff0c;而且常常多年不換。雖然這樣方便記憶&#xff0c;但安全性非常低。 您可能聽說過一些大型網站的信息泄露事件&#xff0c;同樣的風險也可能存在于您的WordPress網站中。如果有不法分子獲取了訪問權限&#xff0c;您的網站和…

寶塔think PHP8 安裝使用FFmpeg 視頻上傳

寶塔think PHP8 安裝使用FFmpeg 一、 安裝think PHP8二、安裝 FFmpeg1&#xff0c;登錄到寶塔面板。2&#xff0c;進入“軟件商店”。3&#xff0c;搜索“FFmpeg”。4&#xff0c;選擇版本點擊安裝。5&#xff0c;檢查 FFmpeg 是否安裝成功6&#xff0c; 在 ThinkPHP 8 中使用 …

Android 輕松實現 增強版靈活的 滑動式表格視圖

表格視圖組件&#xff0c;支持&#xff1a; 1. 無標題模式&#xff1a;只有數據行也可以正常滑動 2. 兩種滑動模式&#xff1a;固定第一列 或 全部滑動 3. 全面的樣式自定義能力 4. 智能列寬計算 1. 無標題模式支持 設置無標題&#xff1a;調用 setHeaderData(null) 或 …

【Python進階】元類編程

目錄 &#x1f31f; 前言&#x1f3d7;? 技術背景與價值&#x1fa79; 當前技術痛點&#x1f6e0;? 解決方案概述&#x1f465; 目標讀者說明 &#x1f9e0; 一、技術原理剖析&#x1f4ca; 核心概念圖解&#x1f4a1; 核心作用講解&#x1f527; 關鍵技術模塊說明?? 技術選…

DeepSeek模型性能優化:從推理加速到資源調度的全棧實踐

引言 在生產環境中部署DeepSeek模型時,性能優化直接關系到服務質量和運營成本。本文將深入探討從芯片級優化到分布式調度的全棧性能提升方案,涵蓋計算圖優化、內存管理、批處理策略等關鍵技術,并分享在千萬級QPS場景下的實戰經驗,幫助工程團隊突破性能瓶頸,實現成本與效能…

Ctrl+R 運行xxx.exe,發現有如下問題.

CtrlR 運行xxx.exe,發現有如下問題. (1)找不到Qt5Core.all,Qt5Cored.dll,Qt5Gui.dll,Qt5Guid.dll,Qt5Widgets.all,Qt5Widgetsd.dll? (2)之后找不到libwinpthread-1.dll 從這個目錄拷貝相應的庫到運行xx.exe目錄下 方法二:將庫路徑添加到系統PATH環境變量里: 在Path中添加路…

硅基計劃2.0 學習總結 陸 抽象類與接口

文章目錄 一、抽象類1. 定義2. 示例代碼3. 特性 二、接口初識1. 定義2. 命名與語法3. 示例代碼4. 常見特性5. 多接口實現6. 接口的繼承 三、Object類初識1. equals方法2. hascode方法 一、抽象類 1. 定義 請你假設這樣一個場景&#xff0c;我們定義一個人的類&#xff0c;這個…