电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师3 j& w7 ?: P( Q* ^- U7 b9 X9 O
关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
; _, O# H/ g  }6 s  L$ y* A使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。
- d$ U& M1 V  P8 g) V1 E

rhz4zq5cili64010755427.png

rhz4zq5cili64010755427.png

" L( m# v% W! {1 r! n. f1 S8 D二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。
/ H* @; q) p. e; W三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread
& V  T6 L2 m8 ~) L头文件接口:$ P  r) V7 {; S# C/ S/ f4 {) i
本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
% Y% G# Z: g, B- H6 Y+ M/*
! n% l, j) K2 {# b4 M    驱动注册
% N8 l; A/ u1 c& E*/# n# f1 i+ b8 [) {! ~" ~
int cola_device_register(cola_device_t *dev);4 i! W7 t( Z6 R/ Y- u8 Z+ A2 a# c
/*# x& k! _" i) K# g4 X
    驱动查找
; i# G3 d2 W% n$ G3 S*/4 y2 K6 D0 k. A
cola_device_t *cola_device_find(const char *name);
  B8 C, _, [5 ]2 k+ y# W/*
' f# ?% Q! Y! Y    驱动读
9 Z7 u* s1 m% ]3 I6 D: x2 ]# |*/
% W- j. L/ I0 Kint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
, u3 R* W2 S! T* Y; x% s3 o- k/*3 n% l) t! r5 ?5 V
    驱动写4 Q) a0 Q9 |& y' L1 l" c
*/
4 {3 F/ M: i1 Dint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
3 d# q' w( i  Q# h) Q7 \% e( R/*
* L) ~; O8 R) i  w6 t    驱动控制% s; j9 r; g' u) I7 C0 E& ?# N" f
*/9 _0 D: _  X5 @+ d
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:
* w$ k7 s' N  m- L5 T& u#ifndef _COLA_DEVICE_H_! r6 n8 O6 W9 H' h
#define _COLA_DEVICE_H_
& ?. k4 F; [7 d& f. j* `enum LED_state
% O9 ^  B9 c" j+ `; U# o) ^{
" f0 V) y9 R( D; R: j0 }1 D    LED_OFF,' X  \; @/ J3 q# G
    LED_ON,8 ]5 t, x: v1 E1 X3 l: |
    LED_TOGGLE,! J$ l* u6 K, Z2 S$ e0 c9 T# D
};* H& P7 f* s8 d/ _! ^  _  r8 M
typedef struct cola_device  cola_device_t;
3 S6 N# l1 }1 V  N% R2 u3 dstruct cola_device_ops
) D: y' w; N/ [1 E6 I# Y{; J, H/ I/ l5 V8 g* V+ T
    int(*init)(cola_device_t*dev);
