国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

荔枝派zero驅(qū)動(dòng)開發(fā)04:GPIO操作(寄存器方式)

這篇具有很好參考價(jià)值的文章主要介紹了荔枝派zero驅(qū)動(dòng)開發(fā)04:GPIO操作(寄存器方式)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

參考:https://wiki.sipeed.com/soft/Lichee/zh/Zero-Doc/Drive/GPIO_mmap.html

上一篇:荔枝派zero驅(qū)動(dòng)開發(fā)03:設(shè)備樹基礎(chǔ)
下一篇:荔枝派zero驅(qū)動(dòng)開發(fā)05:GPIO操作(使用GPIO子系統(tǒng))

  • 關(guān)鍵詞:ioremap/iounmap,copy_from_user/copy_to_user,readl/writel

設(shè)備樹修改:

本文不涉及設(shè)備樹操作,但由于默認(rèn)設(shè)備樹配置了LED,因此先在設(shè)備樹中禁用默認(rèn)的LED配置,重新編譯設(shè)備樹后,使用新的設(shè)備樹啟動(dòng)

荔枝派zero驅(qū)動(dòng)開發(fā)04:GPIO操作(寄存器方式),嵌入式Linux開發(fā),驅(qū)動(dòng)開發(fā),linux,arm開發(fā),物聯(lián)網(wǎng),嵌入式硬件

關(guān)鍵代碼:

#define V3S_GPIO_BASE 0x01C20800
// 模式寄存器,4bit,最高位保留,000輸入,001為輸出
#define V3S_GPIOG_MODE (V3S_GPIO_BASE + 0xD8)
// 每個(gè)腳的輸入輸出數(shù)據(jù),1bit
#define V3S_GPIOG_DATA (V3S_GPIO_BASE + 0xE8)

static void __iomem *GPIOG_MODE;
static void __iomem *GPIOG_DATA;

GPIOG_MODE = ioremap(V3S_GPIOG_MODE, 4);
GPIOG_DATA = ioremap(V3S_GPIOG_DATA, 4);

uint32_t val=0;
val=readl(GPIOG_MODE);
val &= ~(7 << (PIN_N * 4)); // 清除配置
val |= (1 << (PIN_N * 4));  // 配置為輸出
writel(val, GPIOG_MODE);

val=readl(GPIOG_DATA);
val &= ~(1 << PIN_N);
writel(val, GPIOG_DATA); // 引腳初始化為低

根據(jù)v3s寄存器表,GPIO的物理地址基址為0x01C20800,GPIOG的模式寄存器地址為(0x01C20800+0xD8)
在裸機(jī)開發(fā)中,可以直接讀寫*(0x01C20800+0xD8)來操作GPIO寄存器;但在linux中,內(nèi)核不能直接訪問物理地址,必須映射為虛擬地址后才可以訪問,映射和取消映射的函數(shù)為ioremap()和iounmap()。

writel() 向內(nèi)存映射的物理地址上寫數(shù)據(jù),wirtel() 寫入 32 位數(shù)據(jù) (4字節(jié));readl同理,讀取32位數(shù)據(jù) (4字節(jié));類似的操作函數(shù)有writeb/writew/writel,分別對應(yīng)8位、16位、32位操作

位操作比較清晰,清除指定的位,或在指定位寫入數(shù)據(jù);v3s的模式寄存器每個(gè)腳占用4bit,0b000輸入,0b001輸出,要配置為輸出直接向指定的4bit寫入0b001即可

static ssize_t led_gpio_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos)
{
    unsigned char val;
    copy_from_user(&val, user_buf, 1);
    printk("led_gpio_write: 0x%02x\n", val);
    if (val=='1' || val == 1) //默認(rèn)輸入為0x30即字符'0'
    {
        val=readl(GPIOG_DATA);
        val &= ~(1 << PIN_N); //低電平點(diǎn)亮
        writel(val, GPIOG_DATA);
    }
    else if (val=='0' || val == 0)
    {
        val=readl(GPIOG_DATA);
        val|= (1 << PIN_N); //高電平熄滅
        writel(val, GPIOG_DATA);
    }
    return 1;
}

用戶空間內(nèi)存不能直接訪問內(nèi)核空間的內(nèi)存,需要借助函數(shù) copy_from_user 將用戶空間的數(shù)據(jù)復(fù)制到內(nèi)核空間;LED控制較為簡單,只需一個(gè)字符即可控制LED,這里復(fù)制1個(gè)字符即可,應(yīng)用層也只需一個(gè)字符控制LED

