电子产业一站式赋能平台

PCB联盟网

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

如何实现嵌入式软硬件分层处理接口?

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师
' L. O9 W3 @6 n. }5 R4 {关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
9 z5 p: s( Z4 G8 }, z7 l+ _使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。- Q+ s5 x! {; c* j# z$ M

gwivymslucp6403562313.png

gwivymslucp6403562313.png
, U+ U$ E2 N+ N# w
二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。
2 U8 ~+ d' `4 Z8 f, I, S4 j三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread+ U  c( R, e' b0 Z
头文件接口:
8 R: ^+ o" |# q+ c2 l9 a1 i1 D本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:+ F. U/ T. W% _( q/ i* @
/*4 }9 t3 E8 A$ r* h9 M4 p
    驱动注册
$ k" b$ t$ C1 u8 G) V" Z# n*/% B8 b- q, I1 S: j' \
int cola_device_register(cola_device_t *dev);
( r+ ]$ g% m# _9 d5 F% ?1 i% C/*
4 E2 k+ ^" F5 l    驱动查找
& d) w+ F$ [* G. k3 F* Z8 e*/0 V, r2 ~, o% {, D4 r
cola_device_t *cola_device_find(const char *name);
0 f6 j( l# Z9 s8 n5 ~4 H/*
! N' b9 c) y$ l3 O* I! d    驱动读
! u9 W7 b% ^( G% j4 e& R) ~*/
3 n# ^4 r8 J6 t. A# Zint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);) F' E# \; F9 q$ S' `/ [  L
/*
) O: ?$ `/ K. B+ i* y    驱动写
. N$ D8 y' r8 \) W9 l*/- l, ]+ k) [1 S7 d
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);* e& n0 Y4 b) s+ m2 w9 f
/*
) l: W0 Q; Q9 X5 ~5 q- H    驱动控制; E3 O3 L9 }: G1 I8 D
*/9 Y6 M$ R1 o- h
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:
2 x* @8 _5 T7 W1 J#ifndef _COLA_DEVICE_H_' H* w+ U1 [5 n9 \
#define _COLA_DEVICE_H_
* v- _. p, e! B; Jenum LED_state) ]; I6 J. \7 h; ^, h( g" j
{! f$ x, ]9 g, x" ?, G/ o
    LED_OFF,
3 @2 [3 D$ g: @    LED_ON,) c8 \; N0 }5 ], A+ k5 B0 I
    LED_TOGGLE,
