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

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

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

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

[復(fù)制鏈接]

455

主題

455

帖子

849

積分

二級會員

Rank: 2

積分
849
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
) B' V* W) M, I5 O2 J) |- R關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應(yīng)用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。
' g: p3 J7 m: q9 j2 o( l  O使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅(qū)動層。6 _# u4 I! }6 S9 a. ]0 h
2 w+ A2 Q, [4 }! a7 B( x. \
二、實現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動鏈表上,在驅(qū)動層實現(xiàn)device的open、read、write等操作。當然這樣做也有弊端,就是驅(qū)動find的時候需要遍歷一遍驅(qū)動鏈表,這樣會增加代碼運行時間。3 _7 @- u& o  Y
三、代碼實現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
/ |& L8 A; ]( ~, R' z頭文件接口:- ^$ X/ O- q" P% G
本次只實現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實現(xiàn):
. O1 y  m9 p& b8 n* A/*
! J1 |! ?, s% Q$ r! j    驅(qū)動注冊
; B. A, n. C) n% |; ?  t*/* f3 }1 y1 k4 ~" [
int cola_device_register(cola_device_t *dev);% R" V7 @5 h% ^, h1 y
/*& a, Q; O. p% E5 H: Q) _# D
    驅(qū)動查找' M5 S) Y) u& L/ ?% k, I3 H
*/
. A4 w! m5 x" @; k1 e0 u$ scola_device_t *cola_device_find(const char *name);! L8 g, j* g! Y/ [" @* n
/*
- G& q; U3 Y4 G    驅(qū)動讀, K* @) f2 T( _- \2 P0 L$ H
*/" f) J' e+ i1 v4 D. }6 N
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);5 l1 z& r. V; \/ w4 A! q
/*
4 v, M6 I) e" a- y    驅(qū)動寫* ^# a3 U) D, ~( r! a/ C) l
*/
. ~7 f" a7 \2 uint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
/ Z* l9 [; u  e2 C7 f& [2 [7 f/*
& z7 y/ R0 m- Q- P0 ^) P: T' K    驅(qū)動控制
: {4 t6 O% k% [/ k* d' e3 U*/" Y6 _, R; s3 t! r8 L2 v
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:  v: F! D5 D' H+ z' ~5 `
#ifndef _COLA_DEVICE_H_
. u/ P) X! V4 H#define _COLA_DEVICE_H_
, e3 p8 j, i8 D+ ]; p+ Benum LED_state
: F9 R* F# b9 D{
: c  h' Y* s9 J/ v$ ]    LED_OFF,
$ C: z: i1 t$ i! b% `+ y    LED_ON,( N) K' [8 M4 [5 o, I9 v
    LED_TOGGLE,, P. ?" G6 `8 [1 v, v
};
- I- \* o. q5 j* gtypedef struct cola_device  cola_device_t;' U; _) Y1 t6 s9 R2 p7 R- @
struct cola_device_ops
: _8 a" J7 Z% A3 j4 E# ^{7 j3 n# @1 B  E, n
    int(*init)(cola_device_t*dev);$ y6 G. j/ v8 d9 x
    int(*open)(cola_device_t*dev,int oflag);( L* G, Q: J  \! U) r) t. |
    int(*close)(cola_device_t*dev);
  }( W5 F9 T9 Z( o/ M! E    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
$ ~: z4 Z/ c) d# {/ l1 n) H9 t    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
' b* s# Z" D* K% ?# i8 Q    int(*control)(cola_device_t*dev,int cmd,void*args);1 h$ E1 H: `  {" Z
};
2 N1 Z6 v3 l0 K' ^struct cola_device: _+ E' o8 A; @. Y8 `! T- }
{
$ e4 K' b1 @. m    const char* name;& W. L/ Z8 i' f$ Z2 ~. S
    struct cola_device_ops *dops;8 |' |$ K4 c; S+ M
    struct cola_device *next;
. E; u& g1 C7 p" Y* S# e$ [};
3 N: O3 w: B) g8 ]+ T/*
, u; q2 V+ u0 V. k. g4 o9 ]    驅(qū)動注冊2 w- ]+ Y& D! v
*/
, S  t* g  t( c: Dint cola_device_register(cola_device_t *dev);
7 P5 M* T( s1 ?' |/*
4 `0 d" Y. U! ]    驅(qū)動查找, ?0 L" d- @: G/ J, _, D
*/
6 ?# l0 L# B/ hcola_device_t *cola_device_find(const char *name);
$ M' A0 p  l$ e- G! S; ?' W4 S# Z/*
% G3 I2 z! P% g/ ~2 `    驅(qū)動讀/ Z5 s+ V7 \$ B2 {; K
*/7 W. _1 e* Z2 V: X" C# k
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
( J5 |5 E  w0 _& n' p' `0 G# t1 X/*; J- f; F" l% }2 F- G
    驅(qū)動寫$ ]# e2 }1 i( [/ s2 i, s2 D
