電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 31|回復(fù): 0
收起左側(cè)

如何實(shí)現(xiàn)嵌入式軟硬件分層處理接口?

[復(fù)制鏈接]

455

主題

455

帖子

849

積分

二級會員

Rank: 2

積分
849
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師, F( M8 F+ V. t6 K
關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應(yīng)用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。
; F* q2 _* M/ @: b* g2 {: L1 u使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅(qū)動層。
. N9 [% s! M% P' a. l( A
8 c3 Z9 d- ~9 j- M  n二、實(shí)現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動鏈表上,在驅(qū)動層實(shí)現(xiàn)device的open、read、write等操作。當(dāng)然這樣做也有弊端,就是驅(qū)動find的時候需要遍歷一遍驅(qū)動鏈表,這樣會增加代碼運(yùn)行時間。. h9 h. ]& g$ x3 b; [) c
三、代碼實(shí)現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
1 J0 {' t  {$ i3 b2 b頭文件接口:
9 P1 W, m  m8 ~. g$ I$ \" j本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):4 s! R+ D# T2 X& e  x) Y
/*
4 L- `; {* }3 f/ E    驅(qū)動注冊
7 K' q  d8 |  F*/2 z. \4 s, E! M) W% _
int cola_device_register(cola_device_t *dev);
" A% z- \, R: ?/*
! E, o: j/ M: K9 _, F; n* x    驅(qū)動查找( O' I5 I$ A0 q) {$ R; W) u* q  Y
*/
5 }6 s& _6 ^6 B8 V, P4 D/ Zcola_device_t *cola_device_find(const char *name);
1 Z" g! S' a8 W/*
$ o+ L( {/ z4 @9 x    驅(qū)動讀
" _* D# z" l3 X: o# j+ G, p*/
+ j1 D8 J4 ?9 ?) vint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);8 D  m0 X4 [1 R' d# o
/*
; L4 _% r$ D* U8 Q: p    驅(qū)動寫4 D2 S$ o& z! @% h8 C+ s8 U. W
*/
" H, q0 e/ @+ j+ z7 ^- Rint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);  C& q  x" S0 Y; s0 C4 H+ N5 k
/*
6 Q$ ?6 H2 k  ?) D( G. u    驅(qū)動控制, G3 Y" I+ D' i6 r
*/
2 \% i8 t2 A8 \9 t) O  _' C7 u. iint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
5 G4 T6 l( C: w" |0 Q) H$ Q#ifndef _COLA_DEVICE_H_
! q4 O$ B8 U$ a, k#define _COLA_DEVICE_H_  j8 s* j# N0 G( ^) b
enum LED_state
" Y: d( u' S5 ?6 u2 W{6 H1 D( g) R2 m
    LED_OFF,
, ]) z4 H& K! z4 J    LED_ON,
$ t( R+ ?  B# T9 f' g6 k! h  W- H  J    LED_TOGGLE,
$ |1 M5 j! H; E};4 e, m' }* d8 \) T  k  U/ C
typedef struct cola_device  cola_device_t;
+ c/ S& k3 |* V, N; Gstruct cola_device_ops
/ v; {; k2 M1 y{
9 X: m9 Z0 [. L$ J4 ?0 M2 x    int(*init)(cola_device_t*dev);
5 V- H% e  n, z2 ?  J    int(*open)(cola_device_t*dev,int oflag);
' y& E" P7 t2 o* S    int(*close)(cola_device_t*dev);* w* W& {6 A3 e0 s8 D5 D& l5 C
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);; X. X3 g! k7 L( x% C' v9 p
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);  J! ?0 }  Z& T, m# x, D8 e* z
    int(*control)(cola_device_t*dev,int cmd,void*args);) A2 U1 t+ d  v
};
+ \: }( A/ Y9 u+ rstruct cola_device
1 R. F" X, }7 @5 R{; K# R& f2 C' H% n9 V) P4 V
    const char* name;  i+ `7 b, y8 ~: A5 v7 z1 E) \
    struct cola_device_ops *dops;. n( Y$ V. A& X4 S; q' L# {  r
    struct cola_device *next;: h* ]( ~. x5 h" O) o: j
};
/ w% ?, @9 c$ n3 [- j/*
" \& J5 B& y; ^- {- b0 y4 q$ h    驅(qū)動注冊
, Q. K# ]: i3 q7 S5 T*/+ o8 O# \9 q. r% j& o  z6 e
int cola_device_register(cola_device_t *dev);- z6 C: s+ y7 j& u" {  j& G
/*4 n% ?9 `; G% G
    驅(qū)動查找
5 R8 c/ n- q) n, N% t3 l: ~) P*/
5 N2 p. d, @4 u  f& R1 kcola_device_t *cola_device_find(const char *name);
* w/ m+ M- t" o- K# B( I/*; Y7 L: ^2 E8 s$ ]7 V( z3 @. x2 @
    驅(qū)動讀
