【PHYTEC开发板试用体验】2 实现一个酷炫霓虹灯_Part-B-开发工程师php招聘

本文来源电子发烧友社区,作者:jf_00240724, 帖子地址:https://bbs.elecfans.com/jishu_2284706_1_1.html

今天我们接上一篇继续,需要做两个事情。第一个是重写驱动,第二个是开发霓虹灯应用程序。

第一章 重写驱动

一.1. 知识储备

一.1.1. 卸载驱动

一.1.1.1. linux加载/卸载驱动有两种方法

一.1.1.1.1. modprobe

这里我们主要用这个。

注:在使用这个命令加载模块前先使用depmod -a命令生成modules.dep文件,该文件位于/lib/modules/$(uname -r)目录下;modprobe命令智能地向内核中加载模块或者从内核中移除模块,可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的依赖关系,决定要载入哪些模块。若在载入过程中出错,modprobe会卸载整组的模块。

载入模块的命令:

(1) 载入指定的模块:modprobe drv.ko

(2) 载入全部模块:modprobe -a

卸载模块的命令:modprobe -r drv.ko

modprobe命令用于智能地向内核中加载模块或者从内核中移除模块。

modprobe可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的相依关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。

选项

-a或–all:载入全部的模块;

-c或–show-conf:显示所有模块的设置信息;

-d或–debug:使用排错模式;

-l或–list:显示可用的模块;

-r或–remove:模块闲置不用时,即自动卸载模块;

-t或–type:指定模块类型;

-v或–verbose:执行时显示详细的信息;

-V或–version:显示版本信息;

-help:显示帮助。

参数 模块名:要加载或移除的模块名称。

实例

查看modules的配置文件:modprobe -c

这里,可以查看modules的配置文件,比如模块的alias别名是什么等。会打印许多行信息,例如其中的一行会类似如下:

alias symbol:ip_conntrack_unregister_notifier ip_conntrack

列出内核中所有已经或者未挂载的所有模块:modprobe -l

这里,我们能查看到我们所需要的模块,然后根据我们的需要来挂载;其实modprobe -l读取的模块列表就位于/lib/modules/`uname -r`目录中;其中uname -r是内核的版本,例如输出结果的其中一行是:

/lib/modules/2.6.18-348.6.1.el5/kernel/net/netfilter/xt_statistic.ko

挂载vfat模块:modprobe vfat

这里,使用格式modprobe 模块名来挂载一个模块。挂载之后,用lsmod可以查看已经挂载的模块。模块名是不能带有后缀的,我们通过modprobe -l所看到的模块,都是带有.ko或.o后缀。

移除已经加载的模块:modprobe -r 模块名

这里,移除已加载的模块,和rmmod功能相同。

一.1.1.1.2. rmmod

这个卸载命令不会把其依赖模块一同卸掉,所以这里我们只作简单介绍。

一.1.2. Linux驱动框架

接下来,我们开始重新写驱动,linux系统下写驱动,其实就是配置相应的硬件寄存器,那本章的霓虹灯驱动,也就是对imX 8的GPIO进行配置,由于裸机实验不同的是,并且驱动要符合linux驱动框架,下面我们来先理解了解一下linux的驱动框架。

一.1.2.0.1. 地址映射

linux的驱动,并不能够直接操作寄存硬件寄存器,而是需要通过MMU即内存管理单元,它的主要功能是

一、以完成虚拟空间的物理空间的映射

二、内存保护设置存储器的访问权限,设置虚拟存储空间的缓冲特性

这里我们会用到两个函数ioremap,iounmap,它们分别是用来获取物理地址空间对应的虚拟地址,和卸载时释放掉之前所做的映射

一.1.2.0.2. linux内存访问函数

对于arm来说,只有IO内存,linux内核建议使用一组操作函数来对映射后的内存进行读写操作

一、读操作函数

<

1 u8 readb(constvolatilevoid __iomem *addr)

2 u16 readw(constvolatilevoid __iomem *addr)

3 u32 readl(constvolatilevoid __iomem *addr)

>

readb、readw和readl这三个函数分别对应8bit、16bit和32bit读操作,参数addr就是要读取写内存地址,返回值就是读取到的数据。

二、写操作函数

<

1void writeb(u8 value,volatilevoid __iomem *addr)

2void writew(u16 value,volatilevoid __iomem *addr)

3void writel(u32 value,volatilevoid __iomem *addr)

>

writeb、writew和writel这三个函数分别对应8bit、16bit和32bit写操作,参数value是要写入的数值,addr是要写入的地址。

接下来我们开始搭建一个linux驱动框架:

<

#include “linux/init.h”

#include “linux/module.h”

#include “linux/fs.h”

#include “linux/types.h”

// struct inode 声明在 linux/fs.h 中

// struct file 声明在 linux/fs.h 中

int led_open (struct inode *i, struct file *f)

{

// printk 声明在 linux/printk.h 中

printk(“led open!rn”);

return 0;

}

int led_release (struct inode *i, struct file *f)

{

printk(“led release!rn”);

return 0;

}

// ssize_t 定义在 linux/types.h 中

// __user 定义在 linux/compiler.h 中

// size_t 定义在 linux/types.h 中

// loff_t 定义在 linux/types.h 中

ssize_t led_read (struct file *f, char __user *b, size_t c, loff_t * l)

