嵌入式中实现应用层和硬件层分层管理_嵌入式代码实现驱动和设备分层

39 阅读3分钟

已剪辑自: mp.weixin.qq.com/s/Ba7JcNJig…

一、前言

以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(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);

头文件cola_device.h:

#ifndef \_COLA\_DEVICE\_H\_
#define \_COLA\_DEVICE\_H\_
 
 
enum LED\_state
{
    LED_OFF,
    LED_ON,
    LED_TOGGLE,
 
};
 
typedef struct cola\_device  cola\_device\_t;
 
struct cola\_device\_ops
{
    int  (\*init)   (cola\_device\_t \*dev);
    int  (\*open)   (cola\_device\_t \*dev, int oflag);
    int  (\*close)  (cola\_device\_t \*dev);
    int  (\*read)   (cola\_device\_t \*dev, int pos, void \*buffer, int size);
    int  (\*write)  (cola\_device\_t \*dev, int pos, const void \*buffer, int size);
    int  (\*control)(cola\_device\_t \*dev, int cmd, void \*args);
 
};
 
struct cola\_device
{
    const char \* name;
    struct cola\_device\_ops \*dops;
    struct cola\_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 <string.h>
#include <stdbool.h>
 
 
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)
        {
            return true;
        }
        cur = cur->next;
    }
    return false;
}
 
 
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;
    }
    return 1;
}
 
/\*
 驱动注册
\*/
int cola\_device\_register(cola\_device\_t \*dev)
{
    if((NULL == dev) || (cola\_device\_is\_exists(dev)))
    {
        return 0;
    }
 
    if((NULL == dev->name) ||  (NULL == dev->dops))
    {
        return 0;
    }
    return device\_list\_inster(dev);
 
}
/\*
 驱动查找
\*/
cola\_device\_t \*cola\_device\_find(const char \*name)
{
    cola\_device\_t\* cur = device_list;
    while( cur != NULL )
    {
        if( strcmp(cur->name,name)==0)
        {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}
/\*
 驱动读
\*/
int cola\_device\_read(cola\_device\_t \*dev,  int pos, void \*buffer, int size)
{
    if(dev)
    {
        if(dev->dops->read)
        {
            return dev->dops->read(dev, pos, buffer, size);
        }
    }
    return 0;
}
/\*
 驱动写
\*/
int cola\_device\_write(cola\_device\_t \*dev, int pos, const void \*buffer, int size)
{
    if(dev)
    {
        if(dev->dops->write)
        {
            return dev->dops->write(dev, pos, buffer, size);
        }
    }
    return 0;
}
/\*
 驱动控制
\*/
int cola\_device\_ctrl(cola\_device\_t \*dev,  int cmd, void \*arg)
{
    if(dev)
    {
        if(dev->dops->control)
        {
            return dev->dops->control(dev, cmd, arg);
        }
    }
    return 0;
}

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

#include "stm32f0xx.h"
#include "led.h"
#include "cola\_device.h"
 
 
#define PORT\_GREEN\_LED GPIOC 
#define PIN\_GREENLED GPIO\_Pin\_13 
 
/\* LED亮、灭、变化 \*/
#define LED\_GREEN\_OFF (PORT\_GREEN\_LED->BSRR = PIN\_GREENLED)
#define LED\_GREEN\_ON (PORT\_GREEN\_LED->BRR = PIN\_GREENLED)
#define LED\_GREEN\_TOGGLE (PORT\_GREEN\_LED->ODR ^= PIN\_GREENLED)
 
 


**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/410ec027ee9e4529b1c9484dcaa1e962~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771259356&x-signature=ETDFwWnvMXe1ugsZc%2BJtsuux4ps%3D)
![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/52239abbf96042c1a5b254d4d5c723cc~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771259356&x-signature=zCqmy7wRs1bmHXaeshZkby7VF5E%3D)

**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**