*/
$ T( I/ n. V2 l# m- S& J* eint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
( K3 C7 l! y" K/*% G6 i& E7 r& u4 a# a
    驅(qū)動控制5 R4 y& Q7 S  P% r7 {
*/2 \% l* }5 o% z: r  @7 B! j# q
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);" A8 u1 v- l9 w1 M$ y, j: R' }
#endif 源文件cola_device.c:
) q; ?& ]& Y/ k* e8 b* z#include "cola_device.h"
+ i# C8 d5 n/ D. ?# \/ ?+ l; I#include 1 T, q2 f+ v) x% U5 a
#include
% a7 c3 ~  J, O' C) t% R0 vstruct cola_device *device_list = NULL;& i; b! i/ x" d2 C
/*
/ v+ u. M- ~& p! E- Z    查找任務(wù)是否存在
: I! A9 ~, Q9 k*/4 {  `2 F# k0 B+ J: Z
static bool cola_device_is_exists( cola_device_t *dev ), ]6 o% ~0 I* i$ x) U# Z8 z
{0 u" l# s0 L2 Y8 d4 r( Y% b
    cola_device_t* cur = device_list;/ e2 r) v% i: I$ ?
    while( cur !=NULL)5 z9 V; k" V. t
    {
* R) t# P, u0 B3 A% x8 d        if(strcmp(cur->name,dev->name)==0)( P, o8 I, E6 A' L
        {! l" V  o- X  w  g: ]2 e+ Z) l
            return true;" o  b* Q* B& O4 q. U: f
        }/ d4 k- r5 Y# }* e8 r
        cur = cur->next;/ V5 ?2 m# v6 _, N4 d* M1 Y
    }7 [  x* j3 w- ?( a! E5 f
    return false;: j* o$ S5 @3 W( K, Y
}
, q7 n- k, o3 ]static int device_list_inster(cola_device_t *dev)
, U+ e& ?. {  W& q& Q{# h# N8 Y( ]! R( i( ~& {  P2 i! }; T
    cola_device_t *cur = device_list;
( g& [9 q- M6 d    if(NULL== device_list)$ S. t  b5 q$ _9 F* Y+ ~$ r
    {- B5 `' {6 ^/ b$ j9 Z7 H7 z9 f
        device_list = dev;
' B8 U6 c5 Q. e1 G! r- y& l        dev->next   = NULL;
+ O( c2 L' }* M+ ^. D    }7 Y' {; M$ F1 s5 O0 ?  }" E+ y
    else+ `" o$ V6 i+ E& j
    {: i$ v7 w/ ^- c  f
        while(NULL!= cur->next)! W; J1 `) d( c+ T3 p% ?0 q) z6 W$ \
        {/ k, F0 O4 }( M/ R1 ^% [
            cur = cur->next;
& d$ }% q) f: V7 ]        }0 U/ m1 P/ s4 M1 j4 @- W, J& j1 p
        cur->next = dev;