+ C  D& j/ W7 C$ }) w5 T. G+ L9 F# B};
! p* C: k& M' |typedef struct cola_device  cola_device_t;
+ P6 [; R1 S/ m% K1 bstruct cola_device_ops6 R  T9 S& v( [: H, D/ r4 Z
{+ M0 k0 Q" k5 ]  G
    int(*init)(cola_device_t*dev);
: R) ~0 _3 ?2 q) T    int(*open)(cola_device_t*dev,int oflag);
' g, L1 r9 T5 @4 h) u4 J# a    int(*close)(cola_device_t*dev);
- E  G1 i6 p5 G7 F    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);' P7 C/ T6 M  Z9 i
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);  c; R5 r" t8 n
    int(*control)(cola_device_t*dev,int cmd,void*args);2 h7 U* I& P, P
};
. a, E/ s, O/ d  v7 {! F" ]struct cola_device
& l" O6 Z: D  v4 z6 k{8 \. i. o* z7 K: j
    const char* name;
5 F( l. s) d( _2 n7 `    struct cola_device_ops *dops;( ?- g7 V$ k8 l  A4 x  X5 X
    struct cola_device *next;6 R. s3 Y- ^* |; ]; @- d
};4 J- {' _. V' q7 ]0 y+ V6 j
/*
. g! t, L( C3 P# g% E4 S$ a- W    驱动注册& X2 i. D. z+ I2 H5 _1 H( X# V, [
*/- q7 K2 `& @$ l& k6 s7 I8 X" M# F8 B8 }
int cola_device_register(cola_device_t *dev);
6 a* X7 B4 m5 a# k7 r3 p5 O/*
% s6 g( b( y$ @: W& v% H    驱动查找6 Z) Y5 H0 D9 d: t. P
*/! l  [, b- R7 Z/ f6 C% p* a0 R% a1 \
cola_device_t *cola_device_find(const char *name);
3 l$ _, n/ e) @' z$ K! a8 I/*
$ s! Z- p3 t1 F: p, K. ^    驱动读
; T4 [2 p5 \. _% }9 M% @% X*/
9 L! d6 V& x. g9 O6 Nint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);" R7 ^9 X8 W2 n7 q  s/ ], V
/*- U8 o% p7 q8 P4 X/ E% F" q
    驱动写: u! Q4 u6 l. x/ T" \0 M4 _  s3 v
*/3 Q, s5 a3 s2 x& g9 p1 [9 H
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);! l4 v1 V) z1 I$ R
/*2 w3 X, W' G, ]; u$ v0 x9 m
    驱动控制9 i: c) E2 `. J9 K
*/: W' H( k/ R1 L+ J. D/ s$ x
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);2 V5 b8 o( R3 H9 p3 d
#endif 源文件cola_device.c:
0 ~- m; K- B' c$ c& a7 ^( Q  v. M#include "cola_device.h"/ O' O% R* C7 s" A$ Z! G, h
#include
: x( ~* v$ B- V6 B" @. ^' F# O3 \, b. j#include
) ^3 w4 f& K7 B0 vstruct cola_device *device_list = NULL;; Q4 e0 O  V8 K* b+ f% I
/*
% }/ p& M7 K; }+ e5 C3 i. w; N    查找任务是否存在2 |+ g; C6 U9 D
*/
) A6 \- j. g* J7 @static bool cola_device_is_exists( cola_device_t *dev )
) W) ]( {; h* i" x9 m0 U0 f{1 C+ j7 w& ~+ m) `! y& Y' `; j' |  A) j& L
    cola_device_t* cur = device_list;
7 `& n" j! f0 N    while( cur !=NULL), c) ^  c0 i# T4 B
    {: X! Q7 g( L# n! M
        if(strcmp(cur->name,dev->name)==0)
. W* L$ o6 q& E        {$ H  v/ t  H, s! s7 `; i' F" v. E* `# ?
            return true;
+ e! h) {' k0 d        }
/ j4 V2 j) _; \; H1 I. q/ i        cur = cur->next;
( R( s/ n  D) O8 c, ~    }
. m6 O) G# `6 v( }2 u( C) h7 c    return false;- r( L/ n- r( ^' m
}/ W; J  [7 r* w& U3 Q( y1 V
static int device_list_inster(cola_device_t *dev)
& J/ X+ @. }: I/ S{
( g+ m1 e7 x0 x( |) s: L    cola_device_t *cur = device_list;  M' h9 j% T. I7 z3 E
    if(NULL== device_list)
% D# \: r: s5 T1 H    {6 |2 H) e: y6 M- [- _& F- |
        device_list = dev;8 L+ @2 ?& e7 b) i* w/ ]) A
        dev->next   = NULL;
/ x8 ]/ x" J7 h    }* X* T+ w: D' D8 {* ?" ?# q
    else
