电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师3 Y6 u1 |$ g5 l' D4 u
关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
: ]8 t3 \+ b; |8 y3 Z使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。
: g$ k# d( J& Z, y7 G/ L# R, v

tl0wljn5hd464020406145.png

tl0wljn5hd464020406145.png

  E2 |  E$ G/ o. w. j1 ?二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。
! q" |% f) B3 [- N三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread
6 e  g! I7 g! W+ J. E头文件接口:# [1 n( q9 E  a. [' g1 f1 ~
本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
+ a/ r! G# N$ Q% U" ]8 [) G/*) W; b, a1 j: K9 u
    驱动注册
* O7 f' b2 u" f4 l*/0 M1 _, @- j$ u5 d& w
int cola_device_register(cola_device_t *dev);
, ?1 ?& z* Y% G* `9 b/*
% l& p$ p. J5 v* o5 h' k8 ^: |( `    驱动查找* B/ T3 H8 {6 F% L: s
*/
# |& o1 {. P0 w' D) L6 x0 Jcola_device_t *cola_device_find(const char *name);
5 N3 ^" o& C" m+ h# R" ^+ w, P/*
+ k' |( S3 a8 j    驱动读
) b+ Y/ y7 h; a% z0 @! q*/
4 m9 N" p9 O: ?: j2 \4 Zint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);6 M0 u! G$ ^/ i- b* u4 K) c8 n
/*1 G' I6 F' ?5 k# }* Y# c
    驱动写
3 f/ q7 p' E2 m3 g# z  x2 [*/
  B' ]( G- h  f: @2 W, ^int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);" I' c: u$ A0 T( |5 y% i
/*. w( G+ k. x& `- }% r/ R5 a
    驱动控制
, |: Q- D  T' q7 S8 c*/
9 f: H& V! o% B* @8 |/ H8 Dint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:2 s$ J6 y2 o( x! l5 @9 s
#ifndef _COLA_DEVICE_H_& g. k( s4 y; ~+ y' k' Z! g
#define _COLA_DEVICE_H_; E( v" R2 _/ c* i, H' a; j3 u
enum LED_state
: Y9 M) Q5 a) {+ v{
: V/ |: b  T) \    LED_OFF,
6 r3 M1 u$ m9 @5 v$ [0 P    LED_ON,
" n! T4 \. j0 ?/ A& V4 R& a' @. d    LED_TOGGLE," Z5 v" v  @" }
};7 y1 B/ p  L7 P5 j) p; }0 L. P7 |& K
typedef struct cola_device  cola_device_t;- n8 o% x8 P( q
struct cola_device_ops" \( U% r5 F1 T7 J
{: A% a! n4 H  ~) }% ?5 S' @" U& N
    int(*init)(cola_device_t*dev);
