电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师
; z4 F) o, B8 H3 {关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
" A, _% \5 o6 |4 f/ g使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。
+ P) b" y+ M* y- k% R' }$ R% q

letrobls00s64019561532.png

letrobls00s64019561532.png
. G, N& s4 x# `8 q  f5 l
二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。9 d# e! b; t0 W0 B6 n
三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread
; G9 n+ E+ B' i4 A; v头文件接口:
- ~% z% x" h* @. B本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:/ u+ H' d+ b: a
/*9 L, n! I, J# ^% R+ W; N5 ^
    驱动注册
: {7 g- S8 ^. a7 B. m  V*/3 t! L# [, m" k, w" ^$ T
int cola_device_register(cola_device_t *dev);5 k8 N; ?, I% K! `* y$ j7 J
/*
& |# a1 P/ V7 _7 e0 V3 T9 u    驱动查找$ Q% f2 h8 @+ b+ n  ]
*/
! G$ l, E' L  H6 Y9 zcola_device_t *cola_device_find(const char *name);
7 d0 V) J9 j0 r* V/ I/*
1 I7 E6 S+ }  L* @1 Q3 V  ~* w    驱动读8 `' l/ K3 s! N4 m' Y
*/9 _; A; n" f; g
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
" ^  `: I: E+ p3 [/ m8 g$ R$ M/*/ ]+ \( n3 A3 p' t; G
    驱动写
+ ~* f; b( f4 _! M9 P*/; v. R/ A3 H4 c& x, Y
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
8 i% y# X. t1 y  ~3 d1 H1 L: u/*  s4 q( i0 Q! Y0 O
    驱动控制# S7 A, W( {% i7 ~. t7 K3 T! j
*/$ R9 n$ a6 n8 F
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:7 e' t9 E. `5 F4 @9 G( D
#ifndef _COLA_DEVICE_H_
+ Q4 I, U: z& l3 [: r#define _COLA_DEVICE_H_
4 X* s$ O! R  O" Nenum LED_state
9 p+ \) D) n0 |( v9 c% D) c0 u  q{
& f$ j. {! ~* G    LED_OFF,
; a% A/ D) O9 O  f' u    LED_ON,& Z- a& @  w+ W" Y0 @
    LED_TOGGLE,4 J, w, X/ j9 M$ W
};: t" D' H$ S# P% Y5 o2 k
typedef struct cola_device  cola_device_t;) q! m$ U" M8 X9 b5 |" \- A$ @2 a- L
struct cola_device_ops
- k2 R( `! l% u2 M{& _3 o: @( U, v  q
    int(*init)(cola_device_t*dev);% a' M& J$ \3 v' d0 `0 n! @
    int(*open)(cola_device_t*dev,int oflag);% E& d/ E1 T% ^) q
    int(*close)(cola_device_t*dev);
( T5 O6 ^( T/ ~. B/ H: L- w    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
* Z4 |; ^$ s, \! I" E    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
0 q( F- g/ h) \7 U' k' d    int(*control)(cola_device_t*dev,int cmd,void*args);% y( I4 }  v/ B4 a$ ^
};
; M8 v: I* h! t" \! Kstruct cola_device
8 P, r6 V2 V' R, c{
2 E( F; z6 ~$ J) ?$ a    const char* name;+ M1 Q+ ~2 i0 x. {" ?. t  g9 l2 {
    struct cola_device_ops *dops;/ f6 A8 S5 d* e
    struct cola_device *next;5 u1 g9 \7 X' v9 A1 b$ L; o, O
};
1 _) H/ p" w7 x% X' o/*
  c, Q) Q4 y8 t9 f; B/ f    驱动注册
