<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Openwrt開發指南 第19章 驅動開發之LED驅動程序

嵌入式大雜燴 ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-07-03 09:01 ? 次閱讀

開發環境:

主機:Ubuntu12.04

開發板:RT5350

Openwrt:Openwrt15.05

1 硬件原理

1688309450899wor3360rqz

圖1

由于發光二級管單向導電特性,即只有在正向電壓(二極管的正極接正,負極接負)下才能導通發光。如圖所示,如果 GPIO 輸出高電平,LED 就會被點亮,如果 GPIO 輸出低電平,LED 就會熄滅。對于我們的驅動開發,無論是單片機、還是 ARM、或者是我們的 MIPS,核心思想,都是讀寫某個地址,即操作某個寄存器。

2 寄存器介紹

RT5350 一共有 28 個 GPIO 管腳,這 28 個 GPIO,除了 GPIO0,其他全部是與其他功能引腳復用的。

表1

1688309451600teuqhsf0kc

GPIO1、GPIO2 與 I2C 復用。

表2

1688309451852hx8f10ostq

GPIO3~6 與 SPI 復用。

表3

1688309452118oauupjmw22

GPIO7~14,與 UARTF 即串口 2 復用。

這些復用關系,都可以通過查閱 RT5350 的芯片手冊得到。

而這些復用功能, 我們可以通過 GPIOMODE 寄存器來進行選擇, 通過查手冊得知,GPIOMODE寄存器的地址為 0x10000060。

表4

1688309452394a7cho2pt83

GPIOMODE 寄存器 bit0 位用于選擇 GPIO1、GPIO2 對應的引腳是用于 IIC 總線,還是用于GPIO。

GPIOMODE 寄存器 bit1 位用于選擇 GPIO3~6 對應的引腳用于 SPI 總線,還是用于 GPIO。

GPIOMODE 寄存器 bit2~4 位用于選擇 UARTF 對應的引腳工作于哪個模塊,具體定義如下。

表5

16883094530699yqb8mgmpb

從該表格可以看出,UARTF 對應的引腳,可以工作于 UARTF、PCM、I2S、GPIO 四種模式,將 GPIOMODE 寄存器 bit24 位設置為相應的值,就能讓這些引腳工作于相應的模式,比如將GPIOMODE 寄存器 bit24 位的值設置為 7,則讓相應的引腳工于 GPIO 模式。

當將相應的引腳設置為 GPIO 以后,我們接下來就需要操作該 GPIO 了,操作 GPIO 不外乎就是設置 GPIO 是輸入還是輸出、讓其輸出高電平還是低電平、讀取其電平狀態。不管是哪種操作,都有對應的寄存器。

表6

1688309453462jtao5bg1g4

GPIO21_00_DIR 寄存器,用于設置 GPIO0~21 的方向,當相應的位被設置為 1,則表示相應的 GPIO 管腳被設置為了輸出,如果被設置為了 0,則相應的 GPIO 引腳就被設置為了輸入。

表7

1688309453878j8wuc87w5l

當相應 GPIO 引腳被設置為輸出時,設置 GPIO21_00_DATA 寄存器的相應位為 1,則讓該GPIO 引腳輸出了高電平,如果設置 GPIO21_00_DATA 寄存器的相應位為 0,則讓該 GPIO 引腳輸出了低電平。

當相應 GPIO 引腳被設置為輸入時,則通過讀取 GPIO21_00_DATA 寄存器時,就能讀取相應的 GPIO 引腳的狀態。

關于更多的 GPIO 操作的寄存器介紹,請自行查閱手冊。

3 編寫驅動程序

我們通過前面章節的學習,掌握了驅動程序的框架,接下來我們就來寫一個驅動程序,實現操作 GPIO25、GPIO26 兩個 GPIO 引腳。具體驅動實現如下。

