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设备驱动第一篇:设备驱动程序简介
首先,我们知道驱动是内核的一部分,那么驱动在内核中到底扮演了什么角色呢? 设备驱动程序在内核中的角色:他们是一个个独立的“黑盒子”,使某个特定的硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设 ...
随机推荐
- 笔记-python-float(‘inf’)
笔记-python-float(‘inf’) 看算法时发现了flaot(‘inf’). Python中可以用如下方式表示正负无穷: float("inf"), float(&quo ...
- Java中syso的封装
将syso设置为由开关切换确实是个很不错的思想,这样就不用傻傻的一个个去找不用的syso进行删除或者注释 当然了,由网友所说,这叫日志系统情何以堪,这里想说的是这个开关的思想值得我这小白学习 此为看 ...
- 20145202马超《java》【课堂实验】P98测试
当时在加水印所以没来得及提交,然而我回宿舍第一时间就提交了,希望老师额能够看到
- Python:PyCharm如何导入模块
- SpringBoot-01:什么是SpringBoot?
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- SpringBoot: Spring Boot可以轻松创建独立的,生产级的基于Spring的应用程序,您可以“ ...
- docker社区的geodata/gdal镜像dockerfile分析
对应从事遥感与地理信息的同仁来说,gdal应该是所有工具中使用频度最高的库了,那么在docker中使用gdal时,面临的第一步就是构建gdal基础镜像,社区中引用最多的就是geodata提供的gdal ...
- Qt-QSplashScreen-程序启动动画
多数大型应用程序启动时可会在程序完全启动前显示一个启动画面,在程序完全启动后消失,程序启动画面可以显示相关产品的一些信息,使用户在等待程序启动时同时了解产品的相关功能,这也是一种宣传方式. 首先运行界 ...
- 爬虫——URL模块爬取糗事百科段子
最简单的爬取网页找有用信息,难点应该是正则锁定有用信息部分,看了一些其他大神的正则,最后还是决定按照自己理解写一个,果然我头脑相对简单,写出来的粗糙而易理解,也完成了自己想要的需求,就这样了~ # - ...
- JavaScript 的一些基础知识
JavaScript基本语法 调试 打开 Chrome 开发工具 Win F12 Mac Command + Option + I 输入代码.测试执行 var str = 'evenyao' cons ...
- Java开发中用的比较多的数据结构
java 中几种常用数据结构 2016年07月11日 09:11:27 阅读数:83211 标签: 数据结构java 更多 个人分类: 自行学习 JAVA中常用的数据结构(java.util. 中 ...