4 G4 L4 u0 v/ R6 ?# i1 \  S5 \( u*/
7 ?' X& `# R. nint cola_device_register(cola_device_t *dev);+ D8 X' n/ h  A/ B- q/ e& Y
/*+ M" t3 l! `+ v1 V. L+ ]
    驱动查找
: p+ K0 e8 e1 l3 B1 [5 i5 q*/
& K" j+ y0 [8 o) Z; E) M9 a. [; f. [cola_device_t *cola_device_find(const char *name);
$ S$ C2 l1 Y% i3 o! l* M: }' }$ L/*
: Y2 x4 o9 i  U% o' M% o    驱动读
/ s8 Z, ^, d: K" m# |*/
) x/ d; p/ X8 k7 f, z- Eint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
  ^% Z# v! x; D& O/ X/*
1 B4 ^/ J% b8 O) {7 n4 T8 ]7 ?: ^# N( P$ \    驱动写
/ T4 B  E) K( s*/
2 g' A: ^3 N4 Q  Lint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
# I4 |/ l2 I+ W  E/*
+ a* `( y0 t3 N+ G" ?! N( g    驱动控制
) f+ ^* G3 m1 r1 B( Y; ~*/
# ^4 z) O: C3 D: }( H& qint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
/ p- m0 d8 M' C: a#endif 源文件cola_device.c:
  k! Q* \0 v1 v) [( [, _#include "cola_device.h"
3 n# \5 C7 N' b2 o) `#include 9 ~  o  v9 p3 T. d: o8 S+ G8 E% [7 q
#include
1 P% h$ n; g$ z# R1 E- vstruct cola_device *device_list = NULL;; [/ x: \6 w( t# ^; n+ Q
/*- G" U+ H. }/ a9 @0 m
    查找任务是否存在
' Z" ~) K% u8 i6 c+ H( E$ J# U( ~*/6 o4 z: }1 U' y' L6 U
static bool cola_device_is_exists( cola_device_t *dev )* T% K' Z5 E- E, {
{
2 i1 w. `! h% W    cola_device_t* cur = device_list;
8 k/ [: o3 ]* _+ ]9 D, T) q    while( cur !=NULL)' h1 D: [4 P. r
    {
- N- S3 \. R9 K0 Z  g& c, P        if(strcmp(cur->name,dev->name)==0)
  e+ p/ u  @$ R0 P* V. n: t, A; I        {
% U8 Z. s' w! q4 q; I5 L' D& X6 U            return true;& y; i7 E* a! W0 u
        }
% C3 ^/ u" h# i6 A        cur = cur->next;0 H! C  P! m7 ~) f% R9 y1 \' v
    }
2 F! P+ P$ v% R" |    return false;  A9 [! A' i: [; U4 A: {! R
}) P, r7 |7 K6 ~) q+ |
static int device_list_inster(cola_device_t *dev)
8 a9 s5 A1 {; U4 c9 t; s{; f1 {- L1 \( W- c
    cola_device_t *cur = device_list;7 g+ x  K9 i" d
    if(NULL== device_list)5 ?. D0 u) N  N/ u
    {
! f  W6 }  L" s8 ~, K2 `8 q        device_list = dev;4 I. Q; H2 K' G' ~7 s3 r0 n9 R! Y
        dev->next   = NULL;+ H  K( i% G; D: k: N6 P8 m, L
    }
5 V7 D! n' a( T2 L# k    else
& V2 G  j  S$ n0 i- |* |    {1 Z/ U; w- `: Z. ]2 }
        while(NULL!= cur->next)/ A2 h6 @( ], d1 D7 B
        {3 k: c0 Q; m/ S: }& c
            cur = cur->next;
5 w6 z# G1 h# n+ E' v* l2 M        }8 Y" m- A5 ~  ]  u# b* x9 }
        cur->next = dev;: G1 f- n! E  K: }
        dev->next = NULL;2 M1 E3 c! h# _- d& ?
    }, e# x* y7 b* O; m/ v
    return 1;8 s4 u/ O& h* Q$ R# J9 o8 L
}
/ |* p( W* {2 H- U- H  e0 M" k/*
0 q' O3 |2 N/ T: \    驱动注册5 o: @) n+ S! e; m
*/9 ]% a/ A/ k6 M! n. t4 O# J% H
int cola_device_register(cola_device_t *dev)3 L/ {: i: D# C, i' }2 O( l6 T4 A
{: l6 B5 w$ P  P+ Y) j* b1 ^& _
    if((NULL== dev)||(cola_device_is_exists(dev))); i8 x+ |( x' K6 K7 L- T
    {
0 b7 g) o1 y8 t! o5 m* E. S        return 0;
( C" A9 V% J: r0 s+ y    }2 D& |- Q' G' X' o; S  T8 _& Z
    if((NULL== dev->name)||(NULL== dev->dops))
/ e) o: B+ A3 s0 ]- J2 a    {
! c" W, u# A/ T$ A" U+ r5 e# ^6 D- a        return 0;
. W- Z" \3 ~3 A) ]2 G! m    }
+ r4 w8 `; v/ ^" p( K- _0 W    return device_list_inster(dev);
' `# g8 R3 E: j1 d! J* Y}$ {  i/ w3 A, q& @$ e/ L8 T2 C
/*
- u  f9 t- |. a# r4 E" x    驱动查找
% `! u/ n, x$ t5 A  L$ h1 _*/; |$ T! g+ `8 l
cola_device_t *cola_device_find(const char *name), ^3 n7 r1 X( A6 ~' n, G
{; q" w% n; P' c$ R9 h# Q
    cola_device_t* cur = device_list;
  j) h1 y4 U1 o: h7 u  M$ E    while( cur !=NULL)
5 @3 |; m2 l1 h8 h    {
8 _  k8 D2 X% l. _2 [        if(strcmp(cur->name,name)==0)& j/ T2 M! J( D) H9 ^: ]( W
        {
* N$ T" [; ^, P0 n: l            return cur;0 g0 I- K- d, \- ^2 D% ]
        }
, r  p- b# @7 Q9 Y0 k        cur = cur->next;
  `# [9 M9 S+ q  V& e  V  \4 ?$ |8 F    }  r* z0 F$ F% b* c
    return NULL;
6 J7 u8 N! M0 r+ @* X/ W5 M7 q$ X: y3 [. \}% ~! W$ G5 u  w: Z/ I5 ]
/*( S: r# ^8 d& H& |
    驱动读
" c4 ], `; @4 E/ ^; S( h* S*/
9 L& B7 K; W" [) a4 a$ @9 Wint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)' k- x; m7 J2 K! v: A
{4 s1 h) ]( I3 Q! x' U" P
    if(dev)
& z. o/ l$ }+ u& V' ]  A    {% ?1 l$ e9 W8 y0 z
        if(dev->dops->read)