#include < linux/mm.h >
#include < linux/miscdevice.h >
#include < linux/slab.h >
#include < linux/vmalloc.h >
#include < linux/mman.h >
#include < linux/random.h >
#include < linux/init.h >
#include < linux/raw.h >
#include < linux/tty.h >
#include < linux/capability.h >
#include < linux/ptrace.h >
#include < linux/device.h >
#include < linux/highmem.h >
#include < linux/crash_dump.h >
#include < linux/backing-dev.h >
#include < linux/bootmem.h >
#include < linux/splice.h >
#include < linux/pfn.h >
#include < linux/export.h >
#include < linux/io.h >
#include < linux/aio.h >
#include < linux/kernel.h >
#include < linux/module.h >
#include < asm/uaccess.h >
#define MYLEDS_LED1_ON 0
#define MYLEDS_LED1_OFF 1
#define MYLEDS_LED2_ON 2
#define MYLEDS_LED2_OFF 3

volatile unsigned long *GPIOMODE;
volatile unsigned long *GPIO27_22_DIR;
volatile unsigned long *GPIO27_22_DATA;
static struct class *myleds_class;

static int myleds_open(struct inode *inode, struct file *file)
{
/* 讓 GPIO#25、GPIO#26 輸出高電平,同時熄滅 LED1、LED2 */
*GPIO27_22_DATA &= ~((1< 3)|(1< 4));
return 0;
}
static long myleds_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case MYLEDS_LED1_ON:// 點亮 LED1
*GPIO27_22_DATA |= (1< 3);
break;
case MYLEDS_LED1_OFF: // 熄滅 LED1
*GPIO27_22_DATA &= ~(1< 3);
break;
case MYLEDS_LED2_ON:// 點亮 LED2
*GPIO27_22_DATA |= (1< 4);
break;
case MYLEDS_LED2_OFF: // 熄滅 LED2
*GPIO27_22_DATA &= ~(1< 4);
break;
default:
break;
}
return 0;
}
/* 1.分配、設置一個 file_operations 結構體 */
static struct file_operations myleds_fops = {
.owner = THIS_MODULE, /* 這是一個宏,推向編譯
模塊時自動創建的__this_module 變量 */
.open = myleds_open,
.unlocked_ioctl = myleds_unlocked_ioctl,
};
int major;
static int __init myleds_init(void)
{
/* 2.注冊 */
major = register_chrdev(0, "myleds", &myleds_fops);
/* 3.自動創建設備節點 */
/* 創建類 */
myleds_class = class_create(THIS_MODULE, "myleds");
/* 類下面創建設備節點 */
device_create(myleds_class, NULL, MKDEV(major, 0), NULL, "myleds"); //
/dev/myleds
/* 4.硬件相關的操作 */
/* 映射寄存器的地址 */
GPIOMODE = (volatile unsigned long *)ioremap(0x10000060, 4);
GPIO27_22_DIR = (volatile unsigned long *)ioremap(0x10000674, 4);
GPIO27_22_DATA = (volatile unsigned long *)ioremap(0x10000670, 4);
/* 設置相應管腳用于 GPIO */
/*
** LED1 ---- GPIO#25
** LED2 ---- GPIO#26
*/
*GPIOMODE |= (0x1< 14);
/* 將 GPIO#25、GPIO#26 設置為輸出 */
*GPIO27_22_DIR = (1< 3)|(1< 4);
return 0;
}
static void __exit myleds_exit(void)
{
unregister_chrdev(major, "myleds");
device_destroy(myleds_class, MKDEV(major, 0));
class_destroy(myleds_class);
iounmap(GPIOMODE);
iounmap(GPIO27_22_DIR);
iounmap(GPIO27_22_DATA);
}
module_init(myleds_init);
module_exit(myleds_exit);
MODULE_LICENSE("GPL");

因為我們的開發板上跑的是 Linux 系統,因此操作某個寄存器的時候,需要將它的物理地址映射成虛擬地址,通過 ioremap()函數來進行映射,該函數的參數 1,就是對應的寄存器的物理地址,參數 2 是需要映射多大,可以理解為寄存器有多大,返回值就是該寄存器對應的虛擬地址了。

當寄存器地址映射為虛擬地址以后,然后基于前面寫的驅動程序框架,就能很容易的編寫出自己的 GPIO 驅動了,和操作單片機沒有什么差別了。

4 編寫 Makefile

驅動寫好以后,自然是需要想辦法來編譯該驅動了,通過前面的章節的學習,我們需要給該驅動編寫一個 Makefile 文件。

