1 一个通用嵌入式驱动层的代码实现-德赢Vwin官网 网
0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一个通用嵌入式驱动层的代码实现

工程师进阶笔记 来源:工程师进阶笔记 作者:工程师进阶笔记 2022-11-16 11:31 次阅读

一、前言

STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。

使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。

二、实现原理

原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。

三、代码实现

国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread

头文件接口:

本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:

/*
驱动注册
*/
int cola_device_register(cola_device_t *dev);


/*
驱动查找
*/
cola_device_t*cola_device_find(constchar*name);


/*
驱动读
*/
int cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);


/*
驱动写
*/
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);


/*
驱动控制
*/
int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);;

头文件cola_device.h:

#ifndef_COLA_DEVICE_H_
#define _COLA_DEVICE_H_


enumLED_state
{
  LED_OFF,
  LED_ON,
  LED_TOGGLE,
};


typedefstructcola_devicecola_device_t;
structcola_device_ops
{
  int(*init)(cola_device_t*dev);
  int(*open)(cola_device_t*dev,intoflag);
  int(*close)(cola_device_t*dev);
  int(*read)(cola_device_t*dev,intpos,void*buffer,intsize);
  int(*write)(cola_device_t*dev,intpos,constvoid*buffer,intsize);
  int(*control)(cola_device_t*dev,intcmd,void*args);
};


structcola_device
{
  constchar*name;
  structcola_device_ops*dops;
  structcola_device*next;
};


/*
驱动注册
*/
int cola_device_register(cola_device_t *dev);


/*
驱动查找
*/
cola_device_t *cola_device_find(const char *name);


/*
驱动读
*/
int cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);


/*
驱动写
*/
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);


/*
驱动控制
*/
int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);


#endif

源文件cola_device.c:

#include"cola_device.h"
#include
#include 


struct cola_device *device_list = NULL;


/*
查找任务是否存在
*/
static bool cola_device_is_exists( cola_device_t *dev )
{
  cola_device_t*cur=device_list;
  while(cur!=NULL)
  {
    if(strcmp(cur->name,dev->name)==0)
{
returntrue;
}
cur=cur->next;
}
returnfalse;
}


static int device_list_inster(cola_device_t *dev)
{
  cola_device_t *cur = device_list;
  
  if(NULL==device_list)
  {
    device_list=dev;
    dev->next=NULL;
  }
  else
  {
    while(NULL!=cur->next)
    {
        cur=cur->next;
    }
    
    cur->next=dev;
    dev->next=NULL;
  }
  return1;
}


/*
驱动注册
*/
int cola_device_register(cola_device_t *dev)
{
  if((NULL==dev)||(cola_device_is_exists(dev)))
  {
    return0;
  }
  if((NULL==dev->name)||(NULL==dev->dops))
  {
    return0;
  }
  returndevice_list_inster(dev);
}


/*
驱动查找
*/
cola_device_t*cola_device_find(constchar*name)
{
  cola_device_t*cur=device_list;
  while(cur!=NULL)
  {
    if(strcmp(cur->name,name)==0)
    {
      returncur;
    }
    cur=cur->next;
  }
  returnNULL;
}


/*
驱动读
*/
int cola_device_read(cola_device_t *dev, int pos, void *buffer, int size)
{
  if(dev)
  {
    if(dev->dops->read)
    {
      returndev->dops->read(dev,pos,buffer,size);
    }
  }
  return0;
}


/*
驱动写
*/
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
{
  if(dev)
  {
    if(dev->dops->write)
    {
      returndev->dops->write(dev,pos,buffer,size);
    }
  }
  return0;
}


/*
驱动控制
*/
int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg)
{
  if(dev)
  {
    if(dev->dops->control)
    {
      returndev->dops->control(dev,cmd,arg);
    }
  }
  return0;
}

硬件注册方式:以LED为例,初始化接口voidled_register(void),需要在初始化中调用。

#include"stm32f0xx.h"
#include"led.h"
#include"cola_device.h"
#definePORT_GREEN_LEDGPIOC
#define PIN_GREENLED GPIO_Pin_13             


/*LED亮、灭、变化*/
#defineLED_GREEN_OFF(PORT_GREEN_LED->BSRR=PIN_GREENLED)
#defineLED_GREEN_ON(PORT_GREEN_LED->BRR=PIN_GREENLED)
#define LED_GREEN_TOGGLE (PORT_GREEN_LED->ODR ^= PIN_GREENLED)


static cola_device_t led_dev;


static void led_gpio_init(void)
{
  GPIO_InitTypeDefGPIO_InitStructure;
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC,ENABLE);
  GPIO_InitStructure.GPIO_Pin=PIN_GREENLED;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
  GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
  LED_GREEN_OFF;
}


static int led_ctrl(cola_device_t *dev, int cmd, void *args)
{
  if(LED_TOGGLE==cmd)
  {
    LED_GREEN_TOGGLE;
  }
  else{
  }
  return1;
}


staticstructcola_device_opsops=
{
  .control=led_ctrl,
};


void led_register(void)
{
  led_gpio_init();
  led_dev.dops=&ops;
  led_dev.name="led";
  cola_device_register(&led_dev);
}

应用层app代码:

#include
#include"app.h"
#include"config.h"
#include"cola_device.h"
#include "cola_os.h"


statictask_ttimer_500ms;
static cola_device_t *app_led_dev;


//led每500ms状态改变一次
static void timer_500ms_cb(uint32_t event)
{
  cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
}


void app_init(void)
{
  app_led_dev=cola_device_find("led");
  assert(app_led_dev);
  cola_timer_create(&timer_500ms,timer_500ms_cb);
  cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
}