1 _9 Q. u. W% u0 B$ O        {
9 i' _5 [! Z5 F! \            return dev->dops->read(dev, pos, buffer, size);' o9 Q7 O# X. S% u0 V; }% X  d: _& g
        }
+ c3 T1 t) U2 P& j/ G. J: b    }
2 B8 a: R$ X# Z5 S+ ]7 S7 ]8 H- h    return 0;1 ?  T* n( m. j# ]! R: ]
}$ R0 o/ f2 {! s$ G9 p) ~( W  _4 @3 }
/*  y9 o+ t% R9 S+ k: `0 A$ x
    驱动写
9 g( A- p9 S2 e* O7 m% t( [*/
4 [9 _% H3 M- Y6 M6 r* L  ]5 Pint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
7 h0 v2 `' y! `/ K. B" p{1 F6 {: T1 v1 `9 ~+ c( P7 b
    if(dev)
4 C" s4 A0 t" N* z2 }    {/ ]) {0 I: ?% {
        if(dev->dops->write)
" b; l  D' y; q! U. e& E        {  q$ C6 i4 r3 U
            return dev->dops->write(dev, pos, buffer, size);
" R9 h6 C. A2 G9 k' m        }
. g/ K# b1 d* @3 S- B1 s; y    }
4 _( _8 s+ t0 D+ m    return 0;2 ?$ o) B, ]- y# r. M7 U/ O5 E
}
# h. r% {7 n2 T) t/*
' s, S2 Z* s; X+ B! V! L. k% U    驱动控制
$ @% Z3 e* n* M8 e*/2 X/ Z/ ^  p% B; @' O0 W0 L
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)7 F; d; I4 p( C% u" y
{  Z9 s1 U, |6 h9 ?) E9 G' u
    if(dev)8 R/ K+ l4 m: o. H: [1 ?" O
    {$ U6 c  P& \# M
        if(dev->dops->control)
. A* e  k4 `& H, I! \- ^! W        {- K& |1 y( ?0 [6 J+ m7 i$ v
            return dev->dops->control(dev, cmd, arg);
/ B1 ?" K7 ?, }; C        }- j% r5 ]" h/ m2 K' @0 T5 Q
    }! ?1 ~$ s% }1 d6 ?! U( W
    return 0;
0 _) }0 S  J3 f$ C; E}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。
: N. X0 W) U1 w8 @6 a#include "stm32f0xx.h"3 ~2 Y( K6 ]5 d/ h; t
#include "led.h"7 k! H5 @3 G) O: ]% a9 P
#include "cola_device.h"
8 E7 Z# G, L% V5 N+ ~#define PORT_GREEN_LED                 GPIOC                   9 k" k, o9 a/ {! V  v
#define PIN_GREENLED                   GPIO_Pin_13              ( J$ j/ x, Z. T. \
/* LED亮、灭、变化 */
3 l1 F3 F  S5 [0 {; i& m! Q#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
" _9 G, B0 Q! _$ O( l2 i#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
: S* j6 j# n0 Z  M- [* a2 [! i#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
$ r1 Z0 x6 b' O5 w; T4 |6 pstatic cola_device_t led_dev;" B* q4 p0 }+ f9 g) d, U
static void led_gpio_init(void)8 |, O2 c5 b1 \, g& ^2 j
{
' V) \$ v; [3 @8 t+ P: _    GPIO_InitTypeDef GPIO_InitStructure;
- |7 e( k' q( l5 p# y    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
, ~3 u1 O# q$ [; b    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
. c! l! s0 N: E, G    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- c7 {2 x+ |) G! A/ b. V$ K    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  h; l7 g, X8 c( k2 j. x* S$ r8 o
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
/ h! K. l9 D9 v4 N0 g; A$ H: `# B) B    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;' P6 Z# B# Y- N. {- \
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
2 {" Y- p; q6 V8 T    LED_GREEN_OFF;8 a. W' [9 x+ g' f, R' X, `
}0 D/ g8 r7 d! K. @( f6 _
/ G; u; q* F0 ?6 f3 K' R- [5 Q# Q
static int led_ctrl(cola_device_t *dev, int cmd, void *args)! a) a3 |5 b! d+ X" P
{  t1 G) O! E6 `5 m! ^% f% F, g+ j
    if(LED_TOGGLE == cmd)
% `) P9 t8 ^) i# D  R3 s6 g' {$ P7 h    {
, X) }: l( ]5 ?1 G" v8 P        LED_GREEN_TOGGLE;
6 ^% N4 P# a% B( D( S: O! R& G6 `    }& ]" @) T/ @1 W6 [% f  V# ?4 {+ l
    else