首先是新建一個文件夾,取名為 myleds,然后在 myleds 目錄下再新建一個文件夾,取名為 src,然后將上面的驅動文件復制到 src 目錄下,并且在 src 目錄下新建一個 Makefile,

內容如下。

obj-m += myleds.o

然后回到 myleds 目錄,再創建一個 Makefile 文件,內容如下。

# 
#Copyright (C) 2008-2019 OpenWrt.org
#
#This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=myleds
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define KernelPackage/myleds
SUBMENU:=Other modules
# DEPENDS:=@!LINUX_3_3
TITLE:=Motor driver
FILES:=$(PKG_BUILD_DIR)/myleds.ko
# AUTOLOAD:=$(call AutoLoad,30,myleds,1)
KCONFIG:=
endef
define KernelPackage/myleds/description
This is a myleds drivers
endef
MAKE_OPTS:= \\
ARCH="$(LINUX_KARCH)" \\
CROSS_COMPILE="$(TARGET_CROSS)" \\
SUBDIRS="$(PKG_BUILD_DIR)"
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" \\
$(MAKE_OPTS) \\
modules
endef
$(eval $(call KernelPackage,myleds))

如果不清楚為什么這樣編寫 Makefile 文件,請查看前面章節的相關介紹。

5 編譯驅動程序

接下來,我們就來配置編譯驅動程序。首先將 myleds 文件夾傳到 OpenWrt 源碼的package/kernel 目錄下。然后進入 OpenWrt 源碼的頂層目錄,執行 make menuconfig。

$ make menuconfig

在彈出的菜單界面里,首先進入 Kernel modules 選項。

Kernel modules  --- >
Other modules  --- >
< * > kmod-myleds

16883094542989qo0m5w9t8

圖2

然后我們就能看到我們的驅動程序的選項了 kmod-myleds,將它配置成M,也可以便已進入內核。最后,退出保存。然后再執行編譯命令。

make V=99

編譯完成以后,就能在源碼目錄下的bin/ramips/packages/base目錄下看到我們的內核模塊驅動程序的軟件包 kmod-myleds_3.18.109-1_ramips_24kec.ipk。

19.6 動態的加載和卸載內核驅動模塊軟件包

通過前面的努力,我們終于得到了我們自己的內核驅動模塊軟件包了。接下來就來使用它。首先將 kmod-myleds_3.18.109-1_ramips_24kec.ipk 軟件包傳到開發板上面。然后使用 opkg install 命令來安裝軟件包。

opkg install kmod-myleds_3.18.109-1_ramips_24kec.ipk

1688309454667y59me39sp3

使用 opkg list 命令來查看已經安裝了哪些軟件包。這里是否執行該命令都無所謂。接下來進入我們的/lib/modules/3.18.109目錄,就能看到我們的驅動程序模塊了。

cd lib/modules/3.18.109/

1688309454875gdnscpsfh4

接下來就通過 insmod 命令來裝載驅動模塊。

insmod myleds.ko

驅動安裝成功以后,我們就能看到 GPIO 驅動對應的設備節點了。

168830945511587ihzpsapz

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • led
    led
    +關注

    關注

    237

    文章

    22488

    瀏覽量

    646328
  • 驅動程序
    +關注

    關注

    19

    文章

    772

    瀏覽量

    47310
  • 開發板
    +關注

    關注

    25

    文章

    4506

    瀏覽量

    94458
  • 開發環境
    +關注

    關注

    1

    文章

    204

    瀏覽量

    16471
  • OpenWrt
    +關注

    關注

    10

    文章

    118

    瀏覽量

    38935