; V7 q( q$ G4 b; W& X" c2 f$ `# |2 V5 b    int(*open)(cola_device_t*dev,int oflag);% E; N2 k% n" |/ A. r  T
    int(*close)(cola_device_t*dev);
% p. {+ f# G# Z    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);. e% a; ?+ G% O( D0 c2 J! ~( o" N
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
+ A7 X2 A, d# V% T5 d/ I    int(*control)(cola_device_t*dev,int cmd,void*args);# C! \! c2 E6 D* k: r
};
. d/ U8 T% y8 o5 k+ R# k* j. Vstruct cola_device
6 T: M1 Q3 V5 T# P7 F3 c4 m{: q! M5 \( y3 }$ R3 p& T8 m
    const char* name;! a( S4 a9 [: x0 P6 h5 f2 T
    struct cola_device_ops *dops;
' b* C1 E5 |$ `    struct cola_device *next;
( R4 r1 T; i% @& W7 `0 i6 v};
; @# |/ l# q# g. I1 `# |- J/*/ `! X7 ^* O( X* V! ?2 [9 A3 v
    驱动注册& {) D# }& |  ~( d: S  g& r
*/
  _7 R& x2 _1 t5 {, o5 I3 x2 d% Oint cola_device_register(cola_device_t *dev);
& q" c# R# X- u3 d/*8 l& b. D! q. |( \3 O% N6 H7 d% }
    驱动查找
+ e+ ^' y5 o) F+ T*/$ Y9 [( w0 B& }# V0 x, D2 C
cola_device_t *cola_device_find(const char *name);
! }9 K8 J; U! v' t* X# B3 W, I/*
6 ]6 X+ T! f; f" d, \$ O$ L( T    驱动读
0 r. D1 B. M; o$ G6 m*/
+ }, C) I& i0 y- @. Yint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
- ~5 y' x  }. }9 l/*
% L* ]: V8 I9 e8 O3 ?5 O4 t7 g    驱动写4 q- B7 _4 u0 }4 x4 i  M& x
*/
1 ?2 B* @* o8 |2 B$ H4 Nint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
5 h) U* v) v) ?  d! A/*
. c$ q& n% Q- H  k4 L* G; C    驱动控制
! _) \' W$ b  Q, ^0 J9 h7 P*/
# ~7 ?7 N) q1 j0 S( U: S: g5 |% wint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);4 w. N( |3 \+ q) p
#endif 源文件cola_device.c:
2 ], ^" M2 q& b8 V! C% p9 q5 ^#include "cola_device.h"
& R1 d7 V& C: L5 o0 R2 G#include
- c+ D# b, |6 n#include
! ~' v& E: f- z5 `struct cola_device *device_list = NULL;
0 `+ p& j# M! |1 c' z7 v5 O* R$ ^/*
) }1 k, L" ?3 G' N    查找任务是否存在" {9 @1 {% G8 E) M: }
*/) j/ Z( u% m# ~5 I! z8 l( b; x3 t( c
static bool cola_device_is_exists( cola_device_t *dev )7 y( Y! _! w. [! a8 i" w0 g
{4 e* E, @) I! t) X  B
    cola_device_t* cur = device_list;+ Z" v4 E0 ^# p) Y0 v* @
    while( cur !=NULL)
0 d9 ~: Q5 ~: l$ k6 M- r0 K    {) F0 T6 Q. f5 h9 h
        if(strcmp(cur->name,dev->name)==0)
' H9 ~& ?9 Q) x        {1 m8 N1 G0 V7 w
            return true;- b5 P4 }4 u- U* a' r3 j
        }
# k, q# @4 s* x$ Z+ J$ E        cur = cur->next;
' j- |$ z$ m8 e  c! ]4 @3 t    }
! V* ]% k; Y8 l    return false;  N* o% Z% h( l( i0 b7 U' N
}; t! O3 b* ~. f; `- ?
static int device_list_inster(cola_device_t *dev)
- p- _8 Y+ h9 c! V8 [8 S  l' M{. X( K# Y7 P0 K) x! I1 _1 Y, O
    cola_device_t *cur = device_list;
/ O4 z& x0 P$ p9 x- ?6 [0 [% `. ~    if(NULL== device_list)& q. Q4 L4 G5 K3 C# o
    {0 f4 m* T4 a( A. G( ^
        device_list = dev;
- _, ~* `8 K, Z7 L        dev->next   = NULL;
6 `; [$ {. ~# k    }+ O! r/ E* ~# f7 F
    else
- N& o; |/ N, R    {5 {9 i6 p$ M9 e. |0 \5 D5 n4 d
        while(NULL!= cur->next)1 B, X- y; x! V; X! J# h" F
        {
) u, n" N8 s4 _, R( _  E            cur = cur->next;, m' [- ]# A6 z' |; k: U
        }
8 T$ U, s9 b/ S' U$ F        cur->next = dev;6 r3 h& G4 Z) ]0 V4 N' j
        dev->next = NULL;
$ y" ?# e* _' h& ]1 l$ j    }- T1 L$ \5 C4 |9 l& F& j3 c8 |
    return 1;. U- Z) x: l. j# y1 f5 l7 \' q
}
  T' k& g; ~9 J" n6 Z; P3 w* V" m& d/*9 U4 O+ [7 V; z8 t# p
    驱动注册
$ ]9 t0 C' o6 ?; w*/- I, I! N- H% ^: z0 A
int cola_device_register(cola_device_t *dev)# _, p1 t4 {: M( T  p: Q% i6 l3 Y
{
3 }2 [9 N% Y5 B8 S0 t4 X8 o    if((NULL== dev)||(cola_device_is_exists(dev)))5 \/ x! k  E& U0 L
    {# u% Q9 ]6 T) f6 p" ?' s! ~
        return 0;+ v6 A5 P& I9 ?. ?; k1 i: B
    }
0 P) ?+ Y; {2 v0 [4 l. [6 {& k, d    if((NULL== dev->name)||(NULL== dev->dops))
) L9 d0 b4 \3 F( F8 ]4 J+ m2 d    {
* m9 ^/ W" h" r8 l" Y. f6 _        return 0;
8 s+ f! x7 N5 n4 \; h' i5 X    }  c5 I  Q. e" P( v
    return device_list_inster(dev);
6 u" H  S  w+ f7 _/ O3 G/ Z$ B+ G}& B( h' c  I" d' E
/*
, \/ i# f/ J1 t0 O    驱动查找- x" t3 l; a3 i  r
*/: H: M9 N- i7 S6 l8 a, y3 p4 @
cola_device_t *cola_device_find(const char *name)
2 _7 _& `. g& T4 c8 [{
) S5 p# z" w7 W/ W2 K    cola_device_t* cur = device_list;
* A/ N; _& Z2 x    while( cur !=NULL)
/ J# {+ @2 ?3 i: Y+ _" Q2 U  \. H    {
2 N+ }1 t% [2 I5 S& I6 l, ^! g        if(strcmp(cur->name,name)==0)
, Z& Q& ]! |; k  G2 L        {7 K( f. F' ^- K
            return cur;
# }, Y- [2 m  _8 k0 Z3 @  @        }6 y4 _" I9 ~9 {* \' \7 z
        cur = cur->next;$ X! T9 F- S4 C. V  a  Y
    }) B: d! N2 r( o5 @6 U; q7 E, p- v
    return NULL;
3 `6 B8 {2 u% s}
7 T3 v9 ?1 U8 ^$ w) V5 G, d' W- J6 a/*
' s3 i5 G8 D. ?) A3 ^    驱动读  Z  T3 j. m/ Y) D# N1 h
*/
( n8 \& O9 f( \9 t, D8 ]int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
! K" W! a. n$ B3 g9 X/ }3 N: x) c{
+ Q0 F7 g* O5 d% d7 i; A# ^; e* k- F    if(dev)
, R3 n% `( R: h* w& J1 v9 z    {: _% I* y- X3 b% i! d6 A, H9 `
        if(dev->dops->read)
& _$ S) c) ^  T) o        {! z6 Y/ _, |3 [/ X# D5 p
            return dev->dops->read(dev, pos, buffer, size);3 U5 k4 Z+ M$ e* D
        }
7 D/ ]3 @# E# ^# v4 D. G    }# l1 ?1 }) g& s5 d: K5 e
    return 0;+ f/ R* d# [6 k; _  l5 K! ]; C
}
& V0 k  r! ^, ]$ q9 V3 R/*
: o, m1 a* l2 u: E    驱动写
' i8 Z3 |4 w& c; X1 q. c2 ?4 m*/
6 S! ^1 R$ u1 Sint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
0 }; N3 X3 f  t' C5 r/ Z9 L7 j8 e+ M{7 J% W* p9 s& v0 W5 N2 X
    if(dev)  _( s, l! x( s
    {
+ y: d# d9 Q6 P( `9 y" e        if(dev->dops->write)
: j* v3 x2 o4 B6 @* x        {# w" n: f4 M. E6 D6 f1 k' G& _
            return dev->dops->write(dev, pos, buffer, size);
. ^2 ]$ E4 ~, h% @        }) F& I) U" ?, ?5 A' |. E% C
    }
, U, t) R2 S6 l  {. s- p5 q+ F    return 0;
  I8 l. @7 Q3 y) Y}7 [9 d0 U. z9 L* h
/*" k. R& g( ~0 e7 }
    驱动控制- m) V; H+ Z' O0 \2 z$ u
*/
5 k* E0 H& x' E  y" \5 rint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
, q9 K) S) V" {/ ~0 h{4 c/ ?$ D' H' e( C9 }! [, w
    if(dev)2 J1 i  y4 J4 r7 F
    {5 A7 k1 n0 g% E% [5 ~
        if(dev->dops->control), h& v2 c% E) p  K9 Y$ v* {
        {
7 s" Z& ]$ K$ g7 i( A; Q9 O            return dev->dops->control(dev, cmd, arg);  u( \: S9 u1 x  ?; ?/ N
        }8 S, r  @5 l  }5 a
    }
