接上一篇文章,这篇主要是nuttx驱动编写实践部分。基础部分请移驾《Nuttx驱动(一)简介》

Nuttx驱动例程

在该例程中,假设有这么一个设备:有3个IO输出和一个IO输入的RGB_LED设备,叫slimLED好了。(这里简单点就先不使用PWM控制了

  1. 创建字符设备驱动主体,即文件操作file_operations,然后实现open()close()read()write()ioctl()
  2. 注册该设备驱动到系统中,将会在系统的/dev目录下生成一个名为slimLED的设备节点;
  3. 通过应用程序来获取输入脚状态、控制三个输出脚状态。

1. 驱动框架部分

说明:在nuttx仓库中,实现slimLED这个驱动接口,系统层驱动与具体board无关。后期可以适配不同芯片或不同的board,所以尽可能灵活

要修改如下文件(nuttx仓库)

  • Kconfig
  • Make.defs
  • slimLED.c
  • slimLED.h

Kconfig 配置

用于图形化配置工具的

config SLIM_RGB_LEDbool "slim RGB led device support"default n---help---Enable driver support for the slim LED controler.


Make.defs

# slim RGB LEDifeq ($(CONFIG_SLIM_RGB_LED), y)CSRCS += slimLED.c
endif

slimLED.h

#ifndef __DRIVERS_SLIM_LED_H__
#define __DRIVERS_SLIM_LED_H__/***************************************************************************** Included Files****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>/***************************************************************************** Pre-processor Definitions****************************************************************************/
#define SLEDIOC_SET         0x0001
#define SLEDIOC_GET         0x0002struct slimled_status_s{bool state;
};struct slimled_param_s{short num;struct slimled_status_s on;
};struct slimled_lower_s{CODE int (*setio)(FAR struct slimled_lower_s *low, FAR struct slimled_param_s param);CODE int (*getio)(FAR struct slimled_lower_s *low, FAR struct slimled_status_s *status);CODE int (*ioctl)(FAR struct slimled_lower_s *low, int cmd, unsigned long arg);
};int slimled_register(FAR const char *path,  FAR void *lower);#endif

slimLED.c

#include <nuttx/config.h>
#include <stdlib.h>
#include <fixedmath.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/sensors/slimled.h>#if defined(CONFIG_SLIM_RGB_LED)
/***************************************************************************** Private Function Prototypes****************************************************************************/
static int  slimled_open(FAR struct file *filep);
static int  slimled_close(FAR struct file *filep);
static int  slimled_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static int  slimled_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
static int  slimled_write(FAR struct file *filep, FAR const char *buffer,size_t buflen);/***************************************************************************** Private Data****************************************************************************/
static const struct file_operations slimled_fops = {.open   = slimled_open,.close  = slimled_close,.read   = slimled_read,.write  = slimled_write,.ioctl  = slimled_ioctl,
};
/***************************************************************************** Private Functions****************************************************************************//***************************************************************************** Name: slimled_ioctl****************************************************************************/
static int  slimled_open(FAR struct file *filep){return OK;
}
static int  slimled_close(FAR struct file *filep){return OK;
}
static int slimled_read(FAR struct file *filep, FAR char *buffer, size_t buflen){return OK;
}
static int slimled_write(FAR struct file *filep, FAR const char *buffer,size_t buflen){return OK;
}
static int slimled_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{FAR struct inode *inode    = filep->f_inode;FAR struct slimled_lower_s *lower = inode->i_private;int ret = OK;switch (cmd){case SLEDIOC_SET:{FAR struct slimled_param_s param = {0};param.num = arg & 0xFF;param.on.state = (arg >> 8) & 0x03;ret = lower->setio(lower, param);break;}case SLEDIOC_GET:{FAR struct slimled_status_s *ptr = (FAR struct slimled_status_s*)((uintptr_t)arg);DEBUGASSERT(ptr != NULL);ret = lower->getio(lower, ptr);break;}default:ret = lower->ioctl(lower, cmd, arg);break;}return ret;
}/***************************************************************************** Public Functions****************************************************************************//***************************************************************************** Name: slimled_register****************************************************************************/int slimled_register(FAR const char *path, FAR struct slimled_lower_s *dev,FAR void *lower)
{int ret;DEBUGASSERT(path != NULL);DEBUGASSERT(lower != NULL);/* Register the slimled character driver */ret = register_driver(path, &slimled_fops, 0666, lower);if (ret < 0){_err("ERROR: Failed to register slim led driver: %d\n", ret);}return ret;
}

2. board适配层

说明:在芯片级或 board 级仓库中,实现 slimLED 这个设备驱动,与具体的 芯片平台 或 board平台 进行绑定。构建设备驱动程序与硬件直接的桥梁

要修改如下文件(board仓库)

  • Make.defs
  • configs/nsh/defconfig
  • board_def.h
  • bringup.c
  • platform_data.c
  • board_slimLED.h
  • board_slimLED.c

Make.defs