- U0 w9 e# G1 t7 E3 t* n' a  F# X*/
8 s7 O; o7 g5 d1 Zint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);2 j  T! M; Z" y
/*4 w/ _" T4 r7 P4 T, X! _% W
    驅(qū)動寫4 x* e- q2 b3 o4 [& k
*/- p- Q4 ~7 ~# L! a
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);, J# c; F. F% Z1 C# Y% w% Y) i
/*
$ \& d+ v. ?0 G/ G" Q    驅(qū)動控制: t+ }, }" E+ s
*/
" y+ z' i  |- @. J( Lint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
5 {' T; M3 E$ K! [4 {* e2 A#endif 源文件cola_device.c:
7 D  r; l, c  B0 x7 S#include "cola_device.h"
2 l, d7 Q9 ?) B& J; j#include
7 q0 S4 w# k1 N" h3 z#include : K0 x9 x; T8 a3 i  p: W, k
struct cola_device *device_list = NULL;7 `* P5 _7 n3 i0 J% m4 M( I. g
/*& U. U' G( r! w- C' I) {& h
    查找任務(wù)是否存在
) ]; O& W4 p- s0 Q1 W8 r*/" E: b* B5 H, x8 C/ h' w
static bool cola_device_is_exists( cola_device_t *dev ): {) \( H1 Q# T+ c. n( w  D! t9 e
{" Q4 O; K% A$ ~* d/ `# u
    cola_device_t* cur = device_list;
) h# Y6 M" O' y* _7 F4 L6 H) U    while( cur !=NULL)# W% c  F( o4 [- A: u6 _
    {
- P8 r6 t0 ]9 j) x  s, B+ e* c        if(strcmp(cur->name,dev->name)==0)& N- Q' X+ W, t
        {
( i% I* d1 J. `3 y0 v4 I4 R            return true;2 w% `4 w! d/ L6 {: V1 i
        }$ d  d2 ~  J1 l  \# L
        cur = cur->next;
' o& A" l) g& T3 |! f: m    }  P0 e" E7 G7 t
    return false;
: N9 M3 \/ e( O6 d}
% V  x8 u8 E2 U; D, l0 Nstatic int device_list_inster(cola_device_t *dev)
8 W4 ?: P9 d( h0 f$ z7 \{
% \+ ^9 x$ M: z( ?    cola_device_t *cur = device_list;0 {( ~2 i( y* }7 R
    if(NULL== device_list)7 @$ r- s: f. G! I8 A
    {
" N# }6 E8 R3 n  O. @. R- x$ T        device_list = dev;5 Q6 d) z7 k" \9 ^9 a. q% v
        dev->next   = NULL;
; Z& J3 R( B) B* A: ?( n5 z    }0 v$ z, J! n) C/ `8 n
    else9 H7 W$ e# K* |8 p9 A0 Q3 _
    {
- L% r5 M0 O1 N9 p8 Z6 v        while(NULL!= cur->next). d9 ]. p5 ]# i" s1 [
        {1 _4 {" }* e- E- K. ~6 b9 a
            cur = cur->next;
5 w% |3 T! ^" c/ P1 G: Z        }; X/ h9 h4 j; c- j, J0 c8 }
        cur->next = dev;( f+ Q' ~+ [2 L: k: |4 g+ C
        dev->next = NULL;
  d: k, F% e/ S' a    }
1 @9 j/ V* ?/ V) C  i1 J    return 1;( ]" W9 G# J" }; {1 I$ j
}
. Q& @  q# a4 h- _. J/*. s1 P% l) j) u8 u  O
    驅(qū)動注冊4 ^$ v  N- X6 k; t5 I, [" Z
*/
, s5 L' b7 C" B. z. X2 Uint cola_device_register(cola_device_t *dev)
$ X- ?" ~# \0 C4 l{$ F# n8 W1 `6 V3 g* K: c6 E  W
    if((NULL== dev)||(cola_device_is_exists(dev)))4 T9 z+ P1 {$ R/ r( f0 Q$ t
    {/ d. G" a+ G; n' d. O
        return 0;0 |& d% Q8 U. d( [, k! @
    }
9 ~4 Z& ?$ D: R, ]( y    if((NULL== dev->name)||(NULL== dev->dops))
" I9 ^% S! D' v$ V2 \. Z9 d    {
0 q* ^  I5 Y$ Q        return 0;
& j# G) M9 L0 H' k( S    }
, X( V1 R$ U+ N4 N7 [    return device_list_inster(dev);
/ j0 j( ~, g( x8 g3 i  q}/ P( h* B7 R3 G2 R0 y" u
/*6 ^% U) F5 h6 d: U2 d
    驅(qū)動查找
) H  {/ [' [/ A9 D- ~3 o*/
, U" K3 {  O/ i4 `% P' ?) Ocola_device_t *cola_device_find(const char *name)7 |! a4 N" k% A& K
{% w2 N0 V/ B) |' D& d4 a
    cola_device_t* cur = device_list;
" j  H3 F# q5 v3 o  ~    while( cur !=NULL)
4 r2 \1 Q- q% n$ n    {
$ ]* r& A$ P3 ]( l& s! v7 u% s# s        if(strcmp(cur->name,name)==0)2 ^5 y+ v8 j; u9 Z* g" v2 z2 h5 k
        {
, M! f: v. R, d3 M3 `, a8 ~            return cur;
% s2 v2 `1 P  B0 E* h; q        }" D0 `! F+ N; o
        cur = cur->next;
  q6 Q; r! q) ^# {) A1 m. |# L    }
* Q/ O1 e% `3 {3 |    return NULL;
" c* \5 g6 n  f6 Z}6 Z: j/ x3 O  p
/*  d( k4 s5 j2 O- q& p
    驅(qū)動讀' g9 Z; i; q% \6 G
*/; i" D5 u  j7 v
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)  X# m( I/ }5 h6 `" ^
{
2 K0 `0 A+ Y) z, A2 L! z    if(dev)5 v+ c) s- x: I4 Q3 r
    {
8 Q6 z* B- @, ~# y# A        if(dev->dops->read)
. h7 U0 T, }+ c  j( |* B  g, I$ _        {
* n( @  R* B: J. R' B            return dev->dops->read(dev, pos, buffer, size);
( `, B7 X# {  T( F        }* S# g6 u/ F, d/ a+ O
    }
! i8 V$ x* y+ o    return 0;
. f) A# a/ n5 S}/ q" v& L2 ^5 A  ~% P8 v2 W! q
/*4 d- p, v8 ?9 \* `& `
    驅(qū)動寫
3 g) l0 b6 M. _9 V; h- k, j1 c*/! L$ u4 o  y( d8 A6 y
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)( {' d0 T- s: y: W
{
# ]: ~0 a' w7 M. L' h3 X    if(dev)% i) @% S0 J8 j. w+ ]
    {
' c$ s6 R* |& f) ?9 f( \  B        if(dev->dops->write)
* C8 D: w) ]. `        {% s- b6 B7 M1 M/ A( [" M6 a- {
            return dev->dops->write(dev, pos, buffer, size);- `. H6 k2 o! F& j9 d
        }
, ^4 R* E1 H; c5 z: o& _% x( p    }  t) n2 G3 [$ J7 c4 h: E% Y' r
    return 0;
9 U: W3 v/ o6 S& M4 r}
8 V7 m+ n1 j* o9 w# f! e/*$ V4 D0 a; Z) H+ `1 \0 S) m
    驅(qū)動控制; R& |; G1 f7 F' o, ?4 n/ H8 b* r1 V
*/
) C, M- c1 W5 w. q, N% Eint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
/ O/ }* g, e% Q3 f! H{
4 C& k( c, ^! c# k8 z  r    if(dev)
0 J* z" G( F+ P( S6 e! C0 k# s    {
/ h7 q$ U) p  N, M# Z2 `: z7 r        if(dev->dops->control), v. {4 y7 B/ |
        {
% H4 F+ ^: Y& V+ O! m6 M            return dev->dops->control(dev, cmd, arg);
' z( i0 ?! P# D6 g6 g        }
# k3 T) c, \6 [4 ~    }
; I8 l: h% r9 H' g' ?3 H    return 0;1 Y/ G/ y$ h: y+ W3 q- L$ i; y2 Y
}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。/ F0 ^& [6 a8 ]' `- I. F6 t
#include "stm32f0xx.h"3 k; g* }5 Y- e4 k* m, L
#include "led.h"
7 v2 z6 E5 `: X" k3 v#include "cola_device.h"0 x6 H3 ~! s( w+ }5 C0 X  g; }5 x# m
#define PORT_GREEN_LED                 GPIOC                   0 H' o& y6 e; V+ V0 r
#define PIN_GREENLED                   GPIO_Pin_13              2 _8 }0 K3 W0 A  J1 F; G& t; G  E
/* LED亮、滅、變化 */" f3 b& T- L+ s) q
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)$ m2 h; u' m) N
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)& M5 m; ^2 T* c5 \* P8 M. X
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)" C0 ?5 O& {3 z2 ~
static cola_device_t led_dev;1 |+ L! B- W- a' f# Q, O
static void led_gpio_init(void)
4 J; I6 l4 O' H{
  r/ L* H" _) B8 E' o' [' ^4 c    GPIO_InitTypeDef GPIO_InitStructure;
4 `! R& W) t5 o# C1 q    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);& E! F) a4 L- R: F2 J, M
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;2 X+ f* N1 k5 r) Y+ D
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
1 \( W3 q% S, T* F+ q8 N& w    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
* V/ p5 v1 [4 \2 z1 D    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  s, ?* m, X: \  g2 T8 r
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;* |: h  `0 W+ X/ W+ T9 m; f
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
% M, K) K, V* v3 Y6 @    LED_GREEN_OFF;
4 \1 L. X2 B5 q& U+ c- f+ n% _}9 S6 e' K: J, O$ J+ c( b! A9 v
1 ~* V$ z7 T( f" w7 x+ x& N, H
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
6 f1 Q  N* h( s/ s{# V- w5 S+ Q9 }3 E8 n
    if(LED_TOGGLE == cmd)
& {! i+ R% `7 y7 F- A6 S    {
8 o& \$ `3 \/ q" U        LED_GREEN_TOGGLE;  B( P& V1 ]( E  y  [1 ~
    }
' z' E) j+ I: \$ R    else1 W0 m' {# k8 L" p' `
    {
' T& W# J" g" o! @" S# d    }# V4 I0 `, Z" c# u) O+ h
    return 1;
: V" H$ @$ Z7 x}5 U$ n$ x5 H" r; ^- N) D; s
static struct cola_device_ops ops =
0 F! p. g/ j2 B. X{) I" p; Z' @1 U& f
.control = led_ctrl,( M3 a* @! }7 b$ {4 `7 S
};" K: `. v& ]! _% _3 a- Q
void led_register(void)
, l9 m9 R7 o6 Z' {2 c{1 D$ ~8 h( z+ x% D0 T7 K, r
    led_gpio_init();. {+ y; a! J. a* |1 Q1 _; J
    led_dev.dops =&ops;
& Y, i" W( _. A$ s9 J    led_dev.name ="led";& W2 M! S& P2 q: f/ @/ E
    cola_device_register(&led_dev);& X$ ]0 x1 E. g/ j. N6 B3 l9 r
}應(yīng)用層app代碼:: @9 [8 p0 Y' p- J1 g
#include
$ c3 [% Y" r; R- k" X#include "app.h"
$ D& i; a8 r8 p0 p* |  o/ u#include "config.h"  z( M3 i  O6 ^& y& M# C; j
#include "cola_device.h"
6 j9 F2 {& k3 r  _. F#include "cola_os.h"
$ @! ~4 ]9 W% W! f. Istatic task_t timer_500ms;( }3 |7 ~/ y$ I3 e6 }
static cola_device_t*app_led_dev;
' T' b1 U; u  n5 E1 A//led每500ms狀態(tài)改變一次
/ L; M+ S0 k$ J5 J4 B2 x. xstatic void timer_500ms_cb(uint32_t event)
! S7 ~1 w8 i1 w5 C7 F( l{
. N" ?- G' l3 {8 Y: i    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
4 r% i! y" U! m8 m% G: G0 U}
; {7 Z, r& @0 O4 J  a) [void app_init(void)
3 N& `; V, {+ q% C% Z{) c2 ~$ X+ ?1 ]3 l/ K, G' |
    app_led_dev = cola_device_find("led");
/ R! A0 i! w, f2 ^    assert(app_led_dev);
9 x- q' i4 |5 K, c9 o6 C3 C    cola_timer_create(&timer_500ms,timer_500ms_cb);2 z: H8 f" O7 g& H
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
! e! K# A& \& c. s6 n: J}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。0 s5 L. ~1 g. W9 I. ^6 |; a& ]; N
四、代碼下載鏈接https://gitee.com/schuck/cola_os/ O/ K  A& U! K: j0 M) }/ D+ n
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722* n- X' n/ A: c1 T% U$ M# Q
-END-! Y9 f" g" f' W
往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀
) D% h9 r4 S. |* h- x: r: }% |& z                                                       
, X8 o& n* N7 b7 Z7 C/ r1 e                                                                3 d0 {4 ^. x2 t# I/ F5 V* F6 [" U
                                                                        7 A, a# z% U- J7 r# a
                                                                               
, M& j3 O4 U. Z+ Y % S% |$ A* {# b# ^4 A7 O
                                                                               
2 d1 w9 j  N3 M3 l/ r7 c5 J: s1 R                                                                                        嵌入式 C 語言的自我修養(yǎng)+ }8 @# `) x& |- b9 r; }
                                                       
, [1 [+ d% B) b( G8 \  m                                                               
, K' I' w( x4 h# X9 q9 ?                                                                       
' A* T0 M3 ^  Z4 k$ |) H! d) g                                                                               
' Y8 X. P9 `) q& O  k! m
2 J! v4 A8 f% Q0 z# m; ?                                                                               
* |. v" R- t* E; v9 q: X, ~                                                                                        被 char 類型的變量坑慘了!8 Z8 L7 ], \1 D5 u
                                                                4 I% l' d" j" m, T9 _% V2 Y: w
                                                                       
+ z/ o, J8 r9 a; x7 h! G                                                                                $ h8 i& _7 h. Y3 K- y& R6 A
) K$ S% n0 ?* l" u: I. T8 h
                                                                                ; @4 z. a" t$ K# t8 _
                                                                                        嵌入式 C 語言知識點(diǎn),動態(tài)變長數(shù)組
. d) Y8 s5 g. o6 T) E% B) }3 n                                                                                2 W8 X4 X5 {" q2 I4 c. b1 i$ [
                                                                       
. H- L3 Y( l) u$ Q( l7 y: }; C                                                                & h8 c! a% {3 X$ b9 P. b
                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師. b4 f) U! S( J: \' N0 w
關(guān)注我,一起變得更加優(yōu)秀!

發(fā)表回復(fù)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表