/ x" T% j" h% T! A4 i    int(*open)(cola_device_t*dev,int oflag);
( |& x4 [8 n% J" }    int(*close)(cola_device_t*dev);
1 R$ ^; V# p! N. F) _8 c    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
- y/ D' C2 X3 g9 k& ]7 I% u    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
7 O; ~8 `. |8 @# q" o& f- ], F    int(*control)(cola_device_t*dev,int cmd,void*args);! ?3 Q% p% `+ b1 F( w$ D' E6 Z0 f
};
6 Z# g) }* g1 t1 [- r: Lstruct cola_device
" O; a! W; `4 q2 Z2 f/ ~- Y- W{
% y6 \5 y& ^6 l/ e- c    const char* name;
) I1 N6 N6 A  H( m3 U- }    struct cola_device_ops *dops;
& \9 D  v; x( g8 O# ^    struct cola_device *next;! z) ~+ K" _, D# {
};% M: \; j, V: r/ I: R9 v" k
/*, k% K% J& @9 n2 i
    驱动注册
2 T9 T& X; L  I- F*/* V0 P6 F- P4 d3 R2 `* z
int cola_device_register(cola_device_t *dev);& L2 u5 J9 k& W; B6 ~( K3 d
/*
/ p& X3 F, O9 T# o: V6 o    驱动查找
: v+ A. u, u3 u- W$ _*/2 q. T# }6 @+ t/ }) T
cola_device_t *cola_device_find(const char *name);
% c) v5 d4 T6 }! O/*
, S: D6 \- k' ^! X" W1 _( q    驱动读
3 f" h4 A( c! V3 U# l) ]*/
3 }/ m" E) P" w# t2 Rint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
' ?$ [1 L0 {3 I4 W; A* m& ]0 {+ ?/*. ?, F0 t$ n( q0 ~5 z( e! m, G
    驱动写
5 p( `1 p' p: R7 @5 p9 y*/
- t5 @% N3 G! q+ p+ O+ {" t( eint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
3 y/ L3 H! w: t# o. g$ r/*( t) |7 `" u9 v$ b6 ?+ V. W5 Q
    驱动控制
' G( V% [4 ^$ C" _6 V+ t9 A6 a*/9 A' `$ ]/ C  e5 c' ~
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);9 p: Z8 Y' K5 u
#endif 源文件cola_device.c:
% i/ c$ }3 Z) A4 S#include "cola_device.h"
& v% F4 m! s6 c, F3 q7 f#include * S$ G) X) _# p5 R5 F$ ]
#include
; f$ `) R! K  ^0 \9 bstruct cola_device *device_list = NULL;8 j; X0 j. U- j$ W" L+ Q2 K
/*( @8 O! m; _; M# {
    查找任务是否存在
3 r0 U; Z" H8 B/ t% [*/
+ e- i; |1 o! Istatic bool cola_device_is_exists( cola_device_t *dev )
7 v) e7 W% ^# }/ s* J{+ {2 W. |8 A$ m
    cola_device_t* cur = device_list;" v# m8 j' q4 C# W; Y
    while( cur !=NULL)# E; N6 f) D5 E) S. _3 n2 i! D
    {5 t" V/ l0 ~8 a+ t0 ]. }2 C# M
        if(strcmp(cur->name,dev->name)==0)
4 H' P6 E* P3 p3 B" H# c2 G  l        {
0 a% m& a! a7 Q) Y2 y) H5 s5 s            return true;7 G) \; N* J; t7 n" g& b& G
        }