ifeq ($(CONFIG_SLIM_RGB_LED),y)
CSRCS += board_slimled.c
endif

defconfig

CONFIG_SLIM_RGB_LED=y

board_def.h

定义对应的IO口,以Apollo芯片为例

#define SLIM_LED_R        (GPIO_PIN1 | GPIO_FUN_GPIO | GPIO_DRIVESTRENGTH_0P5X | GPIO_OUTCFG_PUSHPULL)
#define SLIM_LED_G        (GPIO_PIN2 | GPIO_FUN_GPIO | GPIO_DRIVESTRENGTH_0P5X | GPIO_OUTCFG_PUSHPULL)
#define SLIM_LED_B        (GPIO_PIN3 | GPIO_FUN_GPIO | GPIO_DRIVESTRENGTH_0P5X | GPIO_OUTCFG_PUSHPULL)
#define SLIM_STA          (GPIO_PIN4 | GPIO_FUN_GPIO | GPIO_OUTCFG_DISABLE | GPIO_INPUT_ENABLE | GPIO_INTDIR_HI2LO)

bringup.c

初始化slim led设备,设备名和设备操作函数绑定及其初始化

int board_bringup(void){...
#ifdef CONFIG_SLIM_RGB_LEDret = board_slimled_initialize("/dev/slimled", &slimled_pdata, eLED_CNT);if(ret < 0){printf("ERROR: slim led driver initialize failed: %d\n", ret);}
#endif...
}

platform_data.c

const struct slimled_platform_data slimled_pdata[] = {{.pin   = SLIM_LED_R,.state = false,},{.pin   = SLIM_LED_G,.state = false,},{.pin   = SLIM_LED_B,.state = false,},
};

board_slimLED.h

#ifndef __BOARD_SLIMLED_H__
#define __BOARD_SLIMLED_H__#include <nuttx/config.h>
#include <nuttx/regulator/fixed-regulator.h>typedef enum{eLED_R,eLED_G,eLED_B,eLED_CNT,
}slimled_Num;struct slimled_platform_data{uint32_t pin;bool     state;
};extern const struct slimled_platform_data slimled_pdata[];
int board_slimled_initialize(const char *devpath, const struct slimled_platform_data *pdata, uint32_t cnt);#endif

board_slimLED.c

#include <nuttx/nuttx.h>
#include <nuttx/irq.h>
#include <nuttx/signal.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>#include <nuttx/err.h>
#include "board_def.h"
#include "board_slimLED.h"
#include <slimLED.h>#ifdef CONFIG_SLIM_RGB_LEDstatic bool _get_slimled_state(void);
static void _set_slimled_param(FAR const struct slimled_lower_s *lower, FAR struct slimled_param_s param);static const struct slimled_lower_s slimled_lower = {.getio = _get_slimled_state,.setio = _set_slimled_param,.ioctl = _set_slimled_param,
};/***************************************************************************** Private Functions****************************************************************************/
static bool _get_slimled_state(void){return gpioread(SLIM_STA);
}static void _set_slimled_param(const struct slimled_lower_s *lower, struct slimled_param_s param){printf("%s %d %d\r\n", __func__, param.num, param.on.state);if(param.num < eLED_CNT){gpiowrite(slimled_pdata[param.num].pin, param.on.state);}
}int board_slimled_initialize(const char *devpath, const struct slimled_platform_data *pdata, uint32_t cnt){if(cnt > eLED_CNT){printf("ERROR: slim led cnt setting error...\n");cnt = eLED_CNT;}for(uint8_t i=0;i<cnt;i++){configgpio(pdata[i].pin);}configgpio(SLIM_STA);return slimled_register(devpath, &slimled_lower);
}#endif

3. 应用层

这里直接创建 slim led 应用线程

#include <stdio.h>
#include <stdbool.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>
#include <nuttx/config.h>
#include <nuttx/analog/ioctl.h>
#include <slimLED.h>
#include <syslog.h>typedef enum{eCHANNEL_LED_R,eCHANNEL_LED_G,eCHANNEL_LED_B,eCHANNEL_LED_CNT,
}slimled_channelTypeDef;
static int led_fd = -1;static bool _slimled_init(void){led_fd = open("/dev/slimled", O_WRONLY);if(led_fd < 0){printf("slimled open failed\n");return false;}return true;
}static bool _set_slimled_channal(slimled_channelTypeDef channel){struct slimled_param_s tmp[eCHANNEL_LED_CNT] = {0};if(channel > eCHANNEL_LED_CNT){printf("param setting error...\n");return false;}if(led_fd < 0){printf("slimled not opened yet\n");return _slimled_init();}for(uint8_t i=0;i<eCHANNEL_LED_CNT;i++){tmp[i].num = i;if(i == channel){tmp[i].on.state = true;}else{tmp[i].on.state = false;}ioctl(led_fd, SLEDIOC_SET, tmp[i]);}
}void *slimled_Thread(void *arg){struct slimled_param_s slimled[3] = {0};int ret = 0;int sta = 0;if(false == _slimled_init()){return;}for(;;){for(uint8_t i=0;i<eCHANNEL_LED_CNT;i++){_set_slimled_channal(i);sleep(5);}ioctl(led_fd, TLEDIOC_GET, &sta);printf("= = == ioctl state: %d get IO state:%d= == =\n\n\n", ret, sta);}close(led_fd);return;
}
— 完 —