0 l" E) x3 U% t3 z- d    {
, }/ A$ |! @9 U/ i5 T# u; e  S        while(NULL!= cur->next)
8 _& z) S; Z  `$ h3 }" |        {
$ J5 y9 y7 Z5 x# e# f* T            cur = cur->next;4 o  ^: {2 S' g; _4 I' ?! F
        }
6 z' D) A: k( Q# _8 B# F        cur->next = dev;
- Z! k8 z: L) J( K* ^        dev->next = NULL;0 \: N) n/ v! |# t7 F7 A+ v
    }) s' d7 Y* l: M. [  d0 D1 _
    return 1;
4 W- L- Y* K+ J* [3 B/ K$ T}4 f: r7 A' K  i6 A& |2 ]% m
/*3 U! B* ?5 M0 |- m- x) y
    驱动注册
( _" P4 a0 K# e1 r8 U. d$ b*/. \' `% P2 K2 S9 l6 R/ Y7 A$ X
int cola_device_register(cola_device_t *dev)0 _9 u) _& l5 d) X
{
5 R* y, V! n3 S( v  h* j    if((NULL== dev)||(cola_device_is_exists(dev)))1 J) }* ^# X* [1 P0 K
    {2 ]0 |9 {4 y3 z6 d2 g
        return 0;- R& Q7 y  L8 G8 V/ s) F' z
    }
) C8 b2 ^, Z" i$ J+ y& A    if((NULL== dev->name)||(NULL== dev->dops))
# y7 i5 O/ v1 q5 |& E% n, y3 W+ U) m    {0 c- ^; A7 ^( ]; ?  g" M
        return 0;
4 h" ?/ j5 n+ u4 C. i    }' G3 M1 B8 J- j5 w3 p
    return device_list_inster(dev);
# F$ F3 a/ k% |" {$ g5 U- J}! s8 _9 C" j; H: I' k; K
/*
# I% @, ]6 \( K5 d+ @    驱动查找+ V! N, k0 V* N# c3 E
*/& @* Y. N! r8 K6 ?
cola_device_t *cola_device_find(const char *name), @0 f& l+ \, j/ j: D/ e
{
, f- d1 k. f% |) \4 N    cola_device_t* cur = device_list;1 F) X# t4 D* y' m& K
    while( cur !=NULL)! ]! b9 M3 e4 b$ U) R
    {
, J8 j, a$ L; O5 U/ d* V        if(strcmp(cur->name,name)==0)
" T7 `! p8 D2 E1 L+ n        {
# n; p! s5 i7 |% v            return cur;
/ I3 o9 R" {$ \        }, q0 o, |$ k4 j- y& [
        cur = cur->next;/ v* A' v1 `2 P, ^+ o
    }4 I3 m5 O4 g4 P6 N" d2 s" b
    return NULL;4 I2 u+ I( I9 W: K% B# B0 \
}5 n* X# d9 h* ^2 {0 n
/*
9 t( B2 m1 n4 l$ q    驱动读; v6 J: }5 q, ?
*/" B+ I; Q7 k" s) P0 P
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)2 T8 e  J3 R) d/ r
{
: Q( [6 t- e4 d4 A) F* {    if(dev)
& G7 v5 |9 n. U9 i7 m# k    {% @3 s- r' ~5 B2 s
        if(dev->dops->read)
0 F& Y4 \$ N& I: {& a        {
) M1 `; `, U" y            return dev->dops->read(dev, pos, buffer, size);3 Z- P9 X- s+ q3 Q6 X
        }
1 \1 K* i$ u4 ]$ F8 p" l    }
/ v* c3 C; Y" x. v' l8 |  ?    return 0;, D4 u$ ~9 p4 G/ J) t6 o
}
; X0 R+ @  w$ L3 R8 ^* q% [6 Y/*& t- H% o5 f8 V( t2 V
    驱动写8 n6 N5 x6 V5 p9 x
*/* [( {! E' y' c/ y3 v& N# I0 V
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)+ a! Y3 H' l& e. x/ ^$ O
{8 r5 J( ~, Q; `) j
    if(dev)
0 c- e- _) H) p  w$ W    {, S! E" |, {' E: l, m8 E7 @; f& c" A
        if(dev->dops->write)
2 i4 }$ C0 W7 ?) R) q        {1 T; O4 S( ?9 c
            return dev->dops->write(dev, pos, buffer, size);
2 {# q$ I1 F7 y! ]% @4 E        }  }0 P3 j* o# I) e" G
    }7 i& b3 g$ n% `5 Q& F
    return 0;
% Z* S$ f+ O5 B}0 Z/ r: ?* |7 u* \  i
/*$ d0 ]2 K; u2 \7 K* o0 H
    驱动控制
0 y" L4 O6 {& {* V. ~*/
5 D5 P1 n+ b; |; S  V4 j4 v. d, ]int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)2 f2 W5 \$ c! e: N  Y
{& s# U& p- K; j( ?3 Y* z$ O
    if(dev)' E( X( |- Y5 H
    {: ~" W* W+ A4 ~- C! w
        if(dev->dops->control)
6 r0 B; g  d( {9 l5 M6 g' D4 q        {
' p3 d$ N4 ?; I! Z7 V: m            return dev->dops->control(dev, cmd, arg);" v$ f, ]) b1 h/ U6 n
        }2 j  V% t5 l% U
    }1 |* x5 f/ A" P2 C: d% v- U5 \
    return 0;
3 u. p. Y* M8 ?3 F}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。
4 p; d3 U; s: ~. }# G#include "stm32f0xx.h"
; B+ w7 y5 n. r2 t  Y4 `6 q. q#include "led.h"$ s7 V6 b" y2 |
#include "cola_device.h"' m  b: I& q8 h
#define PORT_GREEN_LED                 GPIOC                   8 P+ r6 g7 u! a8 d( W# L  q9 R
#define PIN_GREENLED                   GPIO_Pin_13              6 S  Z8 s) t& W  {. Q
/* LED亮、灭、变化 */
. L; b" W( V7 L#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
  ]9 ^9 X/ x+ I5 c6 \5 Y5 }#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
4 r& a* {1 g( N9 H. R#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)5 _8 v- T4 N. X' A# F* M
static cola_device_t led_dev;0 Y1 _4 D! x9 N, E) G" g
static void led_gpio_init(void)
" o* Q6 x! m5 k0 S{1 d6 h* f  c  m6 y2 M: e
    GPIO_InitTypeDef GPIO_InitStructure;
% b" z8 s1 ~" a+ V7 C    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
: Q* R$ T" X2 b6 p! T    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;6 `; W5 A) }2 e) B9 O
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
) F( f( j" N2 }8 H) G    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;7 T* [0 ]4 H& x4 V0 m
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
7 y  ?- p/ R8 S! V, A) c* `    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;- M" F  E/ i3 W  U, Y2 k
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);6 b! A8 q2 H! P% v6 r
    LED_GREEN_OFF;
  I* i1 E$ w+ M- `: Q% y2 O}