- B% W" I3 ?: `) M# v( o        dev->next = NULL;4 h9 Y  B2 f2 q* Q" L
    }7 m7 V/ V2 ~9 }. ^( H
    return 1;7 y. t  Q! D, P0 B) `9 t
}( v. e3 `$ E) O, O9 y
/*
. e6 N. N7 s! K* F3 A6 K    驅(qū)動注冊/ r2 a) d' ?# L# J- e6 J
*/
5 t: p) \( ~( r% b; tint cola_device_register(cola_device_t *dev)0 s5 N2 @- D7 Y  X) c/ B
{5 @  @6 K. g4 R4 S* A
    if((NULL== dev)||(cola_device_is_exists(dev)))
& u$ n, u2 S4 w5 n. w    {* @) H6 H- Y2 k. P4 j0 @
        return 0;
7 P- u. G1 ~6 S  p$ Z    }
% ?" S) ?% {0 c8 q    if((NULL== dev->name)||(NULL== dev->dops)), X2 p" b5 y0 X8 R6 ^" n  e& S
    {
; s9 d7 W- V' g7 u        return 0;& @; m5 f0 n) v1 w" T
    }
6 ^' P$ N. x( ~* @2 o; r    return device_list_inster(dev);7 [  b( B' I. T  z* y0 y1 Q4 l
}
- \' u$ P7 R/ V* ^$ E: s/*& c) {/ t; q% p# T8 _
    驅(qū)動查找
! o) ~1 i( \8 p- z  _*/
! C  g" t4 N0 D- L( bcola_device_t *cola_device_find(const char *name)
: V- [3 e3 I1 U+ `( x8 S) ~  X. A{4 u9 z1 r4 y8 x$ P4 t2 M) s
    cola_device_t* cur = device_list;3 D7 k' ^6 W1 p
    while( cur !=NULL), |# _1 K% x: m# a4 k
    {
9 j1 [& g! X7 B+ r        if(strcmp(cur->name,name)==0)
- _. B% t0 A9 A. [2 t" K/ O) p9 e3 W        {
5 s3 D$ _0 O2 d            return cur;
% }9 X. ?8 \" `: T" K        }
$ B2 |' x8 R, \8 |5 L$ F/ K8 L        cur = cur->next;% {7 L( u1 w9 M
    }
' J& i1 J' j. {' c    return NULL;
( n+ r. m9 s- F0 w}
% Q: I4 x: z2 G8 L3 T4 P  b/*
. _/ w5 `6 C( y7 R    驅(qū)動讀
8 z7 c1 A6 q4 b*/% j% L* q# b) L! [. [: l* u
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)! C( X6 u, Z! Z. Z
{
+ ]; p5 C+ i. @. v    if(dev)
) |- _- g3 q+ z/ _3 T6 E' |    {# S. k. o$ G* C" @. {4 p
        if(dev->dops->read)' A6 |0 c- y$ D
        {
+ G/ f1 ]( t8 S/ ?, L) Q            return dev->dops->read(dev, pos, buffer, size);
" h) [1 m) u+ |) a1 \+ o8 ^7 N        }3 ~7 K$ j& u. E+ h3 e5 m9 b
    }
