在嵌入式中如何实现应用层和硬件层分层管理呢

发布者:雅致人生最新更新时间:2024-01-03 来源: elecfans关键字:嵌入式  应用层 手机看文章 扫描二维码
随时随地手机看文章

一、前言

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


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

64544a82-0a99-11ee-962d-dac502259ad0.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,

 

};

 

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 

#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;

}

 


硬件注册方式:以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,

};

 

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"

 

static task_t timer_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就是这样实现的。


四、总结


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


关键字:嵌入式  应用层 引用地址:在嵌入式中如何实现应用层和硬件层分层管理呢

上一篇:STM32G474 中 Triggered-half 模式的实现
下一篇:一个通用嵌入式驱动层的代码实现

推荐阅读最新更新时间:2024-10-28 15:28

Linux系统在嵌入式DVR中的应用
以强稳定性的优势,嵌入式DVR越来越被安防行业与广大客户所接受。嵌入式DVR的稳定性优势不光来自于硬件的低故障率,很大因素取决于嵌入式DVR中所采用的操作系统及应用软件的高稳定性,它所选用的软件平台起着至关重要的作用。   从国内嵌入式DVR的领军人物海康威视公司在嵌入式DVR的开发历程上,可清晰地看出Linux系统在嵌入式DVR中的地位日益凸显出来。海康威视公司第一代嵌入式DVR的研发初期,在确定以Samsung S3C2510加Ti的DM642作为其硬件平台的时候,采用了Linux与VxWorks同时开发,相互参照、评估,最终主要由于基于对WindRiver 的VxWorks商用软件的信赖,选用了VxWorks作为其操作系统
[单片机]
嵌入式新利器 性能功耗完美体
由于嵌入式系统设计日益复杂且对运算效能的要求大幅提高,为全方位满足客户对执行效率、面积、功耗的高要求,新思科技公司日前发布其全新DesignWare ARC HS处理器,具有高度的可配置性、延展性,能提供丰富的设计弹性,同时能够提供超过4200DMIPS的性能,而功耗小于85毫瓦,堪称高阶嵌入式系统开发的设计新利器。   据悉, 新思科技 此次推出的32位ARC HS34和HS36处理器是基于扩展ARCv2架构的高速、低功耗处理器系列的首批成员、是迄今为止性能最高的ARC处理器内核,在采用典型的28纳米(nm)硅工艺时,可提供高达2.2GHz 的速度和1.9 DMIPS/MHz的性能。即使是延用上一代制造工艺,不管是在主打高效能
[模拟电子]
<font color='red'>嵌入式</font>新利器 性能功耗完美体
面向嵌入式视觉和边缘的高速连接,SGET发行SMARC2.1规范
嵌入式计算技术的领导厂商德国康佳特宣布,SGET已经批准了新的SMARC 2.1规范。在市场总监Christian Eder担任编辑的情况下,康佳特在规范的制定过程中发挥了重要作用。新的修订版带来了许多额外的功能,如SerDes支持扩展边缘连接,以及多达4个MIPI-CSI摄像头接口,以满足日益增长的嵌入式计算和嵌入式视觉融合的需求。这些新功能向后兼容Rev.2.0版本,这意味着2.1模块可以安装到2.0载板上。所有对Rev.2.0的扩展也都是可选的,因此所有的康佳特 SMARC 2.0模块都可以自动兼容SMARC 2.1。 担任康佳特市场总监及SGET编辑(SMARC 2.1规范)的Christian Eder解释道
[网络通信]
面向<font color='red'>嵌入式</font>视觉和边缘的高速连接,SGET发行SMARC2.1规范
ST多功能软件工具套件支持厂商为STR7 和STR9微控制器开发完整的USB固件
为所有的USB固件层和传输方式轻松开发固件,提供设备固件升级和虚拟COM演示 ? 中国,2007年1月22日 — 世界领先的微控制器开发厂商意法半导体(纽约证券交易所代码:STM)今天推出一套与STR7和STR9系列微控制器配套使用的USB软件开发工具,这套工具大幅度简化了嵌入式软件的实现难度,能够处理相对比较复杂的USB接口标准。今天,USB在嵌入式系统中应用非常广泛,这是因为USB使用起来既灵活又简便,同时在市场可以买到集成USB模块的高性能微控制器。 新的USB开发工具套件支持内建USB接口的STR71x和STR91x系列产品,以及最近新推出的STR75x系列,用户可以从ST网站免费下载这套开发
[新品]
基于S3C2440的嵌入式IPv6防火墙设计
  1 引言   在众多的网络安全设施中,防火墙是行之有效的重要网络安全设备,通过对网络通信进行筛选屏蔽以防未经授权的访问进出计算机网络。防火墙是位于可信网络和不可信网络之间的一道安全屏障,其最核心的任务就是管理和控制进出网络的通信量,它可以截获中途传输的数据包并进行处理,然后与事先定义好的安全策略规则相比较,并最终决定转发或丢弃该数据包。传统的防火墙通常位于一段网络的边界,它可以很好的过滤外界用户对内部网络的访问,但对内部网络的攻击却无能为力。针对此问题近年来关于新型防火墙的研究有很多,如分布式防火墙系统,嵌入式防火墙系统等。这些系统的目的是将防火墙的边界延伸,使其能够遍布网络的每一个终端设备,构建全方位的安全防护网络。  
