在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. Java基础之this和super关键字用法

    this 在java中,this是一个引用当前类对象的引用变量,主要有以下几种用法: 引用当前类的实例变量· this关键字可以用来引用当前类的实例变量.如果实例变量和某个方法的参数之间存在歧义(实例 ...

  2. object转List<XXX>的问题

    List<object> demo(object a) { List<object> res = new List<object>(); object c = a; ...

  3. nginx 路由配置

    nginx中location对url匹配: 语法:location [=|~|~*|^~] /uri/ { … } 当匹配中符合条件的location,则执行内部指令:如果使用正则表达式,必须使用~* ...

  4. Android 9 适配怎么做? “QQ音乐”优化实录

    WeTest 导读 2018年8月7日,Google对外发布最新 Android 9.0 正式版系统,并宣布系统版本Android P 被正式命名为代号“Pie”,最新系统已经正式推送包括谷歌Pixe ...

  5. Windows系统常用修复命令 无须重装系统

    1.0 netsh int ipv4 reset 2.0 netsh winsock reset winsock是Windows网络编程接口,winsock工作在应用层,它提供与底层传输协议无关的高层 ...

  6. Java 语法基础

    一 关键字 关键字: 其实就是某种语言赋予了特殊含义的单词 保留字: 其实就是还没有赋予特殊含义 但是准备日后要使用过的单词 二 标示符 标示符: 其实就是在程序中自定义的名词 比如类名, 变量名, ...

  7. 博客美化—添加萌萌的live2D看板娘(不能再简单了)

    看着很多博客都有live2D的萌萌哒看板娘,我闲着有空说干就干. 从参考博客的附件中下载资源文件 waifu.css waifu-tips.js live2d.js flat-ui.min.css// ...

  8. 网页性能管理详解:浅谈chrome-Timeline及window.requestAnimationFrame()方法

    你遇到过性能很差的网页吗? 这种网页响应非常缓慢,占用大量的CPU和内存,浏览起来常常有卡顿,页面的动画效果也不流畅. 你会有什么反应?我猜想,大多数用户会关闭这个页面,改为访问其他网站.作为一个开发 ...

  9. leetcode9_C++判断一个整数是否是回文数

    判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 输出: true 示例 2: 输入: - 输出: false 解释: 从左向右读, 为 - ...

  10. 【Machine Learning】如何处理机器学习中的非均衡数据集?

    在机器学习中,我们常常会遇到不均衡的数据集.比如癌症数据集中,癌症样本的数量可能远少于非癌症样本的数量:在银行的信用数据集中,按期还款的客户数量可能远大于违约客户的样本数量.   比如非常有名的德国信 ...