网站建设明细标价表,建网站有多少种方式,直播app开发哪家好,购物网站线下推广办法练习要求#xff1a; 一、设备树 1、配置设备树信息#xff1a;将3个led灯和1个风扇使用到的设备信息配置到设备树中 二、设备驱动层 1、通过of_find_node_by_name、of_get_named_gpion等内核核心层统一的api接口调用外设#xff1b; 2、通过udev设备管理器自动注册并创建设… 练习要求 一、设备树 1、配置设备树信息将3个led灯和1个风扇使用到的设备信息配置到设备树中 二、设备驱动层 1、通过of_find_node_by_name、of_get_named_gpion等内核核心层统一的api接口调用外设 2、通过udev设备管理器自动注册并创建设备文件 3、通过ioctl控制开启/关闭外设其中3个led灯通过传递 设备名称-次设备号minor 控制具体的某栈灯 三、应用层 1、多线程开发第一个线程实现三个灯的流水第二个线程实现风扇的控制 2、通过open、close、ioctl 对应的字符设备文件调用对应的驱动 1、设备树的配置
arch/arm/boot/dts/stm32mp157a-fsmp1a.dts (根目录 / 里面)
leds{led1-gpio gpioe 10 0;led2-gpio gpiof 10 0;led3-gpio gpioe 8 0;
};fans{fan-gpio gpioe 9 0;
};
2、源码
2.1、应用程序
app.c
#include stdio.h
#include pthread.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include string.h
#include sys/ioctl.h
#include led_driver.h
#include fan_driver.hvoid *led_task(void *args)
{// 打开文件int fd1 open(/dev/myled1, O_RDWR);int fd2 open(/dev/myled2, O_RDWR);int fd3 open(/dev/myled3, O_RDWR);// 操作硬件for (int i 0;; i){if (i % 3 0){ioctl(fd1, CMD_LED_ON);ioctl(fd2, CMD_LED_OFF);ioctl(fd3, CMD_LED_OFF);}else if (i % 3 1){ioctl(fd1, CMD_LED_OFF);ioctl(fd2, CMD_LED_ON);ioctl(fd3, CMD_LED_OFF);}else{ioctl(fd1, CMD_LED_OFF);ioctl(fd2, CMD_LED_OFF);ioctl(fd3, CMD_LED_ON);}sleep(1);}// 关闭文件close(fd1);close(fd2);close(fd3);
}// void *beep_task(void *args)
// {
// // 打开文件
// int fd open(/dev/mybeep, O_RDWR);
// char cmd[3] {0};
// unsigned short cnt 0;
// printf(beep_task\n);
// for (int i 0;; i)
// {
// if (cnt % 5 0)
// {
// ioctl(fd, CMD_BEEP_ON);
// }
// else
// {
// ioctl(fd, CMD_BEEP_OFF);
// }
// sleep(1);
// }
// // 关闭文件
// close(fd);
// }void *fan_task(void *args)
{// 打开文件int fd open(/dev/myfan, O_RDWR);for(int i0;;i){if (i % 2 0){ioctl(fd, CMD_FAN_ON);}else{ioctl(fd, CMD_FAN_OFF);}sleep(5);}// 关闭文件close(fd);
}int main(int argc, char *argv)
{pthread_t pid1, pid2, pid3;pthread_create(pid1, NULL, led_task, NULL);// pthread_create(pid2, NULL, beep_task, NULL);pthread_create(pid3, NULL, fan_task, NULL);pthread_join(pid1, NULL);// pthread_join(pid2, NULL);pthread_join(pid3, NULL);return 0;
}
2.2、led驱动程序
led.h:
#ifndef _LED_H_
#define _LED_H_//
#define CMD_LED_ON _IO(L, 0)
#define CMD_LED_OFF _IO(L, 1)
//#endif
led.c:
#include linux/fs.h
#include linux/init.h
#include linux/module.h
#include linux/device/class.h
#include linux/device.h
#include linux/gpio.h
#include linux/of.h
#include linux/of_gpio.h
#include led_driver.hint major; // 主设备号
struct device_node *np; // 设备树节点
int led1_gpio_no; // gpio编号
int led2_gpio_no;
int led3_gpio_no;
struct class *pClass; // udev的文件类指针long file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{int signal 0;int minor (int)file-private_data;int gpio_no;if (minor 1)gpio_no led1_gpio_no;else if(minor 2)gpio_no led2_gpio_no;else gpio_no led3_gpio_no;if (cmd CMD_LED_ON){signal1;}else{signal0;}//改变gpio的电平值gpio_set_value(gpio_no, signal);return 0;
}int file_open(struct inode *inode, struct file *file)
{file-private_data (void*)MINOR(inode-i_rdev);return 0;
}int file_close(struct inode *inode, struct file *file)
{return 0;
}struct file_operations led_fops {.unlocked_ioctl file_ioctl,.open file_open,.release file_close};int __init led_driver_init(void)
{int minor;// 注册字符设备驱动 register_chrdevmajor register_chrdev(0, myled, led_fops);if (major 0){printk(register_chrdev failed\n);return -1;}printk(register_chrdev succes. major[%d]\n, major);// 从设备树获取硬件信息np of_find_node_by_name(NULL, leds);if (np NULL){printk(of_find_node_by_name failed\n);return -1;}printk(of_find_node_by_name success\n);// led1 获取gpio操作句柄led1_gpio_no of_get_named_gpio(np, led1-gpio, 0);if (led1_gpio_no 0){printk(of_get_named_gpio failed\n);return -1;}printk(of_get_named_gpio success. no1[%d]\n, led1_gpio_no);if (gpio_request(led1_gpio_no, led1) 0){printk(gpio_request failed\n);return -1;}printk(gpio_request success\n);gpio_direction_output(led1_gpio_no, 0);// led1 获取gpio操作句柄led2_gpio_no of_get_named_gpio(np, led2-gpio, 0);if (led2_gpio_no 0){printk(of_get_named_gpio failed\n);return -1;}printk(of_get_named_gpio success. no2[%d]\n, led2_gpio_no);if (gpio_request(led2_gpio_no, led2) 0){printk(gpio_request failed\n);return -1;}printk(gpio_request success\n);gpio_direction_output(led2_gpio_no, 0);// led3 获取gpio操作句柄led3_gpio_no of_get_named_gpio(np, led3-gpio, 0);if (led3_gpio_no 0){printk(of_get_named_gpio failed\n);return -1;}printk(of_get_named_gpio success. no3[%d]\n, led3_gpio_no);if (gpio_request(led3_gpio_no, led3) 0){printk(gpio_request failed\n);return -1;}printk(gpio_request success\n);gpio_direction_output(led3_gpio_no, 0);// 初始化gpio// 向设备管理器udev注册设备文件信息pClass class_create(THIS_MODULE, myled);if (IS_ERR(pClass)){printk(class_create failed\n);return -1;}printk(class_create success\n);for (minor 1; minor 4; minor){struct device *pDev device_create(pClass, NULL, MKDEV(major, minor), NULL, myled%d, minor);if (IS_ERR(pDev)){printk(device_create failed\n);return -1;}printk(device_create success. major[%d], monor[%d]\n, major, minor);}return 0;
}void __exit led_driver_exit(void)
{int minor;// 从设备管理器udev注销设备文件信息for (minor 1; minor 4; minor){device_destroy(pClass, MKDEV(major, minor));}class_destroy(pClass);// 释放gpio资源gpio_free(led1_gpio_no);// 注销字符设备驱动 unregister_chrdevunregister_chrdev(major, myled);
}module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE(GPL);2.3、fan驱动程序
fan.h:
#ifndef _FAN_H_
#define _FAN_H_#define CMD_FAN_ON _IO(F, 0)
#define CMD_FAN_OFF _IO(F, 1)#endif
fan.c:
#include linux/fs.h
#include linux/init.h
#include linux/module.h
#include linux/device/class.h
#include linux/device.h
#include linux/gpio.h
#include linux/of.h
#include linux/of_gpio.h
#include fan_driver.hint major;//主设备号
struct device_node * np;//设备树节点
int fan_gpio_no;//设备树种gpio编号
struct class *pClass;//udev中的文件分类long file_ioctl(struct file * file, unsigned int cmd, unsigned long arg){if(cmd CMD_FAN_ON){printk(!!!!开风扇\n);gpio_set_value(fan_gpio_no, 1);}else if(cmd CMD_FAN_OFF){printk(!!!!关风扇\n);gpio_set_value(fan_gpio_no, 0);}return 0;
}int file_open(struct inode * inode, struct file * file){return 0;
}int file_close(struct inode * inode, struct file * file){return 0;
}struct file_operations led_fops{.unlocked_ioctl file_ioctl,.open file_open,.release file_close
};int __init fan_driver_init(void){//注册字符设备驱动 register_chrdevmajor register_chrdev(0, myfan, led_fops);if(major 0){printk(register_chrdev failed\n);return -1;}printk(register_chrdev succes. major[%d]\n, major);//从设备树获取硬件信息np of_find_node_by_name(NULL, fans);if(np NULL){printk(of_find_node_by_name failed\n);return -1; }printk(of_find_node_by_name success\n);//获取gpio操作句柄fan_gpio_no of_get_named_gpio(np, fan-gpio, 0);if (fan_gpio_no 0){printk(of_get_named_gpio failed\n);return -1;}printk(of_get_named_gpio success. fan_gpio_no[%d]\n, fan_gpio_no);if(gpio_request(fan_gpio_no, fan-gpio) 0){printk(gpio_request failed\n);return -1;}printk(gpio_request success\n);//初始化gpio//设置gpio为输出gpio_direction_output(fan_gpio_no, 0);//向设备管理器udev注册设备文件信息pClass class_create(THIS_MODULE, fan_class);if (IS_ERR(pClass)) {printk(class_create failed\n);return -1;}printk(class_create success\n);struct device * pDevicedevice_create(pClass, NULL, MKDEV(major, 0), NULL, myfan);if(IS_ERR(pDevice)){printk(device_create failed\n);return -1;}printk(device_create success\n);return 0;
}void __exit fan_driver_exit(void){//从设备管理器udev注销设备文件信息device_destroy(pClass, MKDEV(major, 0));class_destroy(pClass);//释放gpio资源gpio_free(fan_gpio_no);//注销字符设备驱动 unregister_chrdevunregister_chrdev(major, myfan);
}module_init(fan_driver_init);
module_exit(fan_driver_exit);
MODULE_LICENSE(GPL);3、疑问
配置设备树中引用关系并没有搞明白暂且认为是一种固定的格式。
例如