[单片机]
基于S3C2440的<font color='red'>嵌入式</font>IPv6防火墙设计
嵌入式WiFi技术研究与通信设计
嵌入式WiFi技术是当前无线网络应用的一个热点。本文介绍IEEE802.11b的基本技术,给出一种在 嵌入式环境中的WiFi通信设计方案;通过一个移动监护系统的具体实现,说明方案的有效性。 关键词 IEEE802.11b嵌入式WiFi TCP/IP 移动监护 目前,IEEE802.11无线局域网标准在语音通信、无线办公等领域广泛应用,但主要还是局限在PC机、笔记本电脑等通用平台的无线通信。无线局域网在信息家电、工业控制、移动手持设备等嵌入式环境中的应用需求日益增多。如何在嵌入式系统中整合WLAN宽带通信,成为嵌入式系统应用中的一个热点。 1 IEEE802.11b无线局域网 IEEE802.11系列包括IEEE8
[工业控制]
基于嵌入式系统的汽车行驶记录仪的设计
  引言   汽车行驶记录仪是能够记录和再现汽车行驶状态的一种数字式电子记录装置,它可以全程记录汽车的行驶数据,并通过对所记录的行驶信息数据的分析,对车辆的行驶状况予以精确的掌控。汽车行驶记录仪可有效预防驾驶员的违章驾驶,降低车辆的交通事故。早在20世纪70年代,欧共体就开始全面强制使用机电模拟式汽车行驶记录仪并使得交通事故率降低了30%-50%。90年代以来,美国、日本、马来西亚、新加坡等国家也纷纷制定汽车行驶记录仪的法规。   我国从20世纪80年代开始进行汽车行驶记录仪的研制。2003年4月15日,由公安部有关部门起草、国家标准化管理委员会、国家经贸委审定通过,国家质量监督检查检疫总局发布了汽车行驶记录仪的国家标准(GB
[单片机]
基于<font color='red'>嵌入式</font>系统的汽车行驶记录仪的设计
S3C6410嵌入式应用平台构建(六)——linux-3.14.4移植到OK6410-(Yaffs2文件系统移植)
我个人觉得nandflash上用yaffs2文件系统是很好的方案,但是最新的Linux并不支持yaffs2文件系统,需要你自己给内核打补丁,不过话说在前面,由于内核间差异及兼容问题,在编译时肯定会出现各种编译问题,需要你一一的去解决。 一、准备工作 1. 下载源码 使用git工具下载:$ git clone git://www.aleph1.co.uk/yaffs2 2. 给内核打补丁 下载完成后,在该执行目录下会有yaffs2文件夹,进入该文件夹。 $ ./patch-ker.sh c m ../../kernel/test/linux-3.14.4 Updating ../../kernel/te
[单片机]
S3C6410<font color='red'>嵌入式</font>应用平台构建(六)——linux-3.14.4移植到OK6410-(Yaffs2文件系统移植)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved