【驱动篇】龙芯LS2K0300之LED驱动

实验目的

点亮龙芯开发板上面的用户自定义LED灯,编写LED驱动以及测试用例验证实现效果,LED位于开发板左下方(靠近USB口)第二个

在这里插入图片描述

原理图

LED通过电阻上拉至电源P3V3,低电平时LED被点亮

在这里插入图片描述

设备树

打开arch/loongarch/boot/dts/loongson/loongson_2k0300_pai_99.dts,将72-150行的i2c1和i2c2两个节点注释掉,如下所示

在这里插入图片描述

将loongson_2k0300_pai_99设备树编译进内核,编译完后将内核scp到开发板的/boot目录下,然后重启开发板

在这里插入图片描述

驱动示例

LED驱动

LED对应的GPIO号为83

#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>#define GPIOLED_CNT			1		  
#define GPIOLED_NAME		"led"	
#define OFF 				0		
#define ON 					1		
#define GPIO_LED 			83struct my_led_dev{dev_t dev_id;		struct cdev cdev;	struct class *class;	struct device *device;	int major;			int minor;			struct device_node	*nd; int led;		
};struct my_led_dev led_dev;	static int led_open(struct inode *inode, struct file *filp)
{filp->private_data = &led_dev; 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 ret;unsigned char data[1];unsigned char ledstat;struct my_led_dev *dev = filp->private_data;ret = copy_from_user(data, buf, cnt);if(ret < 0) {printk("kernel write failed!\r\n");return -EFAULT;}ledstat = data[0];	if(ledstat == ON) {	gpio_set_value(dev->led, 0);	} else if(ledstat == OFF) {gpio_set_value(dev->led, 1);	}return 0;
}static int led_release(struct inode *inode, struct file *filp)
{return 0;
}static struct file_operations led_dev_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;led_dev.led = GPIO_LED;if(led_dev.led < 0) {printk("can't get led-gpio");return -EINVAL;}ret = gpio_request(led_dev.led, "LED-GPIO");if (ret) {printk(KERN_ERR "led_dev: Failed to request led-gpio\n");return ret;}ret = gpio_direction_output(led_dev.led, 1);if(ret < 0) {printk("can't set gpio!\r\n");}if (led_dev.major) {		led_dev.dev_id = MKDEV(led_dev.major, 0);ret = register_chrdev_region(led_dev.dev_id, GPIOLED_CNT, GPIOLED_NAME);if(ret < 0) {pr_err("cannot register %s char driver [ret=%d]\n", GPIOLED_NAME, GPIOLED_CNT);goto free_gpio;}} else {					ret = alloc_chrdev_region(&led_dev.dev_id, 0, GPIOLED_CNT, GPIOLED_NAME);if(ret < 0) {pr_err("%s Couldn't alloc_chrdev_region, ret=%d\r\n", GPIOLED_NAME, ret);goto free_gpio;}led_dev.major = MAJOR(led_dev.dev_id);	led_dev.minor = MINOR(led_dev.dev_id);	}led_dev.cdev.owner = THIS_MODULE;cdev_init(&led_dev.cdev, &led_dev_fops);cdev_add(&led_dev.cdev, led_dev.dev_id, GPIOLED_CNT);if(ret < 0)goto del_unregister;led_dev.class = class_create(THIS_MODULE, GPIOLED_NAME);if (IS_ERR(led_dev.class)) {goto del_cdev;}led_dev.device = device_create(led_dev.class, NULL, led_dev.dev_id, NULL, GPIOLED_NAME);if (IS_ERR(led_dev.device)) {goto destroy_class;}return 0;destroy_class:class_destroy(led_dev.class);
del_cdev:cdev_del(&led_dev.cdev);
del_unregister:unregister_chrdev_region(led_dev.dev_id, GPIOLED_CNT);
free_gpio:gpio_free(led_dev.led);return -EIO;
}static void __exit led_exit(void)
{cdev_del(&led_dev.cdev);unregister_chrdev_region(led_dev.dev_id, GPIOLED_CNT); device_destroy(led_dev.class, led_dev.dev_id);class_destroy(led_dev.class);gpio_free(led_dev.led); 
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

Makefile

跟之前一篇文章的Makefile差不多,这里要改一下驱动名称

obj-m += led.o 
KDIR:=/home/asensing/loongson/linux-4.19
ARCH=loongarch 
CROSS_COMPILE=loongarch64-linux-gnu-
PWD?=$(shell pwd) 
all:make -C $(KDIR) M=$(PWD) modules 

build脚本

分别编译测试用例和驱动模块

export PATH=$PATH:/home/asensing/loongson/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.3-1/bin
make -j8
loongarch64-linux-gnu-gcc test.c -o test
FILE=$PWD/$(basename $PWD).ko
scp $FILE test root@192.168.137.128:/home/root

测试用例

c代码

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"int main(int argc, char *argv[])
{int fd, ret;char *filename;unsigned char data[1];if(argc != 2){printf("Error Usage!\r\n");return -1;}filename = argv[1];fd = open(filename, O_RDWR);if(fd < 0){printf("file %s open failed!\r\n", argv[1]);return -1;}while(1) {data[0] = 1;ret = write(fd, data, sizeof(data));if(ret < 0){printf("LED Control Failed!\r\n");close(fd);return -1;}usleep(500000);data[0] = 0;ret = write(fd, data, sizeof(data));if(ret < 0){printf("LED Control Failed!\r\n");close(fd);return -1;}usleep(500000);}ret = close(fd);if(ret < 0){printf("file %s close failed!\r\n", argv[1]);return -1;}return 0;
}

① 通过执行上面的build脚本,生成led.ko和test文件

② 插入内核驱动模块led.ko

③ 检查/dev目录是否已经生成设备节点

④ 执行test用例

在这里插入图片描述

命令行

在led.ko没有插入的情况下,也可以用以下脚本循环点亮LED灯

while true; 
do echo 1 > /sys/class/gpio/gpio48/value; sleep 0.5; echo 0 > /sys/class/gpio/gpio48/value; sleep 0.5; 
done;

实验效果

可以看到板子左下角第二颗LED被循环点亮

龙芯LS2K0300之LED驱动

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/32510.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【职场人】如何与同事有效沟通

在职场中&#xff0c;沟通如同桥梁&#xff0c;连接着每一位职场人士的心灵与智慧。有效的沟通不仅能让工作更加顺畅&#xff0c;还能让团队关系更加和谐。那么&#xff0c;如何与同事进行有效沟通呢&#xff1f;下面&#xff0c;我将结合个人经验和一些幽默的比喻&#xff0c;…

[ThreadX] NetX DHCP 客户端API

1、常用API nx_dhcp_create&#xff1a;创建 DHCP 实例nx_dhcp_clear_broadcast_flag&#xff1a;清除客户端消息上的广播标记nx_dhcp_delete&#xff1a;删除 DHCP 实例nx_dhcp_decline&#xff1a;向服务器发送拒绝消息nx_dhcp_force_renew&#xff1a;发送强制续订消息nx_d…

音频数据集1--LJSpeech单人语音

LJ Speech Dataset 版本号: 1.1 , 文件大小: 2.6GB 1.简介 1. 1 内容简介 LJS是一个语音数据集&#xff0c;包含 13,100 个音频片段&#xff0c;内容为Linda Johnson(欧美女性)朗读的 7 本书籍段落(非小说类)。每个片段都提供文本转录&#xff0c;片段长度从 1 到 10 秒不等&…

八大排序之希尔排序

一、概念及其介绍 希尔排序(Shell Sort)是插入排序的一种&#xff0c;它是针对直接插入排序算法的改进。 希尔排序又称缩小增量排序&#xff0c;因 DL.Shell 于 1959 年提出而得名。 它通过比较相距一定间隔的元素来进行&#xff0c;各趟比较所用的距离随着算法的进行而减小…

什么是微分和导数?

文章目录 设立问题微分特性指数特性线性特性常数特性 多项式微分导数 在机器学习领域&#xff0c;有多种解决最优化问题的方法&#xff0c;其中之一就是使用微分。 通过微分&#xff0c;可以得知函数在某个点的斜率&#xff0c;也可以了解函数在瞬间的变化。 设立问题 请想象一…

HTML 教程

HTML 教程 HTML(HyperText Markup Language)是一种用于创建网页的标准标记语言。它描述了一个网站的结构骨架,使得浏览器能够展示具有特定格式的文本、链接、图片和其他内容。本教程将带你深入了解HTML的基础知识,包括其语法、常用标签以及如何构建一个基本的网页结构。 …

Tortoise 删除文件

1、右击需要删除的文件&#xff0c;选择Delete 2、提交

【查看显卡信息】——Ubuntu和windows

1、VMware虚拟机 VMware虚拟机上不能使用CUDA/CUDNN&#xff0c;也安装不了显卡驱动 查看显卡信息&#xff1a; lspci | grep -i vga 不会显示显卡信息&#xff0c;只会输出VMware SVGA II Adapter&#xff0c;表示这是一个虚拟机&#xff0c;无法安装和使用显卡驱动 使用上…

GitHub 标星 6

美国网友对这个大全给予了很高的评价&#xff1a;这份清单中列出的开源软件&#xff0c;不仅解决了硅谷大厂前员工的难处&#xff0c;也能为其他所有码农解除困惑。 在这套大全的指导下&#xff0c;任何一个工程师&#xff0c;都能获得类似在谷歌内部写代码的体验。xg2xg 上线…

fot循环语句

概念&#xff1a; 循环是一种重复执行一段代码的结构&#xff0c;只要满足循环的条件&#xff0c;会一种执行这个代码。 循环条件&#xff1a;在一定范围内&#xff0c;按照指定的次数来执行循环 循环体&#xff1a;在指定的次数内&#xff0c;执行的命令序列。只要条件满足…

骑马与砍杀-战团mod制作-基础篇-武器模型入骑砍(二)

骑马与砍杀战团mod制作-基础-武器模型入骑砍笔记&#xff08;二&#xff09; 资料来源 学习的资料来源&#xff1a; b站【三啸解说】手把手教你做【骑砍】MOD&#xff0c;基础篇&#xff0c;链接为&#xff1a; https://www.bilibili.com/video/BV19x411Q7No?p4&vd_sour…

模型计算量估计,训练时间预测 Scaling Laws for Neural Language Models

一、模型计算量 C ≈ 6N*D 其中C表示训练语言模型所需的总计算量&#xff0c;N表示模型参数量&#xff0c;D表示用于训练的语料总量&#xff0c;6表示每训练一个token所需的浮点计算量约为6N&#xff0c;其中前向计算2N&#xff0c;反向计算4N。 注意&#xff1a;这里的6是针…

前端小白指南:前端生成唯一设备标识的那些事儿

最近&#xff0c;我在使用javascript开发一个基于Chrome的插件&#xff0c;遇到了一个有意思的需求。插件需要生成一个授权码&#xff08;code&#xff09;&#xff0c;但为了确保安全性&#xff0c;这个code必须与设备绑定&#xff0c;防止被不同的设备使用&#xff0c;限制一…

Python vs MATLAB: 易于学习和代码可理解性的对比

Python vs MATLAB Python vs MATLAB: 易于学习和代码可理解性**Python的易用性与代码理解****MATLAB的易用性与代码理解****哪个更易上手&#xff1f;****结论** Python vs MATLAB: 易于学习和代码可理解性 在科学计算、工程模拟和数据分析领域&#xff0c;Python和MATLAB是两…

使用 C++11 Lambda 表达式在 Qt 中连接信号与槽

在 Qt 使用 C11 引入的 lambda 表达式来简化信号与槽的连接已经成为一种不错的选择。本文将通过一个简单的例子来展示如何使用 lambda 表达式来连接 QAction 的信号与槽。 传统的连接方式 首先&#xff0c;看看传统的连接方式&#xff1a; QAction* action foo->addActi…

腾讯视频通话接口

简要描述 获取登录IM账号及签名请求URL /videocall/getImUserInfo?account=1234&appName=tv请求方式 GET参数 参数名必选类型说明account是string通话双方统一账号appName是string应用名称,区分不同类型应用如:TV,MINI返回示例 {"code": 200,"status"…

kafka 管理节点 Controller 角色分析

kafka 管理节点 Controller 角色分析 kafka controller 如何管理分区的创建、状态监测、故障切换、内容复制、如何管控分区副本的状态检测故障切换、数据同步、learder 选举?Kafka Controller 是 Kafka 集群中的一个关键组件,负责管理分区的创建、状态监测、故障切换、内容 …

document.write()方法总结

document.write()方法总结 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;document.write()方法是JavaScript中用于向HTML文档写入内容的方法之一。它允许我们在…

【团队成长】2024-25周周报-业务介绍内容创作

大家好&#xff01;我们是IndustryOR 团队&#xff0c;致力于分享业界落地的算法技术。欢迎关注微信公众号/知乎/CSDN【运筹匠心】 。 记录人&#xff1a;张哲铭&#xff0c;某互联网大厂算法专家 【团队成长/个人成长】系列的推文会以 【工作周报】 的方式记录IndustryOR团队及…

【SpringCloud-Seata源码分析2】

文章目录 分支事务注册-客户端分支事务服务端的执行 分支事务注册-客户端 第一篇我们将全局事务启动&#xff0c;以及开启源码分析完成了&#xff0c;现在我们需要看一下分支事务注册。 我们分支事务的开始需要从PreparedStatementProxy#executeUpdate中去看。 public class…