这样 app.c 文件中就不需要调用 led.h 头文件了,rtt 就是这样实现的。

四、总结

这样就可以实现软硬件分层了,是不是非常好用!

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5082

    文章

    19104

    浏览量

    304777
  • 代码
    +关注

    关注

    30

    文章

    4779

    浏览量

    68518

原文标题:一个通用的嵌入式驱动层,基本都是这么玩的

文章出处:【微信号:工程师进阶笔记,微信公众号:工程师进阶笔记】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    新手怎么学嵌入式?

    实现些简单的功能,如点亮 LED 灯、读取传感器数据等,来加深对嵌入式技术的理解。你还可以参加
    发表于 12-12 10:51

    【「嵌入式系统设计与实现」阅读体验】+ 学习STM32的案例

    嵌入式系统设计与实现——第六届全国大学生嵌入式芯片与系统设计竞赛芯片应用赛道优秀作品剖析》书的基本情况。今天来学习
    发表于 12-06 22:22

    HAL库在嵌入式系统中的应用

    HAL库是种在嵌入式开发中用于屏蔽底层硬件细节、提供统接口的软件。它允许开发者在编写应用程序时无需关心具体的硬件实现,从而提高了
    的头像 发表于 12-02 11:32 454次阅读

    零基础嵌入式开发学习路线

    底层岗位方向比如:嵌入式硬件工程师、驱动开发工程师等岗位投简历啦!当然,这只是大致的路线,并不涵盖所有的细节和知识点。如果你想深入学习,还需要仔细研究
    发表于 10-25 15:55

    嵌入式学习建议

    动手做一个实际的小系统,底层硬件基础就有了。各个硬件模块驱动程序的编写是嵌入式系统的必备基础。学习嵌入式系统的初期,这个过程是必须的。 ④至于嵌入
    发表于 10-22 11:41

    什么是嵌入式文读懂嵌入式主板

    在现代科技浪潮中,嵌入式技术已成为支撑各种智能设备和系统运行的核心力量。那么,究竟什么是嵌入式嵌入式系统,顾名思义,是将计算机的硬件和软件嵌入到某种设备或系统中,以
    的头像 发表于 10-16 10:14 919次阅读

    嵌入式系统的原理和应用

    嵌入式系统是种专用的计算机系统,其设计初衷是执行特定任务,而非作为通用计算机使用。这类系统通常作为更大系统的部分,起到控制、监控或辅助的作用,具有资源受限、实时性高、可靠性强等特点
    的头像 发表于 10-05 17:03 815次阅读

    EsDA,一站式嵌入式软件

    EsDA是套面向工业智能物联领域的嵌入式系统设计自动化工具集,包含实时操作系统AWorksLP、低代码开发平台AWStudio、资源管理平台AXPI、跨平台GUI引擎AWTK和云服务平台ZWS
    的头像 发表于 09-15 08:10 278次阅读
    EsDA,<b class='flag-5'>一站式</b><b class='flag-5'>嵌入式</b>软件

    种常用嵌入式开发代码

    使用开源协议:GPL-2.0varch简介varch(we-architecture,意为我们的框架库)是嵌入式C语言常用代码模块库,包含了嵌入式中常用的算法库,数据结构(容器)库,解析器库,独立C
    的头像 发表于 09-04 08:06 454次阅读
    <b class='flag-5'>一</b>种常用<b class='flag-5'>嵌入式</b>开发<b class='flag-5'>代码</b>库

    七大嵌入式GUI盘点

    LCD设计提供高级支持,极大简化了LCD设计。它是使用比较广泛的款GUI,配合GUI Builder或App Wizard上位机软件,用起来也比较方便。emWin以C语言源代码提供,使其成为嵌入式
    发表于 09-02 10:58

    嵌入式linux开发的基本步骤有哪些?

    嵌入式Linux开发是复杂的过程,涉及到硬件选择、操作系统移植、驱动开发、应用程序开发等多个方面。以下是嵌入式Linux开发的基本步骤,
    的头像 发表于 09-02 09:11 477次阅读

    宇珑RK3576核心板与嵌入式主板通用平台介绍

    宇珑RK3576核心板与嵌入式主板通用平台介绍
    的头像 发表于 08-26 17:23 554次阅读
    宇珑RK3576核心板与<b class='flag-5'>嵌入式</b>主板<b class='flag-5'>通用</b>平台介绍

    RK3576核心板与嵌入式主板通用平台介绍

    RK3576核心板与嵌入式主板通用平台介绍
    的头像 发表于 08-26 11:37 750次阅读
    RK3576核心板与<b class='flag-5'>嵌入式</b>主板<b class='flag-5'>通用</b>平台介绍

    从事嵌入式方向,定要软硬件通吃?

    软件工程师的职责嵌入式软件工程师的主要职责是为嵌入式系统编写和调试代码,确保系统按预期工作。他们需要处理底层硬件接口、实时操作系统(RTOS)、驱动程序和应用
    的头像 发表于 06-05 08:10 1176次阅读
    从事<b class='flag-5'>嵌入式</b>方向,<b class='flag-5'>一</b>定要软硬件通吃?

    啥是嵌入式嵌入式都有啥?薪资如何?前景如何

    ,以实现稳定、可靠、高效的功能。嵌入式系统广泛应用于各个领域,包括消费电子、汽车、医疗设备、工业控制、物联网(IoT)设备、航空航天等。 嵌入式系统的特点包括: 专用性:嵌入式系统通常
    的头像 发表于 01-17 16:39 917次阅读
    啥是<b class='flag-5'>嵌入式</b>?<b class='flag-5'>嵌入式</b>都有啥?薪资如何?前景如何