RT-thread 设备驱动组件之PIN设备
在RT-thread 2.0.0正式版中引入了pin设备作为杂类设备,其设备驱动文件pin.c在rt-thread-2.0.1\components\drivers\misc中,主要用于操作芯片GPIO, 如点亮led,按键等。同时对于相应的芯片平台,需要自行编写底层gpio驱动,如gpio.c。本文主要涉及的pin设备文件有:驱动框架文件(pin.c,pin.h),底层硬件驱动文件(gpio.c,gpio.h)。在应用用PIN设备时,需要在rtconfig.h中宏定义#define RT_USING_PIN。
一、PIN设备驱动框架
在pin.c中定义了一个静态的pin设备对象static struct rt_device_pin _hw_pin,其中结构体类型struct rt_device_pin在pin.h中定义为:
/* pin device and operations for RT-Thread */
struct rt_device_pin
{
struct rt_device parent;
const struct rt_pin_ops *ops;
};
struct rt_device_pin_mode
{
rt_uint16_t pin; //pin index in pins[] of gpio.c
rt_uint16_t mode;
};
struct rt_device_pin_status
{
rt_uint16_t pin; //pin index in pins[] of gpio.c
rt_uint16_t status;
}; struct rt_pin_ops
{
void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);
void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);
int (*pin_read)(struct rt_device *device, rt_base_t pin); /* TODO: add GPIO interrupt */
};
在pin.c中主要实现了_pin_read,_pin_write,_pin_control三个函数,同时将这三个函数注册为_hw_pin设备的统一接口函数:
int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data)
{
_hw_pin.parent.type = RT_Device_Class_Miscellaneous;
_hw_pin.parent.rx_indicate = RT_NULL;
_hw_pin.parent.tx_complete = RT_NULL; _hw_pin.parent.init = RT_NULL;
_hw_pin.parent.open = RT_NULL;
_hw_pin.parent.close = RT_NULL;
_hw_pin.parent.read = _pin_read;
_hw_pin.parent.write = _pin_write;
_hw_pin.parent.control = _pin_control; _hw_pin.ops = ops;
_hw_pin.parent.user_data = user_data; /* register a character device */
rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR); return ;
}
最后,在pin.c文件中将rt_pin_mode,rt_pin_write,rt_pin_read三个函数加入到finsh的函数列表中,用于调试。
二、底层硬件驱动
在gpio.c中主要实现struct rt_pin_ops中的三个接口函数:stm32_pin_mode,stm32_pin_write,stm32_pin_read:
const static struct rt_pin_ops _stm32_pin_ops =
{
stm32_pin_mode,
stm32_pin_write,
stm32_pin_read,
};
同时注册 _hw_pin设备,其设备名称为“pin”,PIN设备硬件初始化:
int stm32_hw_pin_init(void)
{
rt_device_pin_register("pin", &_stm32_pin_ops, RT_NULL);
return ;
}
INIT_BOARD_EXPORT(stm32_hw_pin_init);//stm32_hw_pin_init will be called in rt_components_board_init()
三、PIN设备初始化
在gpio.c中修改使用的IO口数组:
/* STM32 GPIO driver */
struct pin_index
{
int index;
uint32_t rcc;
GPIO_TypeDef *gpio;
uint32_t pin;
}; /* LED ->PD12,PD13,PD14,PD15; USER Button->PA0 */
static const struct pin_index pins[] =
{
{ , RCC_AHB1Periph_GPIOD, GPIOD, GPIO_Pin_12}, //green
{ , RCC_AHB1Periph_GPIOD, GPIOD, GPIO_Pin_13}, //orange
{ , RCC_AHB1Periph_GPIOD, GPIOD, GPIO_Pin_14}, //red
{ , RCC_AHB1Periph_GPIOD, GPIOD, GPIO_Pin_15}, //blue
{ , RCC_AHB1Periph_GPIOA, GPIOA, GPIO_Pin_0}, //user button
};
此外在gpio_pin.c的外设初始化函数中,需要先调用rt_device_open函数(尽管该函数没有在底层实现),保证pin设备对象类的设备引用计数值ref_count不为0,这样才可正常使用rt_device_control,rt_device_write,rt_device_read函数操作GPIO口:
static struct rt_device_pin_mode led_mode[]=
{
{,PIN_MODE_OUTPUT},
{,PIN_MODE_OUTPUT},
{,PIN_MODE_OUTPUT},
{,PIN_MODE_OUTPUT},
}; static struct rt_device_pin_status led_status[]=
{
{,PIN_HIGH}, /* 0:green on */
{,PIN_HIGH}, /* 1:orange on */
{,PIN_HIGH}, /* 2:red on */
{,PIN_HIGH}, /* 3:blue on */ {,PIN_LOW}, /* 4:green off */
{,PIN_LOW}, /* 5:orange off */
{,PIN_LOW}, /* 6:red off */
{,PIN_LOW}, /* 7:blue off */
}; /* it can't be PIN_MODE_INPUT_PULLUP, or the key always will keep PIN_HIGH status */
static struct rt_device_pin_mode key_mode = {,PIN_MODE_INPUT};
static struct rt_device_pin_status key_status = {,PIN_LOW}; static struct rt_device_pin * pin_device;
static rt_err_t gpio_pin_init(const char * pin_device_name)
{
pin_device = (struct rt_device_pin *)rt_device_find(pin_device_name);
if(pin_device == RT_NULL)
{
rt_kprintf("pin device for gpio %s not found!\r\n", pin_device_name);
return -RT_ENOSYS;
} /* oflag has no meaning for pin device , so set to RT_NULL */
if(rt_device_open(&pin_device->parent, RT_NULL) == RT_EOK)
{
/* init led */
for(int i=; i<(sizeof(led_mode)/sizeof(led_mode[])); i++)
{
rt_device_control(&pin_device->parent, RT_NULL, &led_mode[i]);
rt_device_write(&pin_device->parent, RT_NULL, &led_status[i], sizeof(led_status[i]));//init all led PIN_HIGH
} /* init key */
rt_device_control(&pin_device->parent, RT_NULL, &key_mode);
} return ;
} int rt_gpio_pin_init(void)
{
gpio_pin_init("pin"); return ;
}
INIT_APP_EXPORT(rt_gpio_pin_init);
RT-thread 设备驱动组件之PIN设备的更多相关文章
- RT thread 设备驱动组件之USART设备
本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...
- RT-thread 设备驱动组件之SPI设备
本文主要介绍RT-thread中的SPI设备驱动,涉及到的文件主要有:驱动框架文件(spi_dev.c,spi_core.c,spi.h),底层硬件驱动文件(spi_hard.c,spi_hard.h ...
- 【Linux高级驱动】linux设备驱动模型之平台设备驱动机制
[1:引言: linux字符设备驱动的基本编程流程] 1.实现模块加载函数 a.申请主设备号 register_chrdev(major,name,file_operations); b.创 ...
- Linux 驱动框架---cdev字符设备驱动和misc杂项设备驱动
字符设备 Linux中设备常见分类是字符设备,块设备.网络设备,其中字符设备也是Linux驱动中最常用的设备类型.因此开发Linux设备驱动肯定是要先学习一下字符设备的抽象的.在内核中使用struct ...
- RT-thread 设备驱动组件之IIC总线设备
本文主要介绍RT-thread中IIC总线设备驱动,涉及到的主要文件有:驱动框架文件(i2c_core.c,i2c_dev.c,i2c-bit-ops.c,i2c_dev.h,i2c.h):底层硬件驱 ...
- Linux中总线设备驱动模型及平台设备驱动实例
本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...
- Linux设备驱动编程之复杂设备驱动
这里所说的复杂设备驱动涉及到PCI.USB.网络设备.块设备等(严格意义而言,这些设备在概念上并不并列,例如与块设备并列的是字符设备,而PCI.USB设备等都可能属于字符设备),这些设备的驱动中又涉及 ...
- Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志【转】
转自:http://blog.csdn.net/yikai2009/article/details/8653697 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 阻塞 阻 ...
- linux设备驱动第一篇:设备驱动程序简介
首先,我们知道驱动是内核的一部分,那么驱动在内核中到底扮演了什么角色呢? 设备驱动程序在内核中的角色:他们是一个个独立的“黑盒子”,使某个特定的硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设 ...
随机推荐
- JVM基础知识及拓展
我们可以吧JVM的基本结构分为四块:类加载器.执行引擎.运行时数据区和本地接口.一般来说Java程序在JVM中的执行流程如下: ①.首先我们会利用javac命令将我们所编写的.java源代码文件变异成 ...
- 北京Uber优步司机奖励政策(1月28日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- MySql 使用explain分析查询
今天写了个慢到哭的查询,想用explain分析下执行计划,后来发现explain也是有局限性的: EXPLAIN不会告诉你关于触发器.存储过程的信息或用户自定义函数对查询的影响情况 •EXPLAIN不 ...
- OpenCV 3.2 Tracking 物体跟踪
跟踪就是在连续视频帧中定位物体,通常的跟踪算法包括以下几类: 1. Dense Optical Flow 稠密光流 2. Sparse Optical Flow 稀疏光流 最典型的如KLT算法(Kan ...
- 并发任务管理器AsyncTaskManager
//-------------------------------------------------------------------------- // // Copyright (c) BUS ...
- 用Scanner读文本文件内容
import java.io.File; import java.util.Scanner; class Demo { public static void main(String[] args) t ...
- EF Core注意事项
流程:https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/new-db 1.Both Entity Framework 6. ...
- 修改Eclipse中项目在Apache Tomcat中的部署路径
在Eclipse中配项目已经部署到如下默认目录下:eclipse workspace/.metadata/.plugins/org.eclipse.core.resources/.projects. ...
- Spring学习记录-Java 11运行eureka-server报javax.xml.bind.JAXBContext not present错
在pom.xml加入依赖就行 <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId&g ...
- Qt-QML-Repeater-导航条
上篇文章中,我写了一个自己的Button,也就是美化了一下QML自带的Button 就是上面的这个,剩下的就是放三张图片在上面就可以了,当然了,这个Button在后期,还是会加入更让多的美化,比如,可 ...