' [; v- y+ p% g    {
- f& l/ Q# T+ B* Q) g% K    }
' T2 ~+ }' V1 ?; L* t1 m    return 1;
9 V7 M, }0 K8 H& e! x3 {& L}
- I" z& T# q  C/ @9 E* ustatic struct cola_device_ops ops =
  h8 A# Q8 J( t{9 F  Y1 k4 d$ i, \% v
.control = led_ctrl,
1 T6 C4 K* a9 |  ~};
1 y" `# c6 a- ~6 d7 S: x" evoid led_register(void)
9 c. |% h$ k$ T% r{
( n, {" m( \9 `5 `* ^3 D1 i7 E) ~    led_gpio_init();
% f! v! X( V- o, J; _) `# a, x    led_dev.dops =&ops;0 A+ x3 v  S& ~% U) b) n
    led_dev.name ="led";
4 C; z" s/ t4 O( C    cola_device_register(&led_dev);  z: z5 H5 y5 L/ J! S
}应用层app代码:
* i2 |9 \6 C6 |% R% ~1 N9 ^: Z#include 8 ~) l9 \. B" w7 W9 ]0 u9 k
#include "app.h"
0 e, U! T$ t0 E% k! }#include "config.h"! B  s- h. d  R( p7 I( P
#include "cola_device.h": M) g7 l! b, M6 y( f* v
#include "cola_os.h"
) @' `, c% l  D  Q3 bstatic task_t timer_500ms;. N- E: Z) z: l1 n$ X& c5 `# @2 |
static cola_device_t*app_led_dev;
- g) m, E! i3 A/ g7 U4 b7 o7 |7 z//led每500ms状态改变一次' Y. [/ z- u) q( J
static void timer_500ms_cb(uint32_t event)
2 c4 `5 M, k- k7 V: I" A5 t1 Y! [{$ i. L: v) I2 G- j9 A4 Z
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);2 Y/ Y2 B$ X, W% M, o1 F: j
}* G; @) @2 Q4 x5 k8 O
void app_init(void)
% @3 ^1 y" l* }{8 l2 |* @6 Q$ L0 Z
    app_led_dev = cola_device_find("led");
