电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师& m$ R! g8 e( O% ^7 U# T" ^7 N) j
关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。+ k5 S8 N' |9 X; ^# v# v
使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。
$ e& Q& `  |  n5 I2 U2 N

hs3hnielobh640200602.png

hs3hnielobh640200602.png

" Y: s: @: k# t( H二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。& N5 n2 I; n- D
三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread/ v- w9 b5 c  _  b7 v& ^; e. |
头文件接口:
  Z/ t3 ~* Y: Q  i! F; w: q本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
- R! d0 I7 S( c6 W; H) S8 _# T: q6 o1 i% o/*( T  N, q1 j9 |2 d* t% J* J  T
    驱动注册* v. R% W! z4 A' L/ \
*/
+ l+ m$ B+ I$ W6 d( J' h7 J; Bint cola_device_register(cola_device_t *dev);
& P" g/ i  ]. `2 I/ u4 f& g/*$ G( Q5 x' J9 _5 s, ^
    驱动查找
9 O. L1 V4 N8 L5 P0 r*/
2 @; {; f' B+ R  G+ ]0 ]& ecola_device_t *cola_device_find(const char *name);9 q. }4 t" L5 R1 u9 N8 d3 h
/*" n. {' ~8 n* T3 q6 w! b
    驱动读8 @. F8 n: J' |  m2 K6 T( i. V
*/
+ `% A4 o1 }. `; U! S$ y8 vint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);0 Q5 G) ^2 E8 |! t+ l
/*
) T# k6 V) @8 q) `; v0 `    驱动写4 I6 o4 O5 G* n8 g
*/
% q- @% g7 l" h+ O  ?int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);* l2 y4 `# b) r" S' ]
/*! X$ u9 C/ O3 a, d( r, w% x
    驱动控制: m! r' g' e8 R5 ^4 l
*/
) a+ @! N- _  W/ f7 U3 Xint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:, H+ g* a( F, J
#ifndef _COLA_DEVICE_H_/ k9 h% `1 D. e# s. b5 q: {
#define _COLA_DEVICE_H_# }" }  h9 p. ^3 f% |
enum LED_state. I7 R1 f: X9 c
{
8 I; `6 q2 D, I% d$ D2 T    LED_OFF,
0 s8 Q4 x$ m0 i* i, o    LED_ON,
' r# Y6 K, \* _, T. w" y( d    LED_TOGGLE,
& Z  m$ Q) x- h/ @" i: @};+ O8 A" j" U) W& u% K6 p
typedef struct cola_device  cola_device_t;
) \9 J; N/ x- L/ z# \  d. k" sstruct cola_device_ops
; }  z& E0 \! Y' b6 U: p; ^{
  A5 \6 }) ], }4 G& U: Q1 ^    int(*init)(cola_device_t*dev);
* t5 |2 y2 O: K( H3 H7 I    int(*open)(cola_device_t*dev,int oflag);: v% L1 X: u! t  M& G& ]) x6 u; F7 O
    int(*close)(cola_device_t*dev);
4 O& x' u% g4 M) l" _* @    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
) }0 T% w5 ^- e( B' {    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);1 p: z, r- g* C% K8 A
    int(*control)(cola_device_t*dev,int cmd,void*args);. [" N/ G4 @: W* H' n' V5 |6 q9 s
};
  Y+ q5 n# F! [' ]* k$ w0 a8 fstruct cola_device
; ^8 T; x3 t8 T. f! O8 R7 u{8 X0 [+ x. D( k6 I, O6 H
    const char* name;$ C; W3 K& q1 E* C. e& t
    struct cola_device_ops *dops;
5 ?" m* L. _0 V3 x2 Y, H    struct cola_device *next;
/ _' u4 D, _; E. F, y};! h0 r+ t+ Z! o6 ]; K0 Z
/*3 y7 _+ T2 Y; V) [! e! `
    驱动注册
" s, z( l" c# ^9 \  `/ {7 w*/8 O0 G+ M. I$ O$ x6 d% G% l4 K
int cola_device_register(cola_device_t *dev);
) V0 K& c4 N# z! h& W% n0 [/*8 W% X: j! H: Z. P
    驱动查找- v4 H6 O2 z3 d7 A. `6 k
*/
$ b3 L- d. |- W& U- Mcola_device_t *cola_device_find(const char *name);/ r8 a% Z* _- u( W- ?- `3 K5 S! z. W
/*
# O4 ]( ?# D% K! |' q/ h+ p    驱动读
2 P# y9 z+ k/ U# v6 l( U*/( n7 m' A8 A4 m9 ]* `! j
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);% v( ^! R5 }# I- s9 B
/*
2 @- F6 Y# Z7 Q, V7 v) }& m    驱动写
( a3 X8 t$ D8 j. o6 o$ W  H*/
- r1 F: p$ b+ Hint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
5 A9 [2 u. a0 V/*
1 I( f3 F. N& ^1 ]; i    驱动控制) C/ r5 L9 g  A8 I; y& |
*/# l- A9 z. Z5 V7 R$ a9 y6 d4 f
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
/ S- P8 [# i3 J. u#endif 源文件cola_device.c:8 }4 O  p8 n& W6 N9 @
#include "cola_device.h"- {2 h" T1 ~1 H
#include ( ~( V" v& h% g  w
#include 7 [" k+ F. T1 D. [& e
struct cola_device *device_list = NULL;
1 B$ s, D. v- s* M) I2 u4 U/*+ T/ |& g+ R8 }+ b
    查找任务是否存在
# O8 H- Q7 L2 M3 o8 c+ I/ O*/4 ~: b$ u7 K- E7 R& R$ T
static bool cola_device_is_exists( cola_device_t *dev ); G. p/ S, L# g6 q" K5 z
{( X/ U& C- w3 N+ N1 i' Z3 O
    cola_device_t* cur = device_list;) p9 K1 `( a0 \1 X
    while( cur !=NULL)
8 ?7 k9 _) l2 Q- h' h, c+ G3 v    {
6 d; B% ~% D. B) S        if(strcmp(cur->name,dev->name)==0)' y, ~) c% B% s8 q; n* }5 u
        {
/ P* K  x! s5 A3 }2 O* h7 d  E8 X7 Q            return true;
$ B$ t# }2 [: H4 T4 a3 t# X        }
) s# O, i9 ^) e0 K        cur = cur->next;' l/ r, c* g; Z% S. g" x6 }
    }
+ s0 Q+ K5 A* H& V. z8 n: d0 s    return false;
' V9 f; Q8 M- c. ^  Z5 M- K* V/ L7 T}
% g0 `/ ~5 {% Istatic int device_list_inster(cola_device_t *dev)
; w7 Z' r5 U. F% U{
3 U  A6 |4 K% J5 f+ V0 o% ]    cola_device_t *cur = device_list;
1 y1 J% r# n+ ]7 i+ z) k, u    if(NULL== device_list)
% E2 h$ f; M! s" c" ~2 C    {
( c) v5 W1 X7 I8 W- B9 B9 H        device_list = dev;- `5 ^# V4 u- r( L( h/ M
        dev->next   = NULL;
  z) i* L+ D7 d) @, l1 P    }
/ s' X% r5 W/ r. i7 Q' Z    else: ~' J& s& T* r" n/ ]
    {" |/ C( `! m; e
        while(NULL!= cur->next)- M9 b; {9 Y, B  h! t* S! k
        {' d& Q3 x0 D. p  f
            cur = cur->next;
$ x& m- k/ b. Z$ k: T' ~        }
% E# |$ x2 [  Z        cur->next = dev;
1 p, A7 s; d' V1 a* h9 ^- i        dev->next = NULL;
+ ^' t: r( D# @7 ?1 x4 B  H    }
0 L* g2 t, h  P4 a0 k, u( F    return 1;* e6 Z9 p, {8 {# v
}' i0 G9 z* [4 {" h" M$ @6 B
/*; u. E( j3 _# ^
    驱动注册
/ n0 X' o* t9 r*/
8 b0 h4 p! Q$ T2 mint cola_device_register(cola_device_t *dev); e1 z( M, {" H7 V3 Q: I) g
{
, |: V# I7 }* w% |. U  O( H% U    if((NULL== dev)||(cola_device_is_exists(dev))). L# v0 H/ G! d2 h) J4 p
    {
) _/ Z! W( U  Q& |% T) y; [# B        return 0;
. _; k9 E3 ]: n, O1 T! k& p2 N8 B    }
# q4 f4 p* `0 j2 |    if((NULL== dev->name)||(NULL== dev->dops))* i- A; D: ~5 t% c2 F& U' f
    {7 R3 T3 }$ J# ?  M
        return 0;
0 ^+ _9 W2 w& T3 y. l    }7 y& C0 D3 I. R: u; M, U3 J
    return device_list_inster(dev);! m3 I* Y5 D5 G- x( B2 X2 ^2 @# Q
}) f+ S8 X( K( U6 `0 Z# w. _
/*
) b* c2 }5 ?( U& `, \& R' w    驱动查找
6 A# z) i7 P6 \; W3 F*/4 z0 Z2 k9 ]* g* V  e  M1 _
cola_device_t *cola_device_find(const char *name)# c# Q& {" Z( [# m" u7 u; {0 \8 r
{7 A7 b/ c$ x: M. R. u5 F) r
    cola_device_t* cur = device_list;8 L; _4 n# v- A) d, \! ^% B3 F1 l; a
    while( cur !=NULL)8 F( I. `+ j% w) E( o: h
    {' g2 e! b4 \( V5 `% V
        if(strcmp(cur->name,name)==0)
) m9 V* o, L, E) O9 l7 D- O        {
- E: [/ x' j$ _) z8 t7 P% F            return cur;$ c0 Y# f# n2 g7 A5 i5 a  \
        }0 O) T' K' h2 D2 ?6 |8 [
        cur = cur->next;  w0 Y9 h7 z8 H$ K2 b
    }: H/ T) ]* {8 G7 R* h- o2 n
    return NULL;% v& E! n0 c' \) v/ b- N
}# {; O8 l: x& T0 i8 ]( g
/*
3 Q! t0 {% y8 M% ?! s( g    驱动读9 `/ t. l. z0 i- M, E3 `& z" m
*/) f+ @- x( W: N- N+ H
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)1 t5 {/ Q) j% t
{2 @1 R, }  N: W( H: Q
    if(dev)/ K, N8 @. S3 [* \5 F+ |
    {( B7 e1 u3 J7 i/ |& m
        if(dev->dops->read)
( ?/ i( Y+ O+ y9 Q        {
# X: @2 u+ Z6 W% h2 S            return dev->dops->read(dev, pos, buffer, size);
; z/ `6 Q( M/ }) G  g1 d+ y        }
4 F3 ]. y) d+ m: C& ^    }
) I+ q+ x5 s( n& ^- N    return 0;6 W/ l3 }" |; |
}
9 Y6 y, M6 A" D: E" f1 a! I4 @/*1 }8 ~; E; y( S. W9 _8 ?
    驱动写
3 {# }$ s) ~$ ~- ]*/; i  X0 |% C4 e, `. h
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)$ [+ x+ @1 i) e' o1 W/ Q' H
{
$ }" W7 [/ C! C. Q% o' G( y    if(dev)
7 S- C6 }( z  J, j1 [    {
" Q7 h( ]6 P) r5 r: J        if(dev->dops->write)+ m) r* g' K, F* D
        {! i0 \- o  _& a1 S$ h7 Z
            return dev->dops->write(dev, pos, buffer, size);
2 w7 M  l9 C. u& j        }
5 t" Y6 X3 x& N. E1 I9 R    }
1 ~4 W5 Z& G* B, g4 `    return 0;
+ h" S% Q7 {* f! u7 A8 o- J* E}' ]. ^" H% Q/ `( j% H9 e
/*7 l4 b% @0 Y* K/ \& q, }. Q3 L
    驱动控制; V& t; P9 @8 B3 A; @7 D4 Y& J+ F% D6 j
*/; Z( d$ }( ~4 t& T
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)( a5 f: b# B6 G& E: p
{
; w5 ^( ~  E; J0 G9 F    if(dev)
) a8 ]" N# [$ S, g    {
9 n  `) e1 s4 {0 b8 S8 @4 `7 f        if(dev->dops->control)
+ Y, ^( i( ^" N2 K3 Q        {
) t; A( P* X. K" l            return dev->dops->control(dev, cmd, arg);
; A: C! A1 U  u. d3 i        }
  U4 g! t2 |* ]  e" B3 X    }3 l, t* `; `/ O* \8 i
    return 0;
  l; W$ @& m- M) D. N: E}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。. W& ^* K, F( x
#include "stm32f0xx.h"1 l- y, n9 s+ ^: m, M' c& N6 L' Z
#include "led.h"
( I1 [& J/ r0 k$ G#include "cola_device.h"6 o$ U9 w9 u! H) Q0 V" k3 L5 e
#define PORT_GREEN_LED                 GPIOC                   ) S8 `$ L% y  h4 k0 ]* T/ M. ^
#define PIN_GREENLED                   GPIO_Pin_13              0 _6 f* f$ z/ l3 n8 P. M8 `
/* LED亮、灭、变化 */
9 t# j& l1 L2 Z# `#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
/ y- }; A' Z6 K0 o4 @$ V% `, s#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
6 n) Z; Y+ ?6 j1 F! G& e#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
# w# a( q5 K8 ~6 astatic cola_device_t led_dev;7 s1 Q  v& ], r0 C) K" N0 R
static void led_gpio_init(void)  }+ H4 @4 u/ d- b: |4 a
{
( s# l% _0 Y) Y    GPIO_InitTypeDef GPIO_InitStructure;1 R% d/ B: v- m/ p; ^
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);  I! {+ M' }- X  L
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;! G7 o6 i/ w' D- h7 |4 v
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;$ P7 l5 `# a  u, z
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
$ Y/ z) T: z& M, d2 x4 ?# {% R    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
8 G/ T1 J  m) ^  a  O1 W    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;9 W" w% F5 u3 ^9 U; d. r" B
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);- q" ], j; \& K9 P, {, M0 K
    LED_GREEN_OFF;4 `, ^: t% r' D& d* S" p
}  e8 Y4 V5 q" Z; k& u- |: {
6 r' B- _+ P! c. W
static int led_ctrl(cola_device_t *dev, int cmd, void *args)6 f6 r$ m) Y: O( X( k" i
{8 F( Z  b" G2 n  l4 w% k
    if(LED_TOGGLE == cmd)
, \- v) w3 W3 u8 A( N* Q3 Q    {
: G* @# C8 X- E( [# b: B        LED_GREEN_TOGGLE;
: y7 X" G6 Y6 o+ q+ J+ p/ B* H0 A    }3 w* N5 N1 B* |* h: @/ _$ Y
    else" I' O; }' d3 b9 e
    {: _! Q0 h+ G0 M) ^3 N' h, D
    }
: n7 `+ ?. r$ r7 v0 e5 K$ N) H    return 1;
, u) j8 p, x9 t2 |}7 I- C# C+ Q& q, P" l; ^
static struct cola_device_ops ops =
) |- r. s$ W  n4 F{& x3 G9 z: h' ]
.control = led_ctrl,
; S2 q4 h, w  a6 Q  b9 Q0 g4 U" M};
9 a& a! e$ P, Z$ b3 x& j9 L5 ivoid led_register(void), M0 [  o; D9 Y* G3 A/ K3 I
{
* G% \/ l0 {6 s6 j  N( {: E( p    led_gpio_init();
8 U" Q& R  C8 h* N  N7 J  ]! A    led_dev.dops =&ops;. l% H, Y5 R! L3 w) Q
    led_dev.name ="led";0 w2 j+ s; t6 K* d" V: _2 }
    cola_device_register(&led_dev);
$ [: Y2 F9 x( A# T+ k( q$ m}应用层app代码:
3 {2 k+ o* ~6 I7 f$ A1 g#include
  M6 }( M1 X- t. m( {: x# j#include "app.h"- w2 W) L( O6 n& ]4 t
#include "config.h"
; O' p8 e4 m- O#include "cola_device.h"
/ a# k0 i$ j8 D; H' c7 S/ U#include "cola_os.h"1 h& `4 u" y9 t: Y1 }+ `( |$ f
static task_t timer_500ms;9 _  S7 k/ r1 X4 k5 p
static cola_device_t*app_led_dev;
7 U2 a& C3 j7 C% h//led每500ms状态改变一次
% G+ y4 ?: r: E# P% ostatic void timer_500ms_cb(uint32_t event)7 `9 E, q* W4 O4 h6 I& P2 m5 P
{
2 K$ Q" Z& x6 A  e* c    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
) W, Q/ h/ G! `5 H}
3 i4 a5 r; j3 Y! O- o" Evoid app_init(void)
# {  b" D& O( I/ d& w0 P7 F: a# z{
% [5 ~0 @- t' y9 g9 m! G: ^    app_led_dev = cola_device_find("led");
: n. m1 \) s, ?$ {/ F) s8 y3 @: Z    assert(app_led_dev);; I6 s3 o' K8 R# i
    cola_timer_create(&timer_500ms,timer_500ms_cb);
4 Y0 v) I- Y6 L) l    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
. X( K7 ^; }7 Y}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。0 y0 _" g% C, p  T- |' M! M
四、代码下载链接https://gitee.com/schuck/cola_os. @/ M) X9 ]: r# p& G
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722
4 w6 c/ ^' m& {* W* ~# C-END-0 z* U  X& R1 ~! Q# }
往期推荐:点击图片即可跳转阅读
+ u  R; q/ U" L' I. ?3 l% l                                                        6 T  l) y2 z: Z7 U! B, @
                                                               
- U: p  p  X& M                                                                          Y5 x( ~/ g. g0 Z
                                                                               
# O) F& S4 A- g. t/ n

dgm5mqvgxbx640200702.jpg

dgm5mqvgxbx640200702.jpg

" n  X( U8 G* N- y3 y1 x6 I% o                                                                                ! v/ A% i7 P) D2 G6 M1 q
                                                                                        嵌入式 C 语言的自我修养
# t# l$ A: l" W6 H                                                        0 j$ L8 M5 M, L' N
                                                               
5 E4 |4 n1 E: y5 }( a* O! p                                                                       
- c2 k+ P. Y* W/ Z. C+ r                                                                                5 N# W, V* E" J% V$ Q) q

v2gxwrybvcj640200802.jpg

v2gxwrybvcj640200802.jpg
' B5 c# V# Y4 z3 ^# O: {* l
                                                                                . Z- j$ K1 ^) t6 V5 e6 |
                                                                                        被 char 类型的变量坑惨了!
, K) L# `. k- J, a2 r, j                                                               
  o" t0 P% _0 q, C7 A$ N3 N0 {                                                                        - V/ ^! I; C' n3 ~$ P( ^7 d
                                                                               
& v+ Z! Z. y6 e# u

tokxtqioeoj640200902.jpg

tokxtqioeoj640200902.jpg
7 Q' Y. s3 n& R$ n& p! d! J# @
                                                                               
1 ?6 h7 A9 u/ `0 p! b0 f                                                                                        嵌入式 C 语言知识点,动态变长数组4 e& d7 o/ g# p3 h# p
                                                                               
% z& t% E0 J* s- G                                                                        - i* b' b1 H) o  f( N
                                                               
) D- K4 Y, v; A/ T6 ?* i                                                        我是老温,一名热爱学习的嵌入式工程师
  c8 `8 u  V! ]# a% W) c关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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