! ?  G' p- e6 f6 c' A0 {
" P* h: ^2 J" ^1 J, P) D) Hstatic int led_ctrl(cola_device_t *dev, int cmd, void *args)/ m7 F* o% [; V: _& m( _) E
{
1 x; u- ]% v0 Y% u8 L/ P    if(LED_TOGGLE == cmd): w, ]1 t; m- H( y' c1 F
    {8 O+ S6 b# Q2 e2 E# \
        LED_GREEN_TOGGLE;" P+ B' s$ X# n9 d# ^/ l% F$ N9 o
    }
8 [: |' |0 ]9 v& C5 h3 p    else
) Z/ ?* ?: ^& Q  _    {
9 r4 q& i" U4 }2 o: |3 E    }
4 C  ^9 [  q  F3 b  Y8 l+ p    return 1;1 T& o, V: x' \' y+ C( X: u
}
) J6 g& ~- s' {. J; y3 n1 M8 jstatic struct cola_device_ops ops =
4 R' D* O: M& Y+ x$ T{
2 N+ d% f8 i$ \3 ^  M .control = led_ctrl,  X8 Y+ \& D. B) s
};
* g) k; f5 H$ G- F3 H' nvoid led_register(void)
- n) z$ U; V# x2 A# T{
+ I4 X5 p1 Z4 d! |& C( ?    led_gpio_init();
  H& b" b% t* k6 z    led_dev.dops =&ops;; B" |  D; ^, }, U
    led_dev.name ="led";4 z& w9 `' Z7 c
    cola_device_register(&led_dev);( ^4 Z# c6 S5 H1 l8 q: T
}应用层app代码:- o: [; X% L5 Y. v4 `
#include % a6 G$ P% e5 E- y% {1 _( b- ^
#include "app.h"
. j/ _$ J( V0 [) \$ A" Z#include "config.h"; L$ Y9 O7 G; c, [! p3 c
#include "cola_device.h"! N7 u- a; K- t$ ?: Z
#include "cola_os.h"
5 o6 ~$ O7 v4 b4 `4 Kstatic task_t timer_500ms;
7 E9 ~3 I3 G$ j# g3 N$ P# W+ istatic cola_device_t*app_led_dev;
% e# q) Q9 Q5 S7 l9 x//led每500ms状态改变一次
; I9 d4 P' F  h3 M. `, J6 |static void timer_500ms_cb(uint32_t event)* C' K1 i* L7 \3 i- G
{' }2 B0 ~* B/ [9 H) T& E
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);2 {4 \0 z/ t& b; ^
}
5 m3 M6 x& c7 [' q) d7 E/ Gvoid app_init(void)
0 B6 E# [1 d; G' p- N1 i{
+ q+ u/ q: C  m    app_led_dev = cola_device_find("led");
( o* r# n% H3 T* `, _7 E# S    assert(app_led_dev);' l$ ^+ S1 I: V) B1 `/ `
    cola_timer_create(&timer_500ms,timer_500ms_cb);0 t1 H5 i/ a& B* e3 d  h3 o' k0 f
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
% I6 N1 V5 }0 t}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。
- P7 ^) l7 p- \' o2 P) Y- P: c四、代码下载链接https://gitee.com/schuck/cola_os: F: m9 T& d. q" D5 E
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722  w1 {  M5 e0 P" [
-END-3 l! f( L' Y0 H' j( ^
往期推荐:点击图片即可跳转阅读; b9 y. D1 X+ e1 ~+ S
                                                       
! P1 N. b, E$ n& Y! d                                                               
4 n9 n9 U% y/ y3 h& I1 W                                                                       
1 K% z; P' G) ^                                                                                ( v4 b3 u2 |) [8 G/ u/ ?

d5ss33dlyy06403562413.jpg

d5ss33dlyy06403562413.jpg

% D1 H4 f7 ~" Y# B, t6 R                                                                               
2 D, C) K3 x$ g                                                                                        嵌入式 C 语言的自我修养
' n& o' b1 ~) x6 w! C, @* h: w  K                                                        3 [# @2 Y; a4 Z
                                                                ' x7 ?$ C) k# \) R% U
                                                                        * V7 p% k/ ]1 h0 v" }4 y
                                                                                3 p, M$ `) d, t  k

muou0vlscdk6403562513.jpg

muou0vlscdk6403562513.jpg
! U& y1 Y% I7 d2 Y+ I
                                                                               
6 z! s; O0 a, |5 \; |0 N) o                                                                                        被 char 类型的变量坑惨了!
6 n0 d+ W9 i4 B) ]8 n                                                               
5 ?( U- ?' Z) N/ s- d+ Y" r                                                                       
$ B0 n' M) d9 ~* K4 _1 t                                                                               
  y8 T$ |! v5 b  t

rn0ayfz1kxo6403562613.jpg

rn0ayfz1kxo6403562613.jpg
" e% s$ H5 [# c
                                                                                4 S) T/ T# q% l9 @& B5 t7 z
                                                                                        嵌入式 C 语言知识点,动态变长数组
5 f7 `' _. c' M6 Z7 v0 S% b                                                                               
  `; l( g' W8 E+ C! u/ h                                                                       
0 g( \( N) h3 C& M% K9 B                                                                6 q7 b3 `) p# j/ h9 ^7 D
                                                        我是老温,一名热爱学习的嵌入式工程师
* V8 X' Q/ [& i3 w关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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