收藏 人收藏

    評論

    相關推薦

    Openwrt開發指南 第25章 配置OpenWrt支持網絡攝像頭

    Openwrt開發指南 第25章 配置OpenWrt支持網絡攝像頭
    的頭像 發表于 07-13 08:56 ?1621次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發指南</b> 第25章 配置<b class='flag-5'>OpenWrt</b>支持網絡攝像頭

    PCI驅動程序開發實例

    本文采用微軟的驅動程序開發包Device Driver Kit(DDK)開發出來的PCI驅動程序通用性好,兼容性強。本文給出了基于DSP的PCI驅動
    發表于 12-30 11:10 ?6545次閱讀
    PCI<b class='flag-5'>驅動程序</b><b class='flag-5'>開發</b>實例

    Openwrt開發指南 第15章 驅動開發之字符設備驅動程序之概念介紹

    從上到下,一個軟件系統可以分為:應用程序、庫、操作系統(內核)、驅動程序。開發人員可以專注于自己熟悉的部分,對于相鄰層,只需要了解它的接口,無需關注它的實現細節。
    的頭像 發表于 06-30 09:00 ?2219次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發指南</b> 第15章 <b class='flag-5'>驅動</b><b class='flag-5'>開發</b>之字符設備<b class='flag-5'>驅動程序</b>之概念介紹

    Openwrt開發指南 第20章 驅動開發LED應用程序

    在前面的章節中, 我們成功的寫出了我們自己的驅動程序, 并且向應用程序提供了 open、ioctl 兩個接口,那么接下來我們就來編寫應用程序,調用這些接口。
    的頭像 發表于 07-03 09:02 ?2189次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發指南</b> 第20章 <b class='flag-5'>驅動</b><b class='flag-5'>開發</b>之<b class='flag-5'>LED</b>應用<b class='flag-5'>程序</b>

    Openwrt開發指南 第24章 配置開發板支持U盤

    Openwrt開發指南 第24章 配置開發板支持U盤
    的頭像 發表于 07-13 08:55 ?1447次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發指南</b> 第24章 配置<b class='flag-5'>開發</b>板支持U盤

    CE驅動程序開發指南資料分享

    CE驅動程序開發指南資料分享
    發表于 08-03 12:03

    測試系統開發指南:理解驅動程序和直接輸入輸出

    測試系統開發指南:理解驅動程序和直接輸入/輸出
    發表于 08-21 14:53

    鴻蒙系統驅動程序的實現流程

    `這篇文檔介紹的是鴻蒙系統的驅動開發1、HDF開發指南2、驅動服務管理3、LiteOS-a第一個驅動程序加載過程4、編寫
    發表于 09-24 14:48

    WINCE驅動程序開發指南

    CE驅動程序所有驅動皆為動態鏈接庫驅動實現中可以調用所有標準的APICE驅動程序模型本機驅動程序流接口
    發表于 07-07 15:06 ?41次下載

    用WinDriver開發PCI設備驅動程序

    用WinDriver開發PCI設備驅動程序:給出了驅動開發工具WinDriver的主要特點,內部機制及開發步驟,并且結合PCI設備的具體特點
    發表于 06-28 19:26 ?51次下載

    基于VxWorks的pci設備驅動程序開發

    對嵌入式實時系統Vxw池中的設備驅動程序開發進行了簡要的介紹,討論了V s操作系統下的I/O系統和設備驅動程序、應用程序之間的關系。另外,結合作者
    發表于 08-04 17:41 ?34次下載
    基于VxWorks的pci設備<b class='flag-5'>驅動程序</b><b class='flag-5'>開發</b>

    Windows WDM設備驅動程序開發指南

    書主要介紹Windows 98和Windows 2000新的驅動程序模型(WDM)。描述了WDM設備驅動程序的結構、功能和開發方法.
    發表于 12-12 15:31 ?0次下載
    Windows WDM設備<b class='flag-5'>驅動程序</b><b class='flag-5'>開發指南</b>

    A64開發板LCD開發指南

    A64開發板LCD開發指南,驅動開發指南
    發表于 06-21 17:02 ?0次下載

    驅動程序開發步驟

    驅動程序開發步驟 編寫一個驅動程序的大致流程如下: 1)查看原理圖,數據手冊,了解設備的操作方法; 2)在內核中找到相近的驅動程序,作為模板來開發
    發表于 12-29 14:51 ?6254次閱讀

    UM2298_STM32Cube BSP驅動程序開發指南

    UM2298_STM32Cube BSP驅動程序開發指南
    發表于 11-22 19:19 ?1次下載
    UM2298_STM32Cube BSP<b class='flag-5'>驅動程序</b><b class='flag-5'>開發指南</b>
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>