Nuttx驱动(二)实例

2023-05-16

接上一篇文章,这篇主要是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_LED
	bool "slim RGB led device support"
	default n
	---help---
		Enable driver support for the slim LED controler.

在这里插入图片描述
在这里插入图片描述

Make.defs

# slim RGB LED

ifeq ($(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         0x0002

struct 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_LED
  ret = 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_LED

static 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;
}
— 完 —
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Nuttx驱动(二)实例 的相关文章

  • nuttx和linux区别,Nuttx文件系统

    1 介绍 文件系统 xff0c 是对一个存储设备上的数据和元数据进行组织的机制 xff0c 它是操作系统管理持久性数据的子系统 xff0c 提供数据存储和访问功能 将一个文件系统与一个存储设备关联起来的过程叫做挂载 mount xff0c
  • nuttx-概述

    早期基于MSP430系列 STM32系列 EFM32系列 AT91SAM9X imx6ul系列做各种物联网产品 xff0c 近几年国芯片慢慢崛起 xff0c 加上ST芯片价格暴涨 xff0c 更是让国产芯片赢得了难得的发展机会 xff0c
  • Nuttx的源码构建和编译

    下载源码 sudo mkdir Nuttx cd Nuttx Nuttx xff1a git clone https bitbucket org nuttx nuttx gitapps xff1a git clone https bitbu
  • 为何选择nuttx

    裸机程序 xff0c 不能处理太复杂的逻辑 xff0c 系统越复杂 xff0c 越需要上os freertos 不支持posix api rtems是gpl版权 nuttx bsd版权 xff0c px4和apm开源飞控都使用nuttx 经
  • Atmel Cortex-A5跑Nuttx是如此酸爽

    开源RTOS Nuttx已经支持Atmel SAMA5系列MPU xff0c 而且看到Nuttx还支持Graphic API xff0c 决定尝试在Ateml SAMA5D3 Xplained上跑下Nuttx Nuttx是一款开源RTOS
  • Using NuttX OS as a library on Atmel Studio 7

    This document explains how to add NuttX OS to your application on Atmel Studio 7 using NuttX OS as a library With Atmel
  • PX4项目学习::(三)Nuttx操作系统

    50条消息 PX4代码解析 4 超级菜狗的博客 CSDN博客 px4代码解析
  • px4之nuttx操作系统编译

    nuttx 嵌入式操作系统 1 下载源码 https nuttx apache org download 分别下载app和os 下载完毕后 xff0c 解压两个压缩包 2 根据当前嵌入式的开发板子 xff0c 进行配置 span class
  • 记录ubuntu18.04下搭建nuttx RTOS的过程

    官方参考链接 xff1a https nuttx apache org docs latest quickstart install html Getting started 61 61 gt Installing 主要记录一下按照链接指导
  • 乐鑫多系列芯片支持 NuttX 和 Zephyr 操作系统

    乐鑫芯片凭借丰富的功能和广阔的应用 xff0c 在物联网市场广受欢迎 乐鑫还为用户提供了一个物联网开发框架 ESP IDF xff0c 集成大量软件组件 xff0c 包括 RTOS 外设驱动程序 网络栈和多种协议实现技术等 开发者能够在乐鑫
  • genromfs的使用及nuttx下romfs制作

    61 61 61 61 61 gt 我的博客目录导航 前言 这篇文章仅仅是为了记录如何使用genromfs制作romfs然后在nuttx上直接应用 xff0c 不会去详细介绍romfs的一系列特性 genromfs 首先去下载genromf
  • Nuttx下移植uorb笔记

    Nuttx下移植uorb笔记 之前接触过ros下的消息机制 xff08 生产者 消费者 xff09 模型 xff0c 第一感觉是灵活好用 xff0c 但是在资源有限的嵌入式环境里面 xff0c 邮箱 消息 显得就有点不那么灵活 xff0c
  • NuttX RTOS

    目录 综述 NuttX是什么 看看这些文件和功能 它怎么会是一个小小的操作系统呢 xff1f NuttX讨论组 你想谈谈NuttX的特性吗 xff1f 你需要帮助吗 xff1f 问题吗 错误吗 下载 我在哪里可以买到NuttX xff1f
  • nuttx操作系统的移植以及下载

    1 在ubuntu根目录下 xff1a root 64 ubuntu apt get update 更新包 2 root 64 ubuntu apt get install gcc arm none eabi 编译器 3 kconfig f
  • NuttX 文件系统架构介绍(7.14)

  • Nuttx romfs与启动脚本rcS

    ARM系统上电后 xff0c 系统将flash地址映射到零地址处 xff0c 处理器从零地址处开始运行第一条指令 而在零地址处 xff0c 一般是系统复位中断向量 xff0c 此处存放的是一条跳转指指令 xff0c 通过该条换指令 xff0
  • nuttx操作系统的移植以及下载

    origin http blog csdn net seawolfe article details 70244672 1 在ubuntu根目录下 xff1a root 64 ubuntu apt get update 更新包 2 root
  • 5.0 NuttX File System

    转载请注明出处 xff1a 5 0 NuttX File System Alvin Peng的博客 CSDN博客 文章均出自个人理解 前言 前一段时间折腾了几个驱动 xff08 PWM Serial I2C xff09 xff0c 这次来折
  • esp32c3 nuttx 移植 micropython 尝试

    源码来自 https github com apache incubator nuttx apps pull 840 和 https github com apache incubator nuttx apps tree 787ac9060
  • 小米在建IoT护城河Vela NuttX

    MIDC 2020小米开发者大会刚刚过去 整场大会下来 几个印象比较深刻的点是 雷军宣布扩招5000名工程师 最新伸缩式大光圈镜头技术 小爱同学5 0发布 当然了 还有一个更加值得被提及的重点是 首次亮相的Xiaomi Vela物联网软件平

随机推荐

  • 如何计算旋转框的IOU

    一 先将两个框转换为角点形式 一般我们得到的是中心点 xff0c 宽高 xff0c 和旋转角度 通过矢量旋转公式得到角点形式 二 判断四个角点是否在对方的框里 xff0c 并保存在里面的角点 A的角点向B的相邻的两条边投影 任意的B的两条边
  • centerpoint论文和代码解读

    目录 一 序论 二 论文结构 三 代码 论文地址 xff1a https arxiv org pdf 2006 11275 pdf 代码地址 xff1a tianweiy CenterPoint github com 一 序论 centor
  • 关于严蔚敏教授的数据结构一书中return ok ,OK为1不为0的问题

    在主函数即Main 函数中的return 需要返回0 xff0c 表示成功完成本函数 但是在严教授的书中所写的多数函数 xff0c 是status函数类型 xff0c 也就是说并不是主函数 xff0c 是子函数 xff0c 原则上子函数的r
  • MTN模型LOSS均衡相关论文解读

    目录 一 综述 二 依据任务不确定性加权多任务损失 三 依据不同任务的梯度大小来动态修正其loss权重GradNorm 四 根据LOSS变化动态均衡任务权重Dynamic Weight Average xff08 DWA xff09 五 R
  • 安装ceres库的避坑指南(附官方文档)

    目录 写在前面 1 Failed to connect to ceres solver google com port 443 解决办法 xff1a 更换源 2 OpenSSL SSL read Connection was reset e
  • 一文搞清apt与apt-get的异同

    本文翻译自Difference Between apt and apt get Explained It 39 s FOSS 译者注 xff1a 本人尽量以通俗易懂的方式展现原文的内容 xff0c 限于经验和水平 xff0c 错误之处欢迎指
  • SLAM≠机器人自主定位导航

    SLAM技术作为机器人自主移动的关键技术 xff0c 让很多人都误解为 xff1a SLAM 61 机器人自主定位导航 其实 xff0c SLAM 机器人自主定位导航 xff0c 不解决行动问题 SLAM如其名一样 xff0c 主要解决的是
  • slam是什么意思?一文带你读懂SLAM

    SLAM是Simultaneous localization and mapping缩写 xff0c 意为 同步定位与建图 xff0c 主要用于解决机器人在未知环境运动时的定位与地图构建问题 xff0c 为了让大家更多的了解SLAM xff
  • 自带SLAM和定位,不需要里程计的全新建图传感器—— SLAMTEC Mapper来了

    这些年 xff0c 我们引领并见证了激光传感器行业的快速发展 xff0c 是时候 xff0c 我们来搞点新的名堂了 xff01 下面 xff0c 有请今天的主角SLAMTEC Mapper 正式登场 xff01 Slamtec Mapper
  • ROS机器人编程学习(六)——ROS工具

    第6章 ROS工具 本章介绍了ROS的实用工具 RViz 和 rqt RViz是ROS的三维可视化工具 xff0c 便于三维视图的构建和显示 rqt是GUI开发工具 xff0c 便于图像查看 xff0c 重点介绍了rqt plot rqt
  • ZED2双目相机+IMU标定

    本文主要使用了kalibr工具标定ZED2双目相机 43 IMU xff0c 并运行VINS Fusion 阐述了标定板的选择方法 xff0c 以及标定中的注意事项 ZED2双目相机 43 IMU联合标定 1 安装标定工具2 选择标定板3
  • ZED2相机运行VINS-Fusion和ORB-SLAM3

    ZED2相机运行VINS Fusion和ORB SLAM3 1 关于zed2标定2 运行VINS Fusion3 运行ORB SLAM3 1 关于zed2标定 我最开始被zed2的标定问题折磨了好久 xff0c 用kalibr工具标定出来的
  • 用自己的设备跑各种VI-SLAM算法(1)——VINS/PL-VINS/ROVIO/MSCKF

    用自己的设备跑各种VI SLAM算法 xff08 1 xff09 1 VINS Fusion2 PL VINS3 ROVIO4 MSCKF 本人用的设备是一个海康单目相机和一个MTI惯导 xff0c 已经预先用kalibr工具标定了内外参
  • 【语言-汇编】自然常数(e)的计算

    原理介绍 它就是当 时函数 值的极限 即 xff1a 同时它也等于 计算结果 编译平台 xff1a Microsoft Visual Studio 2010 项目 xff1a Win32项目 空项目 CPU xff1a Intel R Co
  • 从零学习VINS-Mono/Fusion源代码(三):IMU预积分公式推导

    本节学习IMU预积分 xff0c 推导离散时间下的IMU预积分公式 xff0c 并解读相应代码 VINS Mono Fusion代码学习系列 xff1a 从零学习VINS Mono Fusion源代码 xff08 一 xff09 xff1a
  • 从零学习VINS-Mono/Fusion源代码(六):后端优化

    本节解析VINS后端优化 xff0c 包括优化变量 残差约束的构建 xff0c ceres求解器等 VINS Mono Fusion代码学习系列 xff1a 从零学习VINS Mono Fusion源代码 xff08 一 xff09 xff
  • TX2配置RealSense D455相机SDK和ros驱动

    TX2配置RealSense D455相机SDK和ros驱动 1 SDK安装2 RealSense ros安装3 bug及解决3 1 realsense viewer显示usb2 13 2 Could not found ddynamic
  • C++中:和::的含义与区别

    前言 xff1a 相信大多数读者和我一样在C 43 43 中总是分不清 xff1a 和 xff1a xff1a 的区别 xff0c 现在 xff0c 咱们就彻底解决它 一 1 类作用域操作符 指明了成员函数所属的类 如 xff1a M f
  • Nuttx驱动(一)简介

    第一次写Nuttx系统的驱动 xff0c 用惯了rt thread FreeRTOS等RTOS或裸机的驱动编写 写Nuttx驱动感觉好蹩脚 xff0c 顺便记录一下 xff08 by the way 先完成 xff0c 再完善 xff09
  • Nuttx驱动(二)实例

    接上一篇文章 xff0c 这篇主要是nuttx驱动编写实践部分 基础部分请移驾 Nuttx驱动 xff08 一 xff09 简介 Nuttx驱动例程 在该例程中 xff0c 假设有这么一个设备 xff1a 有3个IO输出和一个IO输入的RG