( V3 p, h' t7 _3 ]    assert(app_led_dev);  c: R# q* R4 i  F' W
    cola_timer_create(&timer_500ms,timer_500ms_cb);7 B$ u+ r9 \' p; C
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
. h% Z% U9 A9 ?8 N, f- p}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。4 D4 }$ n1 Q( L" L( ~1 h
四、代码下载链接https://gitee.com/schuck/cola_os9 _7 ~9 d" }% A) `! y1 n
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722
1 m3 A5 h4 ~6 H; ~& ]-END-, M8 D* T" S) W% V6 H: f1 K
往期推荐:点击图片即可跳转阅读3 l/ H% D2 a# B
                                                        # _: c) e1 d: C2 O* ~6 |
                                                               
# \! @3 \' u0 B7 f. U$ C0 K                                                                        3 b( L; ?) T3 [1 [# ]
                                                                               
6 m; e& ^; _* o6 ~, ]. A

doqlo0cma3e64019561632.jpg

doqlo0cma3e64019561632.jpg

+ S6 n; k& O- ?5 j4 J                                                                                * J# U8 _% r( P' q: U( T6 N9 @
                                                                                        嵌入式 C 语言的自我修养( @0 k5 D4 a3 i6 i& O1 h
                                                       
5 }# B' ^2 [/ V0 H) S                                                               
7 }# {* \* r/ ?                                                                        9 v. X, ]0 C- F( `
                                                                               
1 e0 z- c4 E* I0 V

z24nisnagj164019561732.jpg

z24nisnagj164019561732.jpg
, S9 Z5 U3 M& O9 O; P
                                                                                ) _6 c8 T) Z) d" A" U
                                                                                        被 char 类型的变量坑惨了!
; q. ^# Y5 N' P' k9 E3 B/ n: {                                                                6 \! _( D7 c, f6 \; F" X
                                                                        # Y$ P( ~* ?4 W; W
                                                                               
/ z5 C' T% D! `% O7 k

mwber4x0eku64019561832.jpg

mwber4x0eku64019561832.jpg
$ ]* ~2 H; u- J( U' G$ g
                                                                               
: _6 m+ m: i9 m; H$ \" B, C                                                                                        嵌入式 C 语言知识点,动态变长数组+ T% ?, u( U8 r
                                                                               
0 E2 U' O0 m7 w" v                                                                       
0 E9 q% I- W% [! l6 b: `5 @7 F5 t                                                                + l2 x' j1 z9 L$ v1 Z
                                                        我是老温,一名热爱学习的嵌入式工程师& E# d  T1 d+ |& k! A+ s' P
关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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