嵌入式开发中应用层与硬件层的分层管理实现策略

2024-12-11 0 992

STM32开发时,例程中的文件层级设置常常让人感到困扰。有时候,应用层的文件竟然混杂着硬件层的文件,看上去十分杂乱。这就像整理房间,东西摆放不当,整个空间就显得乱糟糟的,影响了整体的美观。这确实让开发者感到挺烦恼的。

STM32例程现状

嵌入式开发中应用层与硬件层的分层管理实现策略

网络下载的资源或开发板自带的程序中,经常遇到应用层混用了本该属于硬件层的.h文件。这种现象很常见。就拿我之前开发的一个STM32小项目来说,看到那些层次混乱的文件,真是让人头疼。这不但让代码的结构显得杂乱无章,还使得后续的维护和扩展变得十分困难。尤其是对于初学者,这种混乱的分层结构会让他们在理解代码逻辑时遇到不小的挑战。

在实际的项目开发过程中,若出现层次混乱,可能会使开发周期变长。比如,对于急需上线的项目,开发者若需花费更多时间去理清代码之间的联系,这无疑是不利的。

Linux系统的启示

熟悉Linux的人都知道,Linux系统无法直接对硬件进行操作。观察其源代码,可以发现其中设有驱动程序这一层。以某个Linux服务器的开发为例,我们注意到其代码明确划分了各个层级。这种层级的划分使得整体结构一目了然。Linux对硬件层的隔离措施有效地保障了系统的稳定性。一旦出现故障,我们能够迅速判断是驱动层还是应用层出了问题。

这种分层设计思路就好比将不同部门各自设立办公区域,各自负责各自的工作。在STM32的开发过程中,我们可以采纳这种设计思路,将软件和硬件部分分开管理,这样做不仅能提高开发速度,而且后续的维护工作也会变得更为便捷。

实现原理剖析

在理论层面,将硬件操作接口置于驱动链表中,比如open、read、write等操作在驱动层完成。以智能家居控制系统为例,其中各类硬件设备的操作接口可以纳入驱动链表。然而,此方法存在不足,查找驱动时需遍历整个链表,导致代码执行时间延长。这就像在一家大型公司中寻找文件,若缺乏有效索引,便需逐个文件夹搜索,耗费大量时间。

此时,开发者需考量利弊得失。若代码对实时性的需求不高,软硬分层可通过此法顺利实现。然而,对于对实时性要求极高的项目,可能需对现有方法进行优化调整。

/*
    驱动注册
*/
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);;

代码实现要点

编写代码时,通常遵循国际规范,首先编写头文件。在此例中,我们使用了单向链表来简化操作,若感兴趣,不妨探究双向链表。确保头文件接口定义准确至关重要。例如,本次仅实现部分接口,其他部分可自行深入研究。以一个简单的传感器数据采集项目为例,在代码编写过程中,采用这种分层结构,应用层仅需调用相应接口即可实现功能。

#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 

编写头文件.h和源文件.c时,需依据功能需求做好规划。这好比建造房屋前先确定好结构框架,如此编写出的代码运行更流畅,也便于其他开发者阅读与维护。

硬件注册方式示例

以LED为例,存在一个初始化接口,名为void(void),这是在初始化过程中必须调用的。在处理实际硬件接入的项目中,例如LED显示屏的控制项目,这种硬件注册方法能保证在应用层无需调用led.h头文件,从而实现软件与硬件的分离。这就像在组装一台复杂机器时,每个部件都有其特定的安装步骤,遵循这些步骤可以确保设备能顺畅运作。

#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)
        {
            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;
}

这种硬件注册过程既简便又高效,它有助于使代码结构更加分明,同时降低了不必要的相关性。

代码下载与总结


#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,
};
void led_register(void)
{
    led_gpio_init();
    led_dev.dops = &ops;
    led_dev.name = "led";
    cola_device_register(&led_dev);
}

这里并未提供代码下载的具体链接,不过我们必须认识到软硬件分层的至关重要。这种分层能提高开发速度,并使代码更易维护与理解。我想问问大家,在使用STM32进行开发时,是否遇到过因软硬件分层不清而引发的大麻烦?欢迎点赞和转发这篇文章,并在评论区参与讨论。

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

七爪网 行业资讯 嵌入式开发中应用层与硬件层的分层管理实现策略 https://www.7claw.com/2801950.html

七爪网源码交易平台

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务