, n5 k, |: v7 c: T9 V    return 0;5 W5 Q& K& I) g" b! U- k
}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。/ z/ i9 }4 ^/ B& Z7 t( o
#include "stm32f0xx.h"
# J$ n7 x/ x! i7 g; u#include "led.h"; g/ H3 z! G% t
#include "cola_device.h"" t% C' f0 U; k  }
#define PORT_GREEN_LED                 GPIOC                   2 ]) m$ S3 F0 ]$ s/ s" D7 v
#define PIN_GREENLED                   GPIO_Pin_13              & L; i$ g& e! O
/* LED亮、灭、变化 */4 w5 L: g) T2 M2 L7 C- U$ E
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED); M3 }) q2 r- ]5 f6 F4 r
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)4 W- p- G# J0 T! x$ R% h0 `" r, j
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
7 k6 F; o- V7 tstatic cola_device_t led_dev;" d: h; Q2 ~! P0 G. o
static void led_gpio_init(void)
9 x, x2 a8 A! ~{
( }/ F% O. n5 u" T9 i: [    GPIO_InitTypeDef GPIO_InitStructure;
: |' j' s  P, M1 ?# E    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
8 i* ~" v! }# q  a    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
. P2 J! v- M. _' l5 _3 w3 `" O6 M    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
3 G3 Q" Z+ |( _% C6 h4 B1 B& k/ K    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
# Q0 w% @8 }8 J" T    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
; D1 H+ D2 F; Q! {0 a    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;1 l. H& X- I. i' y0 R2 \
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
- A; Y# q1 ?7 t  f" y1 [# W7 f    LED_GREEN_OFF;. T, p$ Z0 ^# R
}
# T/ r/ m2 s7 t5 P" D/ d  u/ o9 z5 r+ `) S) s0 V, _- m2 {1 y: G
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
1 f5 X, _% _7 U+ B+ ?2 o" A' s{
3 A% V2 b. T( T    if(LED_TOGGLE == cmd)- M' a) m. ]+ ]- q
    {' c! h" y: S# A- u
        LED_GREEN_TOGGLE;8 ?, c' ?- {2 I$ i5 _/ {; L3 u
    }
* D8 x$ L( e4 ^, m$ R* k& j  p. T    else; w( C+ M' J8 h
    {
, u* j7 }  S! I# d/ E# A2 G    }
% A, B4 d9 j' Z( E    return 1;: A, g* Q& I; V' D& {7 T; Z
}" P$ t  Q% L7 x  l) T$ _) D
static struct cola_device_ops ops =; M  L( m& |+ K- I+ N. F
{
. i/ a4 x0 J' o8 b2 k8 s5 V .control = led_ctrl,
; |9 d8 f) P# d% }3 W};( f; v9 F9 o/ P7 y3 A# R
void led_register(void)8 e! u4 d! Q4 }, \
{
6 @# \5 [$ t' }: J9 m    led_gpio_init();
) `1 m# Y# L# s    led_dev.dops =&ops;
/ Q1 d; v1 h/ N4 h" ]* A    led_dev.name ="led";
4 j# z2 h, a% j5 K: t    cola_device_register(&led_dev);
9 z- t+ Z0 Q2 x  Q1 w0 @. I}应用层app代码:
# P7 k" H$ C2 i- U2 l; Q#include 0 K# k- z7 M2 U; B9 D* L
#include "app.h"
1 g7 ]8 q* I9 m# z% j8 M#include "config.h"' j/ o  g7 Q! Y! s4 \
#include "cola_device.h"! C" e7 b( |3 T( M4 R
#include "cola_os.h"
  q' Y3 G( d, S6 _  Q5 B: v) Wstatic task_t timer_500ms;: F0 d- v+ b* q! Q# m' C1 [$ d
static cola_device_t*app_led_dev;
4 ?3 c, y: U% g" f3 F//led每500ms状态改变一次- K& R( Q& U5 z. \
static void timer_500ms_cb(uint32_t event)
6 }5 }+ A/ J! C{
% I" u  [( G" i" a0 ]5 a    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);  C( \/ J/ @+ }2 e
}
6 g- f8 |9 L! F) [9 `$ a' hvoid app_init(void)/ G3 J$ Q6 ]: _5 e/ U, ]8 ^4 E
{
2 ]( E4 }$ i  D& Q5 H7 c  a    app_led_dev = cola_device_find("led");+ t1 g# y6 X$ _1 o3 ~( B
    assert(app_led_dev);; Q8 T1 x$ k. s5 F' T6 P" I2 k
    cola_timer_create(&timer_500ms,timer_500ms_cb);
. L& E( f# B# e  J/ X! f# R    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);6 D6 j0 n$ N0 G) ]! ?& M' \0 h
}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。
4 W. Y+ W; J/ P1 J' J$ o9 a% h- M四、代码下载链接https://gitee.com/schuck/cola_os
" R: ~9 e3 ?# p* Q3 F
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722, e# W; {+ w: X1 x! s
-END-/ q. U3 b* w5 {$ g6 |4 Z
往期推荐:点击图片即可跳转阅读
7 I9 w) S0 h9 l7 E$ d                                                       
5 S6 A, A# R9 t( o                                                               
$ G; a( m; c4 i; z" V; S  p4 K                                                                        4 w- g3 v  M. h" K1 ]
                                                                               
) q) [% l3 `8 A$ |( X

hfwrunjtyoz64010755527.jpg

hfwrunjtyoz64010755527.jpg

- t+ G9 \* v/ {7 c# @0 s                                                                                , z7 O( [! X- x  E2 u* q
                                                                                        嵌入式 C 语言的自我修养
; V6 d8 [) s( x4 f! N6 o                                                       
1 ^0 }1 ~8 x; N! B                                                                . t* M3 V( c5 j
                                                                        ; r! N; w& B. E. Q. a' c4 }: ~
                                                                                . |) I% @) H) Q9 n2 n7 k

sr0c4mauv0m64010755627.jpg

sr0c4mauv0m64010755627.jpg
+ A; V7 N7 r3 M5 S. V/ Q
                                                                                / B  r' x2 F/ A4 D# G
                                                                                        被 char 类型的变量坑惨了!# ^4 r/ D  r* o
                                                               
* {: a# o9 ?, V& x/ h7 F                                                                        . X; q0 }9 }0 b7 s
                                                                                - }; t) K7 }9 j+ F( Y3 e4 A3 A3 H

23ztvbsvynk64010755727.jpg

23ztvbsvynk64010755727.jpg
6 W/ M6 [) i% o& M: O1 x6 e
                                                                                . v; O2 J' K% J
                                                                                        嵌入式 C 语言知识点,动态变长数组
( ^$ v. f+ Q% w( B                                                                               
/ {( ]. c- \6 O$ N                                                                       
9 m2 B. d; s- R) @( E1 E4 F- v                                                               
, S/ x6 j5 Q# M# z( [4 [- `- l                                                        我是老温,一名热爱学习的嵌入式工程师" {" j+ v" M2 g, i# M
关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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