电子产业一站式赋能平台

PCB联盟网

搜索
查看: 184|回复: 0
收起左侧

简化嵌入式开发:硬件操作接口分层实现?

[复制链接]

520

主题

520

帖子

3479

积分

四级会员

Rank: 4

积分
3479
发表于 2024-8-8 11:38:00 | 显示全部楼层 |阅读模式
一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。

y2y5yrn2vi264013234004.png

y2y5yrn2vi264013234004.png

二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现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,
};
typedefstruct 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,constvoid*buffer,int size);
    int(*control)(cola_device_t*dev,int cmd,void*args);
};
struct cola_device
{
    constchar* name;
    struct cola_device_ops *dops;
    struct cola_device *next;
};
/*
    驱动注册
*/
intcola_device_register(cola_device_t *dev);
/*
    驱动查找
*/
cola_device_t*cola_device_find(const char *name);
/*
    驱动读
*/
intcola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
/*
    驱动写
*/
intcola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
/*
    驱动控制
*/
intcola_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;
/*
    查找任务是否存在
*/
staticboolcola_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;
}

staticintdevice_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;
}
/*
    驱动注册
*/
intcola_device_register(cola_device_t *dev)
{
    if((NULL== dev)||(cola_device_is_exists(dev)))
    {
        return 0;
    }
    if((NULL== dev->name)||(NULL== dev->dops))
    {
        return0;
    }
    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;
}
/*
    驱动读
*/
intcola_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;
}
/*
    驱动写
*/
intcola_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;
}
/*
    驱动控制
*/
intcola_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)

static cola_device_t led_dev;
static void led_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_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
    {
    }
    return 1;
}

static struct cola_device_ops ops =
{
.control = led_ctrl,
};
voidled_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"
static task_t timer_500ms;
static cola_device_t*app_led_dev;
//led每500ms状态改变一次
staticvoidtimer_500ms_cb(uint32_t event)
{
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
}
voidapp_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就是这样实现的。
四、总结这样就可以实现软硬件分层了,是不是非常好用!
五、代码下载链接https://gitee.com/schuck/cola_os
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722
猜你喜欢:
Github上热门 C 语言项目汇总!
嵌入式,可测试性软件设计!
一些低功耗软件设计的要点!
嵌入式 C 保护结构体的方式
实用 | 10分钟教你通过网页点灯
谈谈嵌入式软件的兼容性!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表