{

printk(“led read!rn”);

return 0;

}

ssize_t led_write (struct file *f, const char __user *b, size_t c, loff_t *l)

{

printk(“led write!rn”);

return 0;

}

// 声明在 linux/fs.h 头文件中

static struct file_operations fops = {

.open = led_open,

.release = led_release,

.read = led_read,

.write = led_write,

};

/* 驱动入口函数 */

static int __init led_init(void)

{

/* 入口函数具体内容 */

int retvalue = 0;

// 声明在 linux/fs.h 头文件中

retvalue = register_chrdev(200,”chrdev”,&fops);

if(retvalue < 0){

/* 字符设备注册失败 */

}

return 0;

}

/* 驱动出口函数 */

static void __exit led_exit(void)

{

/* 出口函数具体内容 */

// 声明在 linux/fs.h 头文件中

unregister_chrdev(200,”chrdev”);

}

// 声明在 linux/init.h 头文件中

/* 将上面两个函数指定为驱动的入口和出口函数 */

module_init(led_init);

module_exit(led_exit);

// 声明在 linux/module.h 头文件中

MODULE_LICENSE(“GPL”);

>

这只是一个驱动框架没有实际内容。

一.2. 硬件准备

接下来我们要找到电路原理图,和主芯片的操作手册从而找到LED灯对应的哪一个引脚以及其对应的寄存器。

在如下链接中我们找到这样一句话,好吧,原来他并不是GPIO控制的,而是一个iic芯片PCA9533中转控制的,不得不说这个硬件设计让人匪夷所思啊。

Multicolor (RGB) LED (D24)

The phyBOARD-Pollux provides one multicolor (RGB) LED (D24) (see phyBOARD-Pollux Components (Top)). The LEDs are connected to a LED driver (NXP PCA9533/01) controlled by I2C2 bus.

https://www.phytec.de/cdocuments … wareManual-LEDsLEDs

一.3. 软件-实操

一.3.1. 驱动卸载

基于以上的知识储备,本来想尝试一下卸载得掉leds这个驱动?但最终发现不是我们以上准备的驱动框架,而是sysfs的驱动框架,稍微研究一下,发现有点难度,值得针对性的再写一篇。

在此我们就不去卸载了。

一.3.2. 驱动编写

等研究好了sysfs驱动框架后,再实操一遍iic驱动编写。

第二章 应用程序

二.1. 代码

这里直接上代码:

二.1.1. Leds_app.h

<

typedef enum{

LED1_RED = 1,

LED2_GREEN,

LED3_BULE

}LED_ID;

int leds_control(LED_ID led_id,unsigned char brightness)

>

二.1.2. Leds_app.c

<

int leds_control(LED_ID led_id,unsigned char brightness)

{

int fd = 0;

int ret = 0,len;

/*this buffer size is sufficient to store file path */

char buf[128];

//printf(“enter leds_controlrn”);

snprintf(buf, sizeof(buf), “/sys/class/leds/user-led%d/brightness”,led_id);

fd = open(buf, O_RDWR);

if(fd < 0){

printf(“Cant open file %srn”, buf);

return -1;

}

len = snprintf(buf, sizeof(buf),”%d”, brightness);

ret =write(fd, buf, len);

if (ret < 0)

perror(“sysfs_led_write:”);

ret = close(fd);

if(ret < 0){

printf(“Cant close file for led%drn”, led_id);

return -1;

}

// printf(“leaveleds_controlrn”);

return 0;

}

>

二.1.3. Main.c

<

#include

#include

#include

#include “stdio.h”

#include “leds_app.h”

int main(int argc, char *argv[])

{

int led1_value,led2_value,led3_value;

while (1) {

led1_value = rand()%255;

led2_value = rand()%255;

led3_value = rand()%255;

printf(“led1:%3d led2:%3d led3:%3dn”,led1_value,led2_value,led3_value);

leds_control(LED3_BULE,0);

leds_control(LED1_RED,led1_value);

sleep(0.9);

//leds_control(LED1_RED,0);

leds_control(LED2_GREEN,led2_value);

sleep(0.8);

leds_control(LED2_GREEN,0);

leds_control(LED3_BULE,led3_value);

sleep(0.5);

}

}

>

二.2. Log

打印出如下log

<

10:48:51: Starting /opt/HelloQuick/bin/HelloQuick …

Warning: Identity filenot accessible: No such file or directory.

QML debugging is enabled. Only use this in a safe environment.

led1:163 led2:151 led3:162

led1: 85 led2: 83 led3:190

led1:241 led2:252 led3:249

led1:121 led2:107 led3: 82

led1: 20 led2: 19 led3:233

led1:226 led2: 45 led3: 81

led1:142 led2: 31 led3: 86

led1:8 led2: 87 led3: 39

led1:167 led2:5 led3:212

>

二.3. 看效果:

请观看底部视频

霓虹灯效果

免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:【PHYTEC开发板试用体验】2 实现一个酷炫霓虹灯_Part-B-开发工程师php招聘 https://www.yhzz.com.cn/a/6059.html

上一篇 2023-04-12
下一篇 2023-04-12

相关推荐

联系云恒

在线留言: 我要留言
客服热线:400-600-0310
工作时间:周一至周六,08:30-17:30,节假日休息。