Nuttx驱动(二)实例相关推荐

  1. Linux USB 驱动开发实例(七)—— 基于USB 总线的无线网卡浅析

    回顾一下USB的相关知识 USB(Universal Serial Bus)总线又叫通用串行外部总线, 它是20世纪90年代发展起来的.USB接口现在得到了广泛的应用和普及,现在的PC机中都带有大量的 ...

  2. S3C2440上LCD驱动 (FrameBuffer)实例开发讲解

    1.S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 其中的代码也可直接参考:drivers/video/s3c2410fb.c 以下为转载文章,文章原地址:http://blog. ...

  3. Nuttx驱动(一)简介

    第一次写Nuttx系统的驱动,用惯了rt-thread.FreeRTOS等RTOS或裸机的驱动编写.写Nuttx驱动感觉好蹩脚,顺便记录一下(by the way: 先完成,再完善) Nuttx驱动分 ...

  4. 从零开始学Linux内核驱动--(二)简单内核模块驱动程序

    Linux驱动–(二)简单的内核模块驱动程序 一.概述 Linux中所有的驱动都是以内核模块的形式来实现的,他们与其他所有的内核编译在一起形成一个单独的内核镜像文件(所以说Linux是一个宏内核).当 ...

  5. RK3399外设驱动之RTC驱动(二):hym8563驱动

    RK3399外设驱动之RTC驱动(二):hym8563驱动 文章目录 RK3399外设驱动之RTC驱动(二):hym8563驱动 hym8563硬件相关 注册驱动 probe函数 hym8563_in ...

  6. Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试

    参考2.6.14版本中的driver/usb/input/usbmouse.c.鼠标驱动可分为几个部分:驱动加载部分.probe部分.open部分.urb回调函数处理部分. 一.驱动加载部分 [cpp ...

  7. S3C2440上LCD驱动(FrameBuffer)实例开发讲解

    一.开发环境 主  机:VMWare--Fedora 9  开发板:Mini2440--64MB Nand, Kernel:2.6.30.4  编译器:arm-linux-gcc-4.3.2 二.背景 ...

  8. 我的内核学习笔记12:linux i2c-gpio驱动应用实例

    linux内核的i2c-gpio是使用GPIO模拟I2C协议的驱动,只需要配置2根GPIO即可使用.Linux的I2C子系统比较复杂,笔者暂时还没有研究.本着"实用"的目的,介绍一 ...

  9. 我的内核学习笔记11:linux leds-gpio驱动应用实例

    linux内核的leds-gpio是使用GPIO控制LED的驱动,只要将板子上LED灯对接的GPIO引脚号进行适当的配置,就能使用这个驱动了,十分方便.网上有很多文章分析这个驱动,就不献丑--或者后面 ...

最新文章

  1. Facebook表示将不会默认开启人脸识别功能,被罚怕了?
  2. opencv setTo()
  3. 【安全牛学习笔记】kali TOP10 安全工具:
  4. [USACO10DEC] Treasure Chest
  5. rust实现wss访问_Rust的所有权,第2部分
  6. react学习笔记2之正确使用状态
  7. extjs2.0 ie8 下拉树_extjs2下拉树选项框comboxWithTree(支持异步加载子节点)
  8. 进程/线程间通信和同步
  9. C语言程序设计 余贞侠(课后习题答案)
  10. 如何将U盘刻录为系统启动盘?
  11. python实现简单银行管理系统
  12. 分层总和法matlab,高填方路基沉降检测之回归法
  13. matlab(1):画图像修改曲线形状
  14. matlab修改图像分辨率_matlab imresize 改变图像大小
  15. 【历史上的今天】11 月 2 日:蠕虫起源;NP 问题的提出者诞生;领英注册域名
  16. 2016计算机知识竞赛题库,国学知识竞赛题库2016(含答案)
  17. java获取手机号归属地-爬虫
  18. React+Typescript实现一个甘特图表格
  19. selenium网页自动登录、打卡(二)
  20. 铁路客运乘务服务中扫码支付技术的应用

热门文章

  1. 【unity基础_Day15】 灯光系统、粒子系统、车轮碰撞器、TimeLine时间轴
  2. 海贼王游戏--EM游戏06--巧夺天工
  3. 荒野无灯路由器固件配置DDNS的过程
  4. Android 弹窗设计规范
  5. Linux - 第16节 - 网络基础(应用层二)
  6. css的ID选择器和class选择器的区别
  7. uniApp开发安卓App调试与打包
  8. centos 8 安装 mysql 8
  9. 闲人闲谈PS之四十二——顾问的“禁忌之地”—制造能力计划
  10. Matlab多核CPU并行和多线程