測試:

其他參考之前的字符設(shè)備模板寫即可,修改Makefile并編譯,將生成的ledchar.ko拷貝到開發(fā)板,注意前述的設(shè)備樹修改

使用echo測試

荔枝派zero驅(qū)動(dòng)開發(fā)04:GPIO操作(寄存器方式),嵌入式Linux開發(fā),驅(qū)動(dòng)開發(fā),linux,arm開發(fā),物聯(lián)網(wǎng),嵌入式硬件

使用應(yīng)用層APP測試

這里也寫了一個(gè)簡單的測試app,源碼附在文后,調(diào)用本條命令進(jìn)行編譯,編譯出目標(biāo)文件拷貝到開發(fā)板

/opt/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -o ledcharApp ledcharApp.c

荔枝派zero驅(qū)動(dòng)開發(fā)04:GPIO操作(寄存器方式),嵌入式Linux開發(fā),驅(qū)動(dòng)開發(fā),linux,arm開發(fā),物聯(lián)網(wǎng),嵌入式硬件

APP運(yùn)行測試:

荔枝派zero驅(qū)動(dòng)開發(fā)04:GPIO操作(寄存器方式),嵌入式Linux開發(fā),驅(qū)動(dòng)開發(fā),linux,arm開發(fā),物聯(lián)網(wǎng),嵌入式硬件

一點(diǎn)心得:

本篇是最接近裸機(jī)的開發(fā)方式了,簡單直接、深入底層,不涉及Linux的程序框架與造好的輪子;實(shí)際開發(fā)中幾乎不會使用這種開發(fā)方式,但有助于理解驅(qū)動(dòng)框架和硬件的關(guān)系,可以有一個(gè)直觀感受。

源碼

ledcharApp.c

#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"
#include "string.h"
#include "sys/types.h"
#include "sys/stat.h"
#include <fcntl.h>

int main(int argc, char *argv[])
{
	int fd, ret;
	char *filename;
	char val = 0;

	if (argc != 3)
	{
		printf("Usage !=3\r\n");
		return -1;
	}

	filename = argv[1]; 
	fd = open(filename, O_RDWR);
	if (fd < 0)
	{
		printf("cannot open file:%s\r\n", filename);
		return -1;
	}

	val = atoi(argv[2]);
	ret = write(fd, &val, sizeof(val));
	if (ret < 0)
		printf("cannot write file:%s\r\n", filename);
	else
		printf("app:set led:%d\r\n", val);

	ret = close(fd);
	if (ret < 0)
	{
		printf("cannot close file:%s\r\n", filename);
		return -1;
	}
	return 0;
}

ledchar.c文章來源地址http://www.zghlxwxcb.cn/news/detail-808037.html

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/mach/map.h>
#include <asm/io.h>
#include <linux/printk.h>
#include <linux/uaccess.h>

struct ledchar_dev
{
    dev_t devid;
    struct cdev cdev;
    struct class *class;
    struct device *device;
    int major;
    int minor;
};
struct ledchar_dev ledchar = {
    .major = 0,
};

#define PIN_N 0 // 第0個(gè)引腳,PG0,綠色
#define DEV_NAME "led"
#define LED_ON  0 // 上拉,低電平亮
#define LED_OFF 1

#define V3S_GPIO_BASE 0x01C20800
// 模式寄存器,4bit,最高位保留,000輸入,001為輸出
#define V3S_GPIOG_MODE (V3S_GPIO_BASE + 0xD8)
// 每個(gè)腳的輸入輸出數(shù)據(jù),1bit
#define V3S_GPIOG_DATA (V3S_GPIO_BASE + 0xE8)
// 驅(qū)動(dòng)能力,2bit,0-3逐級遞增
#define V3S_GPIOG_DRIVING (V3S_GPIO_BASE + 0xEC)
// 上拉下拉,2bit,0浮空,1上拉,2下拉
#define V3S_GPIOG_PULL (V3S_GPIO_BASE + 0xF4)

