在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设备的更多相关文章

  1. RT thread 设备驱动组件之USART设备

    本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...

  2. RT-thread 设备驱动组件之SPI设备

    本文主要介绍RT-thread中的SPI设备驱动,涉及到的文件主要有:驱动框架文件(spi_dev.c,spi_core.c,spi.h),底层硬件驱动文件(spi_hard.c,spi_hard.h ...

  3. 【Linux高级驱动】linux设备驱动模型之平台设备驱动机制

    [1:引言: linux字符设备驱动的基本编程流程] 1.实现模块加载函数  a.申请主设备号    register_chrdev(major,name,file_operations);  b.创 ...

  4. Linux 驱动框架---cdev字符设备驱动和misc杂项设备驱动

    字符设备 Linux中设备常见分类是字符设备,块设备.网络设备,其中字符设备也是Linux驱动中最常用的设备类型.因此开发Linux设备驱动肯定是要先学习一下字符设备的抽象的.在内核中使用struct ...

  5. RT-thread 设备驱动组件之IIC总线设备

    本文主要介绍RT-thread中IIC总线设备驱动,涉及到的主要文件有:驱动框架文件(i2c_core.c,i2c_dev.c,i2c-bit-ops.c,i2c_dev.h,i2c.h):底层硬件驱 ...

  6. Linux中总线设备驱动模型及平台设备驱动实例

    本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...

  7. Linux设备驱动编程之复杂设备驱动

    这里所说的复杂设备驱动涉及到PCI.USB.网络设备.块设备等(严格意义而言,这些设备在概念上并不并列,例如与块设备并列的是字符设备,而PCI.USB设备等都可能属于字符设备),这些设备的驱动中又涉及 ...

  8. Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志【转】

    转自:http://blog.csdn.net/yikai2009/article/details/8653697 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 阻塞 阻 ...

  9. linux设备驱动第一篇:设备驱动程序简介

    首先,我们知道驱动是内核的一部分,那么驱动在内核中到底扮演了什么角色呢? 设备驱动程序在内核中的角色:他们是一个个独立的“黑盒子”,使某个特定的硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设 ...

随机推荐

  1. Linux 下 gcc 与 g++的差别

    参考网易博客者"静心"的博客--<gcc与g++的区别>结合自己的认识做出的个人领悟.(由于个人水平有限,难免会存在错误的地方,请见谅) 一般而言,在Linux下编译程 ...

  2. yii2 shi用modal弹窗 select2搜索框无法使用

    在modal使用begin的时候指定options选项的tabindex为false Modal::begin([ // ...... 'options' => [ 'tabindex' =&g ...

  3. 为 ItemsControl 类型的控件提供行号,mvvm模式 绑定集合

    从网络上看到的两种方式,一种是,在 codebehind 里为 控件写事件,下面是将集合绑定到 DataGrid 控件: private void DataGridSoftware_LoadingRo ...

  4. DSP5509之采样定理

    1. 在实际种信号是模拟连续的,但是AD采样确实离散的数字的,根据采样定理,采样频率要是模拟信号的频率2倍以上采样到的值才没问题. 2. 打开工程 unsigned ]; main() { int i ...

  5. MySQL高级-查询截取分析

    一.如何分析 1.观察.至少跑1天,看看生产的慢SQL情况. 2.开启慢查询日志,设置阙值比如超过5秒钟的就是慢SQL,并将它抓取出来. 3.explain + 慢SQL分析 4.show profi ...

  6. c的多态

    使用函数数组,实现多态 参考my_strtoll10

  7. 容器云技术:容器化微服务,Istio占C位出道

    在精彩的软件容器世界中,当新项目涌现并解决你认为早已解决的问题时,这感觉就像地面在你的脚下不断地移动.在许多情况下,这些问题很久以前被解决,但现在的云原生架构正在推动着更大规模的应用程序部署,这就需要 ...

  8. fastCMS八大核心对象

    fastCMS内置system对象,该对象包含八大核心对象,应用于不同的操作场景,分别是: 1.system.string 对象(处理字符类操作) 2.system.number 对象(处理数字类操作 ...

  9. Python全栈 Web(边框、盒模型、背景)

    原文地址 https://yq.aliyun.com/articles/634926 ......................................................... ...

  10. 购物单:Excel的应用

    题目描述: 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞. 这不,XX大促销又来了!老板夫人开出了长长的购物单,都是有打折优惠 ...