/ N2 E% N6 K% _6 E  N( u( V    return 0;
4 Q3 v3 ^9 C; y3 U# u: W}
& n3 M6 s; O' }; b0 `( E/ ~# s/*
# N8 T9 J! n" m7 `    驅(qū)動寫
2 ~1 L& o# c) T- f( {*/
1 v2 s0 |3 r2 gint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)  h" C; {+ G& c1 B' x, z0 S
{+ F" t% {# i; x- w
    if(dev)- X- W. P& I7 E& a! O& _+ y
    {
  h$ A5 n- H; b% b        if(dev->dops->write)6 ~6 n! |, R- p0 e5 M0 d4 K" V% o
        {
1 b4 R$ W. m& P7 s& @            return dev->dops->write(dev, pos, buffer, size);. n$ f! Q3 V' z( F* L7 d
        }& V3 R6 l: V$ v
    }* R6 d- `( V+ w5 ^
    return 0;
! F& S2 V% J) e$ m3 B5 ?1 k  ]}. B) U0 O. P: j, l1 u$ b5 w2 L
/*
, b2 E( Q, o3 y* ~) Y    驅(qū)動控制, k3 {  L# }7 h, {, W' L
*// O4 \8 t3 B6 C! K3 n
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
4 ^+ d8 n/ `5 x. t{
- L3 k) ^; J8 N* l9 K$ |" ^: ]    if(dev)
5 @, ^* c+ ]. z0 F: s+ I    {
5 u1 Y1 F4 a" U0 f9 r0 c: R8 |        if(dev->dops->control): p$ e; _, N. {/ D# Z1 x8 J, e
        {! G8 `8 |2 b& m- C4 }$ i6 p
            return dev->dops->control(dev, cmd, arg);: ~4 ]" }! h# Q
        }4 r( p+ R+ z0 T" g7 r( x) W8 _
    }
9 \: u$ A# J9 T1 ^5 Y5 M2 _    return 0;
, w; R6 L) |1 p/ Q}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。
: \* u# r5 U: w; Z#include "stm32f0xx.h"' ?2 \) D- S0 R
#include "led.h"6 L* O7 s) a" H, }
#include "cola_device.h"
/ @7 V7 s* g/ o. j  V5 d2 ~#define PORT_GREEN_LED                 GPIOC                     C+ j7 U  Z: W
#define PIN_GREENLED                   GPIO_Pin_13              
! k' K( C: x$ N5 d9 _4 x. b/* LED亮、滅、變化 */
: V/ ~3 `2 l  {) Y2 r! N#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
; y- d- o' p/ }+ B#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)3 v7 Q  H- q9 b7 s, V% i- M1 Z
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED): s- T0 b4 A5 F9 F! P% F! l2 C
static cola_device_t led_dev;
- M  \" c' i- m8 h7 G6 H- mstatic void led_gpio_init(void)
& u$ {4 i9 l. q5 `& q{( c- N$ s3 ?& B
    GPIO_InitTypeDef GPIO_InitStructure;6 G9 B" I( a! k! w$ @( J4 F
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);  _& n( b& k+ M. N8 F5 G
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
5 v1 k* n0 {- I/ M6 }    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;4 r# w, Y4 v8 f- c) s" O
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
, c, D0 Z1 P+ |8 ^    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;5 f. ~3 z% T+ Q9 _+ n
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  A6 C% t# P- C6 M) Q& }5 a' @' x
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
9 L, c) R8 ]2 F. H, G( p1 M    LED_GREEN_OFF;
& k4 c1 s' y9 n}
3 {5 P: B3 M. d4 f
) Y+ y9 y8 F7 X- S) @' `1 ~  nstatic int led_ctrl(cola_device_t *dev, int cmd, void *args)
/ ?& x& G) z9 U7 G8 y9 [& i" x" T% [{" Z. [! c+ [# C
    if(LED_TOGGLE == cmd)
) T! T2 `: h2 u" W% n' U6 F    {$ [& s2 s( X* z3 D9 X" I5 O4 \
        LED_GREEN_TOGGLE;+ O, g( ?( Y* C7 O  B$ W, F9 p6 t) \
    }
9 |' c2 ]1 F" ?" F# m+ [    else+ {6 T! a7 x* Y/ b! Q
    {, \: l8 C  s& @
    }
& m9 I: m( K. w5 i" z3 ^8 {    return 1;
, Z5 n  ]( D, o/ U/ [}3 E3 G% b- y5 I, ]
static struct cola_device_ops ops =
5 l; M! ~! e. k{
# W4 p  @0 G; V( p, A: x .control = led_ctrl,
4 z; j; v/ x; V* {};0 ^7 D! L9 h! s* G& r
void led_register(void)9 ]( f5 j9 w0 m) Z" y. i! {9 ?
{
* g- X5 j# I+ }! t% d5 X" [1 u( _    led_gpio_init();
! Y* K: S/ ?3 p7 j    led_dev.dops =&ops;
+ @' W( m7 Y6 O, g    led_dev.name ="led";$ z7 w3 G# N# c0 y
    cola_device_register(&led_dev);/ Q, m2 S# l3 x1 g/ h! M+ I
}應(yīng)用層app代碼:
/ q% O+ q* V( d7 R  r( _3 r#include
/ [0 w+ t, M# t: y) {9 x#include "app.h"! f! W8 ]( D4 }8 C1 ^2 b
#include "config.h") n/ D5 ^$ W& s% z- Y
#include "cola_device.h"9 u0 p9 H4 M0 ^, Y9 ^
#include "cola_os.h"
* V5 ~7 M6 b, y3 k$ `5 N8 mstatic task_t timer_500ms;2 E* K/ Q% m+ k6 T0 w
static cola_device_t*app_led_dev;
2 b% l% W& |1 v; V9 a//led每500ms狀態(tài)改變一次
$ a( k/ {9 b* W/ h9 f9 ?3 A0 m& }: {static void timer_500ms_cb(uint32_t event)$ X2 P, h4 r1 ~9 N6 @$ {
{
' I3 N* Y0 a) [6 y; @    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);) [3 j, m" r8 G: |) G# ^
}
+ j- H1 W5 f, R5 b' r9 ~void app_init(void)
+ a5 r; P/ q+ I) P1 c{
- E( Z* y6 i9 p' u5 \( x9 Y& i6 i    app_led_dev = cola_device_find("led");
$ N+ V6 q7 Y9 O( d    assert(app_led_dev);
* z- m& e( O( Y# \9 C    cola_timer_create(&timer_500ms,timer_500ms_cb);
# q$ _. ~, o9 \1 S4 b    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);* N$ L" o" Q" Q' r5 P
}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實現(xiàn)的。" [5 d$ z5 Y( d" F$ _! h( H9 a( m8 D
四、代碼下載鏈接https://gitee.com/schuck/cola_os
# ?, n  h0 y" _
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/1015127221 D; F0 \  l. n  }/ S
-END-* _5 z: j" V, ^/ e8 [4 j
往期推薦:點擊圖片即可跳轉(zhuǎn)閱讀
$ h# z+ }& X0 B! G+ ^; x0 _* k, z. @                                                       
2 \/ d5 T" h  u$ ^& F1 |. m: L                                                               
$ Z# n4 Y1 d* f2 C1 W0 C                                                                        3 Q9 D3 w3 r. R: a: r2 X6 r
                                                                                * ~0 y# [. I2 a' R
$ m( Z" F$ b4 L1 G( {
                                                                                7 {; w/ R' m5 u
                                                                                        嵌入式 C 語言的自我修養(yǎng)
% `1 y2 r3 \# j# F) ]) w                                                       
" c' r3 k$ v& F% L                                                               
0 p9 R( ?4 k6 C% }+ t; U  P                                                                       
$ g, m" S$ F* V. f% y                                                                               
) A; \6 P8 D! t . n4 @% s$ {% s
                                                                                + o, f/ n0 f7 Q4 o% y9 T% |
                                                                                        被 char 類型的變量坑慘了!/ ?. R% `7 g- \1 j/ S# y  h
                                                                $ a0 T* m! a6 {) b) C5 N3 n0 Q
                                                                       
5 i! U# u( R( f" M1 Z* V                                                                               
0 [9 n, D2 ]& Y1 k& H. q
4 M. D. {! N4 _% M                                                                               
* {/ o1 f( ~# a, p2 O8 d1 \4 ?; Z                                                                                        嵌入式 C 語言知識點,動態(tài)變長數(shù)組  T8 b* S& H9 @$ c. m3 S1 Z) ?$ q
                                                                                ) \! o2 a2 \( u" Q# G8 k
                                                                       
1 _2 E4 J  o" x$ a! U                                                               
5 [6 t# U3 N( J' @( M/ m7 O" H                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師2 `( N/ Z% S) W/ B7 _8 f
關(guān)注我,一起變得更加優(yōu)秀!
回復(fù)

使用道具 舉報

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

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

本版積分規(guī)則


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