// 中斷配置,4bit,0上升,1下降,2高電平,3低電平,4雙邊沿
#define V3S_GPIOG_INTCFG (V3S_GPIO_BASE + 0x240)
// 中斷使能,1bit,1使能
#define V3S_GPIOG_INT_CTRL (V3S_GPIO_BASE + 0x250)
// 中斷狀態(tài),1bit,1發(fā)生中斷,寫1清除
#define V3S_GPIOG_INT_STA (V3S_GPIO_BASE + 0x254)
// 中斷時(shí)鐘及分頻配置
#define V3S_GPIOG_INT_DEB (V3S_GPIO_BASE + 0x258)

static void __iomem *GPIOG_MODE;
static void __iomem *GPIOG_DATA;
static void __iomem *GPIOG_DRIVING;
static void __iomem *GPIOG_PULL;


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

static int led_gpio_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    return 0;
}

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

static ssize_t led_gpio_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos)
{
    unsigned char val;
    copy_from_user(&val, user_buf, 1);
    printk("led_gpio_write: 0x%02x\n", val);
    if (val=='1' || val == 1) 
    {
        val=readl(GPIOG_DATA);
        val &= ~(1 << PIN_N); //低電平點(diǎn)亮
        writel(val, GPIOG_DATA);
    }
    else if (val=='0' || val == 0)
    {
        val=readl(GPIOG_DATA);
        val|= (1 << PIN_N); //高電平熄滅
        writel(val, GPIOG_DATA);
    }
    return 1;
}

static const struct file_operations ledchar_fops = {
    .open = led_gpio_open,
    .read = led_gpio_read,
    .release = led_gpio_release,
    .write = led_gpio_write,
};

static int __init led_driver_init(void)
{
    int ret;
    

    GPIOG_MODE = ioremap(V3S_GPIOG_MODE, 4);
    GPIOG_DATA = ioremap(V3S_GPIOG_DATA, 4);
    GPIOG_DRIVING = ioremap(V3S_GPIOG_DRIVING, 4);
    GPIOG_PULL = ioremap(V3S_GPIOG_PULL, 4);

    uint32_t val=0;
    val=readl(GPIOG_MODE);
    val &= ~(7 << (PIN_N * 4)); // 清除配置
    val |= (1 << (PIN_N * 4));  // 配置為輸出
    writel(val, GPIOG_MODE);

    val=readl(GPIOG_DATA);
    val &= ~(1 << PIN_N);
    writel(val, GPIOG_DATA); // 引腳初始化為低

    if (ledchar.major) // 定義了設(shè)備號,靜態(tài)設(shè)備號
    {
        ledchar.devid = MKDEV(ledchar.major, 0);
        ret = register_chrdev_region(ledchar.major, 1, DEV_NAME);
        if (ret < 0)
        {
            pr_err("cannot register %s char driver.ret:%d\r\n", DEV_NAME, ret);
            goto exit;
        }
    }
    else // 沒有定義設(shè)備號,動(dòng)態(tài)申請?jiān)O(shè)備號
    {
        ret = alloc_chrdev_region(&ledchar.devid, 0, 1, DEV_NAME);
        if (ret < 0)
        {
            pr_err("cannot alloc_chrdev_region,ret:%d\r\n", ret);
            goto exit;
        }
        ledchar.major = MAJOR(ledchar.devid);
        ledchar.minor = MINOR(ledchar.devid);
    }
    printk("led major=%d,minor=%d\r\n", ledchar.major, ledchar.minor);

    ledchar.cdev.owner = THIS_MODULE;
    cdev_init(&ledchar.cdev, &ledchar_fops);

    ret = cdev_add(&ledchar.cdev, ledchar.devid, 1);
    if (ret < 0)
        goto del_unregister;

    ledchar.class = class_create(THIS_MODULE, DEV_NAME);
    if (IS_ERR(ledchar.class))
        goto del_cdev;

    ledchar.device = device_create(ledchar.class, NULL, ledchar.devid, NULL, DEV_NAME);
    if (IS_ERR(ledchar.device))
        goto destroy_class;

    return 0;

    // 注意  goto后的標(biāo)簽沒有return操作,將順序執(zhí)行多個(gè)label直至return,這里反向?qū)?destroy_class:
    class_destroy(ledchar.class);
del_cdev:
    cdev_del(&ledchar.cdev);
del_unregister:
    unregister_chrdev_region(ledchar.devid, 1);
exit:
    printk("chardev_init failed\r\n");
    return -EIO;
}