# N' Z7 z& k6 B# _* S! X6 [) P2 y        cur = cur->next;" R' ~8 b: d+ d( S8 q2 C: B
    }0 Q+ \5 C3 l: j7 E9 L$ \1 K
    return false;, ~/ i* @% S5 ]$ t* r, g& K$ z
}' Y2 `1 _. D$ D
static int device_list_inster(cola_device_t *dev)) U( R+ r6 {# R' c9 B: H  A* b% x$ V
{4 v! I8 ?3 T' _  L
    cola_device_t *cur = device_list;- ^: }- B# b' D8 o1 f5 u6 {
    if(NULL== device_list)
1 j3 G5 b3 k3 g1 U! e; k, Q7 }% c    {: C% X4 A2 r7 E- z- K
        device_list = dev;
, k, d9 A6 s5 d1 M) @: E8 \! ^( s        dev->next   = NULL;
7 O& {7 N" {5 j2 f- P7 U5 m! H    }
% A' p! D5 l" y2 h. h* l* r0 v    else; E# q/ G, o# b/ H- `
    {1 {. F8 k# _6 R) Y0 i
        while(NULL!= cur->next)6 E0 S# W# G; x# q2 H' c% U
        {# @# r/ J+ h* _
            cur = cur->next;5 K) g! p8 J5 k8 B& b: D$ q" y  p
        }
6 {) t% D# R+ c8 \4 i. h        cur->next = dev;: t4 @# [% `8 u
        dev->next = NULL;/ q( z3 ?$ ?& `( C
    }
- s6 }5 V' D( w  t6 o$ H    return 1;/ d% C5 A. B3 `2 f- X+ p
}
" N1 Z+ h$ Z( e( ]- {% x2 J  Q/** u7 Q" s  W; P# d6 S, x' G
    驱动注册5 t2 S& }: E5 s' H: y# U9 }* P& s
*/
$ I. ?  J* K5 @" \2 _" K2 }int cola_device_register(cola_device_t *dev)! B& H6 N2 n( r  n3 e( V( g
{& h4 o3 e3 ^% C2 b/ o( Z" T! g
    if((NULL== dev)||(cola_device_is_exists(dev)))
# P  {% x) P; a2 b5 G8 Q+ ?6 J/ u    {4 n# U2 Y4 e# w( y( G1 l0 {
        return 0;
7 k! X8 k  r( h4 S& X" G    }! v1 |9 a$ ?3 w6 o
    if((NULL== dev->name)||(NULL== dev->dops))
; ]3 k% ~8 r' V) z' m    {
7 q* V7 i, `& x8 I. F- r# e        return 0;
; m3 m5 M( i* {7 q9 b    }( T! ~. R( {/ I& ]5 m* o, S
    return device_list_inster(dev);
% Q$ n4 f" L7 j}
) {' V0 O( v3 g9 B% B) K/*
( `  a* w; E3 m, J    驱动查找
& i6 x/ z2 E3 C! J; f*/& `' a; C+ A1 }( Y% V; [) ^
cola_device_t *cola_device_find(const char *name)) e& ?- m$ G; D' p3 n  w
{7 h4 [+ N7 D4 f* q6 U
    cola_device_t* cur = device_list;
- U# F8 H8 n1 a% Z; _    while( cur !=NULL)$ j1 }; ]( d  r
    {
4 S" g2 Q) Z' n$ W! l5 U7 I        if(strcmp(cur->name,name)==0)
/ i7 A: y: H! D8 t4 u        {! ^- |& D! b, i/ d/ v
            return cur;
3 H1 e  |) q( b, \/ ]4 d/ y) W, F        }
1 o2 R* m) e/ }        cur = cur->next;9 c" r1 I5 {# z: o  x# [5 B1 c
    }
! m+ p7 I( T* Q9 L' z6 l, \    return NULL;
; ~( [  L1 j! X}
; F- n2 b) ^0 i" S2 m3 t! _/*
0 _& d7 f- F3 W$ s    驱动读- ?, T/ s- }1 H, w
*// a& f' j5 p9 H9 I- o) Q. n5 H% m
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
4 k. p8 I% W. H: p+ z* w{
0 ]3 X* _1 W( U9 A' H( s; K$ m    if(dev)
* g3 o( I( U. Q( c5 |    {% L- z- \" Q, T% v' L) p
        if(dev->dops->read)
# `  A6 {+ M4 e0 H# s1 C5 f        {
$ `4 Z! W5 O0 @5 R4 m            return dev->dops->read(dev, pos, buffer, size);
( T* _+ }; F$ L/ R        }% |! k' L: P5 z
    }
7 J/ [1 k* V( V# B: q    return 0;  B+ J& h6 T$ L; F& f" C8 y
}
8 X* o/ }& ~' x5 g9 j/*
) Y: @, U) t& S4 f0 V    驱动写, ^3 I$ _! u$ k7 a
*/
2 o8 B$ X" J9 d9 E" p2 q/ \% d1 Kint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
( A; Y4 z- v% W* \{
2 T# N! F; N! Y8 ]$ |, ~& C    if(dev)% b1 X0 Z" T: \6 {" z) L' s' P
    {& |9 K5 x5 M, E9 F( j
        if(dev->dops->write)
* t2 G6 Q4 H; ?$ b        {
& F& S$ u, P, j: U            return dev->dops->write(dev, pos, buffer, size);9 k+ K$ V+ Q3 \+ d/ n
        }
- }) K! n2 S# {+ x0 ~& i! _6 o    }
" b. y9 J/ h' s8 H4 O" O    return 0;; G9 G6 }- T. T; k7 X9 u! D
}& {' R, L( u2 E" C0 J% n/ c
/*
4 u. F3 l- V  e    驱动控制. b/ N; i8 E$ _( s8 a* x
*/
4 S# n2 T+ ^( u+ kint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)+ r, d8 R' N/ l
{/ s, u1 B* X, r5 Z6 A8 Y( ]) e
    if(dev)4 B; ?6 z. w% L8 |  v
    {
) k( t* D4 s  D* v2 `' a" [: w6 S        if(dev->dops->control)- n  _$ |" Q' V2 Y' C
        {# ~' ^/ l( x1 Y+ d' `+ F
            return dev->dops->control(dev, cmd, arg);. {: ^! t" `1 D6 Q2 m5 m
        }
' S" |; `  I/ z! I( ]* W# `5 L, i    }
  ~- H1 b% G. E  b    return 0;5 g: d! U7 w; f" v9 y. N0 S5 v
}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。
: z4 I8 F, ]* b! H3 N4 W#include "stm32f0xx.h"* q4 i5 m4 s  }
#include "led.h"
* F$ H% @- T/ W$ ?( @7 ^3 v) J, R# {#include "cola_device.h"
' `$ p% c% A# f#define PORT_GREEN_LED                 GPIOC                  
8 z( y  ^4 F8 C& C4 Y: v" v#define PIN_GREENLED                   GPIO_Pin_13              
& |9 n: z6 R) A- u" A# r5 }0 D/* LED亮、灭、变化 */* y( [1 U& D7 |0 u; L
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
& I/ f" \: ~( j#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
4 ~, u# O/ n& o$ _( k1 I, r#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)8 R& L2 ~3 N! F! v& J1 l
static cola_device_t led_dev;3 e  ?2 n1 b6 ?: b4 Q
static void led_gpio_init(void)
9 d  B0 ~0 |* [; J& O$ W9 v{: z8 ]+ V% F8 O
    GPIO_InitTypeDef GPIO_InitStructure;+ z# o1 a7 I+ l5 D
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);$ p0 D6 X, F# `
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
- A6 G  A0 _) v  L( s    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
4 R$ [9 o- w" H: Y3 ]    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;# u+ w+ g' p! m" b6 D; A
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
1 c# `/ x+ h9 Z3 p6 C    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;7 h' H8 D! G8 f+ [. E
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);$ R8 S3 ]+ C+ F. S9 F7 o5 M: v/ c
    LED_GREEN_OFF;8 l' h, ~: ~" I: y7 N  @1 ]0 ^
}, r& G9 k; o5 @' X! s
! t( I" W- N; x. S( k$ R1 O$ ^
static int led_ctrl(cola_device_t *dev, int cmd, void *args)+ _2 z: Q% k2 R6 S7 i3 ^
{  s( S( _7 L5 _8 b8 F$ f0 G( k$ \/ Q9 k
    if(LED_TOGGLE == cmd)) L$ |4 [, v6 V( m9 [
    {5 E6 [6 ]& l- a$ O: w8 D
        LED_GREEN_TOGGLE;* e' Q  C6 n! Z" u  G
    }, j9 z  Y. v1 z3 d9 }' @- _
    else
: F2 s1 Q" `& g' k' B+ |    {2 F! B$ t3 H! S- V3 O  n
    }
: X6 d# M# |4 f3 j2 v    return 1;3 a/ r  t! i1 d/ M' b) v
}
! g, o. V. |4 n% ?0 ystatic struct cola_device_ops ops =
( Q/ p3 H/ I9 `! q{9 ~/ V2 Y0 }# g7 V; Y( l
.control = led_ctrl,
8 r* Y! n, Z( @5 k( D};' s8 Y8 Y% R9 v8 K
void led_register(void)/ C( G# d9 L0 F/ |/ O  g) Q
{" T& ^/ w3 ?3 g8 o/ {/ O2 a- B
    led_gpio_init();
: W/ `8 T! B. I/ r2 ?    led_dev.dops =&ops;7 P/ R1 R3 D" U* w8 J9 {. P) G
    led_dev.name ="led";+ U6 v* B; @. i: P0 j) b
    cola_device_register(&led_dev);% P: }; V4 V1 Q' e4 M: Q& V
}应用层app代码:
7 X* h1 ]4 u* W2 E9 X#include
" e: y/ _0 T6 b* r& g#include "app.h"
% W9 ?' s$ |2 ~6 y: e1 G5 Z8 V4 K# c& G#include "config.h"4 o4 q3 R, n- f+ V* O7 w' Q8 E
#include "cola_device.h"1 W9 k" v# ]8 c! b% M* b  z3 G/ P
#include "cola_os.h"
4 d0 G( E% f) B1 c5 \& ustatic task_t timer_500ms;
2 j. h( o0 f; \$ J7 X" O1 A/ b2 Astatic cola_device_t*app_led_dev;
: W* C, N2 W+ X//led每500ms状态改变一次) T8 N( }+ @5 B
static void timer_500ms_cb(uint32_t event)
1 c3 J  c8 u) W; u4 A. i{" a2 b$ l% F. K3 `0 k
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);: o2 _+ L3 H% D* u; J; L1 c. n
}
, J# @$ y0 w5 t/ vvoid app_init(void)
1 L! V. L3 D2 o; X# D3 i{
7 c" g& d* _2 m# h; `  {3 E5 S' v    app_led_dev = cola_device_find("led");- M# R* E& n' g5 u
    assert(app_led_dev);
- |/ s6 R6 C& [% e/ a) ^: U    cola_timer_create(&timer_500ms,timer_500ms_cb);
1 g) a9 ~/ K  s    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
2 z9 J/ G8 {" B}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。9 l& X; c5 u! @
四、代码下载链接https://gitee.com/schuck/cola_os/ Y1 z4 |7 I5 x7 h1 J( m
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722$ n. @6 O0 b2 K1 K
-END-* R) \' M, T! o7 |
往期推荐:点击图片即可跳转阅读8 @0 D% ]; s0 g6 L: v( o
                                                        0 B% G3 i! J/ c+ U; I
                                                               
: d# P( r/ C5 |0 p- i. G- m                                                                       
1 ^' ^7 K# |2 H" H                                                                                & V: M; n" D" a

y0jnszoy0hn64020406245.jpg

y0jnszoy0hn64020406245.jpg

% S' d  H9 {* L4 ^/ x6 g                                                                                4 N  X* v# A: j7 l
                                                                                        嵌入式 C 语言的自我修养; h+ [2 T6 n' K+ [5 M6 r
                                                       
! E) D! b1 [7 s, q% D                                                                4 p( M' G! ^# O: ?
                                                                       
2 e5 D) C$ g8 L6 K                                                                               
4 A7 |' N; B* [! w: n1 v6 Q+ _

43r33df43ip64020406345.jpg

43r33df43ip64020406345.jpg

; d2 m: `( h! g% S- _0 L( m: X1 V                                                                                5 H% l: E/ E, n  c" V
                                                                                        被 char 类型的变量坑惨了!- U& \- y2 O( T
                                                                / ]  u/ T" ~' E
                                                                        * f  `: k$ G3 o! u2 [0 [; @, u
                                                                                ) g$ p' Q# f* ]4 @9 }! j

vcbyugpp1n064020406445.jpg

vcbyugpp1n064020406445.jpg
% I9 }% d6 |" H
                                                                                1 M0 h3 g7 ^2 ~5 R/ g
                                                                                        嵌入式 C 语言知识点,动态变长数组' j5 o! v9 b1 A# i( S* ]
                                                                               
# U- L, p# C1 W8 s" l) M                                                                       
2 {$ m  K! B, y% r" H' A                                                               
9 P3 K! v. R  ^3 ~                                                        我是老温,一名热爱学习的嵌入式工程师
" V7 H8 \0 E( h  f; w关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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