static void __exit led_driver_exit(void)
{
    iounmap(GPIOG_MODE);
    iounmap(GPIOG_DATA);
    iounmap(GPIOG_DRIVING);
    iounmap(GPIOG_PULL);

    cdev_del(&ledchar.cdev);
    unregister_chrdev_region(ledchar.devid, 1);
    device_destroy(ledchar.class, ledchar.devid);
    class_destroy(ledchar.class);
}

module_init(led_driver_init);
module_exit(led_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("USER");
MODULE_INFO(intree, "Y");

到了這里,關(guān)于荔枝派zero驅(qū)動(dòng)開發(fā)04:GPIO操作(寄存器方式)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 荔枝派Zero(全志V3S)驅(qū)動(dòng)開發(fā)之串口

    荔枝派Zero(全志V3S)驅(qū)動(dòng)開發(fā)之串口

    修改設(shè)備樹打開 uart1 和 uart2,在 buildroot 移植 minicom 用來測試 uart1 和 uart2。 ①、查看 V3S 原理圖,查看 uart1 和 uart2 對應(yīng)的引腳 PE21 - UART1_TX PE22 - UART_RX PB0 - UART2_TX PB1 - UART2_RX ②、修改 sun8i-v3s.dtsi 在 linux 目錄下 在 sun8i-v3s.dtsi 中添加 ③、修改 sun8i-v3s-licheepi-zero-dock.dts 在 lin

    2024年02月11日
    瀏覽(24)
  • 【ARM裸機(jī)編程 | 海思SS528】- 操作 GPIO 寄存器輸出低電平點(diǎn)亮 LED 燈

    【ARM裸機(jī)編程 | 海思SS528】- 操作 GPIO 寄存器輸出低電平點(diǎn)亮 LED 燈

    這篇文章主要介紹在 海思SS528 開發(fā)板,去操作某個(gè) GPIO 寄存器輸出高、低電平,來熄滅或點(diǎn)亮 LED 燈。 首先,了解一下 ARM裸機(jī)編程 ,也就是在一塊沒有移植操作系統(tǒng)的ARM開發(fā)板去編程,相當(dāng)于把它當(dāng)成單片機(jī)去使用,很多與硬件相關(guān)的操作都需要直接讀寫該硬件的寄存器。

    2024年02月10日
    瀏覽(22)
  • 荔枝派Zero(全志V3S)驅(qū)動(dòng)開發(fā)之USB攝像頭

    荔枝派Zero(全志V3S)驅(qū)動(dòng)開發(fā)之USB攝像頭

    上一篇博客實(shí)現(xiàn)了在ubuntu打開usb攝像頭,也確認(rèn)了 usb 攝像頭支持 UVC,這節(jié)我們將 usb 驅(qū)動(dòng)移植到荔枝派開發(fā)板上,并實(shí)現(xiàn)拍照的功能以及做 mjpeg-streamer 視頻流服務(wù)器測試。 1、進(jìn)入 linux 源碼目錄,執(zhí)行 2、Device Drivers - USB support 按照下圖進(jìn)行配置 輸出識別的每個(gè)usb設(shè)備的基

    2024年02月11日
    瀏覽(21)
  • STM32 | STM32時(shí)鐘分析、GPIO分析、寄存器地址查找、LED燈開發(fā)(第二天)

    STM32 | STM32時(shí)鐘分析、GPIO分析、寄存器地址查找、LED燈開發(fā)(第二天)

    寄存器 :寄存器的功能是存儲二進(jìn)制代碼,它是由具有存儲功能的觸發(fā)器組合起來構(gòu)成的。一個(gè)觸發(fā)器可以存儲1位二進(jìn)制代碼,故存放n位二進(jìn)制代碼的寄存器,需用n個(gè)觸發(fā)器來構(gòu)成 在計(jì)算機(jī)領(lǐng)域,寄存器是CPU內(nèi)部的元件,包括通用寄存器、專用寄存器和 控制寄存器 。寄存

    2024年03月08日
    瀏覽(36)
  • 荔枝派Zero(全志V3S)驅(qū)動(dòng)開發(fā)之RGB LCD屏幕顯示bmp圖片

    荔枝派Zero(全志V3S)驅(qū)動(dòng)開發(fā)之RGB LCD屏幕顯示bmp圖片

    了解 framebuffer 字符設(shè)備 了解 bmp圖片格式 通過操作 /dev/fb0 字符設(shè)備來實(shí)現(xiàn)在 RGB LCD 屏幕上顯示 bmp 圖片。 顯示設(shè)備例如 LCD,在 Linux 中用 Framebuffer 來表征, Framebuffer 翻譯過來就是幀緩沖,簡稱 fb,在 /dev 目錄下顯示設(shè)備一般表示成這樣: /dev/fbn ,應(yīng)用程序通過訪問這個(gè)設(shè)備

    2024年02月11日
    瀏覽(29)
  • STM32 入門 —— 寄存器與 GPIO

    STM32 入門 —— 寄存器與 GPIO

    STM32 總線構(gòu)圖: 什么是寄存器 根據(jù)百度百科介紹,寄存器是中央處理器內(nèi)的組成部分。寄存器是有限存貯容量的高速存貯部件,它們可用來暫存指令、數(shù)據(jù)和地址。簡單來說,寄存器就是存放東西的東西,存放的東西是指令、數(shù)據(jù)或地址 存放數(shù)據(jù)的寄存器最容易理解,不同

    2024年02月04日
    瀏覽(29)
  • STM32 寄存器配置筆記——GPIO配置輸出

    STM32 寄存器配置筆記——GPIO配置輸出

    ? ? ? ?本文主要介紹GPIO 作為輸出時(shí)的寄存器配置。包括時(shí)鐘配置,輸出模式配置。以STM32F10xxx系列為例,配置PA8、PD2端口作為輸出,輸出高/低電平。 ? ? ? ? 1)GPIO外設(shè)時(shí)鐘 ? ? ? ? ?通過查找STM32F10xxx中文參考手冊得知,GPIO PORT口的時(shí)鐘配置在RCC_APB2ENR寄存器的第2~6位,

    2024年01月24日
    瀏覽(44)
  • 明解STM32—GPIO理論基礎(chǔ)知識篇之寄存器原理?

    明解STM32—GPIO理論基礎(chǔ)知識篇之寄存器原理?

    一、前言 ????????在之前的STM32的GPIO理論基礎(chǔ)知識中,分別對基本結(jié)構(gòu)和工作模式進(jìn)行了詳細(xì)的介紹。GPIO基本結(jié)構(gòu)中主要對GPIO內(nèi)部的各個(gè)功能電路逐一的進(jìn)行的分析;GPIO工作模式中主要介紹GPIO應(yīng)用在不同的使用場景下,GPIO端口的靜態(tài)特征配置和動(dòng)態(tài)的工作模式,同時(shí)對

    2024年02月16日
    瀏覽(22)
  • STM32F103ZET6 GPIO工作模式介紹+使用寄存器點(diǎn)亮第一個(gè)LED燈

    STM32F103ZET6 GPIO工作模式介紹+使用寄存器點(diǎn)亮第一個(gè)LED燈

    目錄 ?GPIO的工作模式介紹 1.輸入模式(模擬、上拉、下拉、浮空) 2.輸出模式(推挽/開漏) 3.復(fù)用功能(推挽/開漏) 4.模擬輸入輸出(上下拉無影響) 如何使用寄存器點(diǎn)亮第一個(gè)LED燈 ? ? ? ? 在輸入模式時(shí),施密特觸發(fā)器打開,輸出被禁止??赏ㄟ^輸入數(shù)據(jù)寄存器 GPIOx_

    2024年02月06日
    瀏覽(91)
  • STM32 | GPIO口的普通與復(fù)用如何配置與用法,本文降從最底層教你如何查看手冊運(yùn)用寄存器來實(shí)現(xiàn)GPIO口的配置

    STM32 | GPIO口的普通與復(fù)用如何配置與用法,本文降從最底層教你如何查看手冊運(yùn)用寄存器來實(shí)現(xiàn)GPIO口的配置

    ??【藍(lán)橋杯嵌入式】專題正在持續(xù)更新中,原理圖解析?,各模塊分析?以及歷年真題講解?都在這兒哦,歡迎大家前往訂閱本專題,獲取更多詳細(xì)信息哦?????? ??本系列專欄 -??藍(lán)橋杯嵌入式_勾欄聽曲_0的博客 ??歡迎大家? ??? 點(diǎn)贊??? 評論??? 收藏?? ??個(gè)人主

    2024年02月14日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包