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

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

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

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

[復(fù)制鏈接]

455

主題

455

帖子

849

積分

二級(jí)會(huì)員

Rank: 2

積分
849
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
我是老溫,一名熱愛(ài)學(xué)習(xí)的嵌入式工程師
+ p9 [( N* ?6 M關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開(kāi)網(wǎng)絡(luò)上下載的例程或者是購(gòu)買開(kāi)發(fā)板自帶的例程,都會(huì)發(fā)現(xiàn)應(yīng)用層中會(huì)有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來(lái)時(shí)屬于硬件層的,如果軟件層出現(xiàn)這些文件會(huì)顯得很亂。
) Z9 r  E( `3 i$ P, K使用過(guò)Linux的童鞋們肯定知道linux系統(tǒng)無(wú)法直接操作硬件層,打開(kāi)linux或者rt_thread代碼會(huì)發(fā)現(xiàn)代碼中都會(huì)有device的源文件,沒(méi)錯(cuò),這就是驅(qū)動(dòng)層。
7 V1 |- q, f7 r( j 6 w  D  K* r; ], t8 f  E
二、實(shí)現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動(dòng)鏈表上,在驅(qū)動(dòng)層實(shí)現(xiàn)device的open、read、write等操作。當(dāng)然這樣做也有弊端,就是驅(qū)動(dòng)find的時(shí)候需要遍歷一遍驅(qū)動(dòng)鏈表,這樣會(huì)增加代碼運(yùn)行時(shí)間。
( i$ |' t4 F! |) v4 ^8 q三、代碼實(shí)現(xiàn)國(guó)際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡(jiǎn)單在這我只用單向鏈表。有興趣的可以自行研究rt_thread- j2 j3 C7 u9 `  \: Y
頭文件接口:  }  h/ W' C: q" t8 O9 n7 X
本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):
) n0 J1 q+ r3 l5 }/*5 U0 \0 j4 x0 a
    驅(qū)動(dòng)注冊(cè)& `$ G" P' t: H' g& J: @6 A  ]
*/
# Q# }6 X; r4 s9 D, B  \( mint cola_device_register(cola_device_t *dev);
( Z  N  O+ c8 ^- b/*% N/ L* m! Z  O0 f- s3 D; ?
    驅(qū)動(dòng)查找+ V9 U8 }" ~. J0 F. K* O! k5 U1 L2 {
*/1 ]2 f8 B% d% C
cola_device_t *cola_device_find(const char *name);
4 f: g4 r: M, q: f/ g$ v/ F1 \/*
3 B9 ~- C+ s8 t+ w1 Q8 w# k    驅(qū)動(dòng)讀
' }- p% C, |3 `+ P3 N0 f  W*/
8 g0 i. ?& B" U2 s& ]% x- h/ p: w) Zint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
  g/ d, g6 C; S. ]+ y) A- E3 w  c0 v/*9 x5 B, l. \' {8 P
    驅(qū)動(dòng)寫" ?9 f: l8 H$ ?% l5 S' F& [' n
*/7 p8 I9 @, O' B0 z+ R$ D: _5 }8 W/ d8 o
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);6 z" k# Q) c* P) U/ d
/*# ~% s, \4 z" A, \' D& E$ y0 D  Q! Z
    驅(qū)動(dòng)控制
! {- z3 b: X4 R*/
" m; D6 A6 Q. r7 s% ~2 Pint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
3 ?' W1 V- Z2 b" ?/ h#ifndef _COLA_DEVICE_H_
6 Z2 ~; _. H; u#define _COLA_DEVICE_H_/ N0 p8 D. L2 i9 b
enum LED_state
& J! w% w% x) _6 j{
) P4 B. F" l; {: P    LED_OFF,$ V* W+ I) L- _; W- u% {; l- Q6 ^1 j! Y
    LED_ON,
; x7 y2 k; o  D$ k! w( H0 t/ K6 o5 [    LED_TOGGLE,9 d* p+ }! J( d! ^8 ]5 k0 |0 y- _
};
2 w8 X; [0 Z, a/ l8 |' Ftypedef struct cola_device  cola_device_t;
5 ~. v% W7 a3 s+ d# tstruct cola_device_ops* f; \* i3 v3 _7 P
{
+ z' ]- t% h: K7 s$ u5 V% O  u    int(*init)(cola_device_t*dev);
* \7 C/ u, h8 V% R) e    int(*open)(cola_device_t*dev,int oflag);# A. R& |: g' s6 r: I% s
    int(*close)(cola_device_t*dev);" ~7 O9 w7 v# z. N- C0 y. s; ^: M
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);! Z% {- F) c7 q
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);/ ^9 [) t  G6 a5 g! w* `
    int(*control)(cola_device_t*dev,int cmd,void*args);
5 t: L$ n# ^5 ?- B, @' W$ c/ Z};% ]5 j( B9 T  j- p3 R2 ?- p
struct cola_device
% R; @$ G; c+ q# I3 p$ y{
; m0 e& @* z1 Q8 c9 s    const char* name;+ ?( O+ S0 y% A7 v$ T. w
    struct cola_device_ops *dops;6 L' N! K3 j9 q; z7 m' [
    struct cola_device *next;& F7 `) @& z/ I7 f) |( p
};
- V, A1 B( _4 Z% L/*4 [9 d: X6 R- q& I! o
    驅(qū)動(dòng)注冊(cè)8 q; d: ?) ?9 P& V$ H
*/
/ y! Q! H3 U: Aint cola_device_register(cola_device_t *dev);
% a/ N2 G; t. k. _) \6 L+ b1 ]0 N/*
& ~. `2 I: M2 J4 `0 d1 C. D" R- h    驅(qū)動(dòng)查找- {$ z6 c2 T7 c2 C
*/
8 F  v; Q% _2 G5 Jcola_device_t *cola_device_find(const char *name);
. E* a8 ?8 Q$ r' I/*
3 \! ^# K) T6 C6 @: S    驅(qū)動(dòng)讀1 c1 G( p+ I2 E, i( t4 a6 c
*/3 r  p. q( T( R
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);( F: k# g/ i# W7 u: i& J
/*
3 B4 W- `7 m) v$ C& m1 B, W. d    驅(qū)動(dòng)寫3 b" }* v% R; I; Z
*/3 e( V) x) N1 g
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
" |% z" ]* {1 ^% A3 L2 \/*: |+ R  L% N- I3 h
    驅(qū)動(dòng)控制
: G  R' p# [5 Z, `: d9 t( C*/
- Y7 ?, {! Z! J7 O: }% K* u5 cint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);2 O- u0 ~: ~1 }4 A
#endif 源文件cola_device.c:
& b/ D/ Q: L! N: x* O4 h. \8 y& }#include "cola_device.h"
/ @2 F; O3 Y) a* I' p7 ]. H, e; {#include . }; u) S$ k6 n; f# c+ \1 J2 E
#include # H! K8 n  m% G( C( w' X3 }0 b
struct cola_device *device_list = NULL;
: q' J& M: A! U3 m/*/ r/ J9 `; C% f/ f
    查找任務(wù)是否存在8 V' l4 O* a; {% C1 S
*/) }% H) {* c7 V+ p# |- |2 ~% z. c7 Y
static bool cola_device_is_exists( cola_device_t *dev )
9 J8 s- p6 i; }0 Y# E{+ V+ v* ?' {2 l
    cola_device_t* cur = device_list;
, H& q& a) d8 g. A    while( cur !=NULL)
3 q4 Q" l& A8 B7 [) ^    {
: B; `# `& r  u/ ^        if(strcmp(cur->name,dev->name)==0)$ Q. y9 r4 N8 i% L8 b  D
        {/ q& k, E2 u+ \% f$ f
            return true;' T! o* m( e" a3 c& H4 h* `3 y
        }
2 A% c' \9 ?$ b; h        cur = cur->next;
# x; u: h+ p4 O; m    }+ E. f6 ~  S; ^% r# t7 @" e4 p% h& N0 q
    return false;
. A  }; G) E' V7 T- a2 b}
1 M! r! X/ R' F5 M% K* i1 j+ tstatic int device_list_inster(cola_device_t *dev)
' }6 I7 ~' L9 u8 \2 U{1 a! i$ o+ N, K8 ?: J
    cola_device_t *cur = device_list;
! ^# x& `: W5 d: C2 W    if(NULL== device_list)
  ^' X( X4 k1 a0 A    {
. `( V; M9 w" k4 a        device_list = dev;  ^4 C* j; @" [# b0 P
        dev->next   = NULL;5 n- s" k" e. V
    }
% l: p' j4 |: j2 D( W' d3 p5 Q3 \    else
0 E. U) J' Y; A3 R6 F. h6 E2 E: L    {
6 B" P& |. d. L2 _+ ~        while(NULL!= cur->next)$ O9 W5 \6 e0 m9 |. F
        {
+ Q% D# G. S* X            cur = cur->next;7 ]0 T5 N4 t, [0 ?3 R9 t( I- U
        }( `1 d2 T' V' i
        cur->next = dev;
; |5 `' w7 z) P- D3 L& J        dev->next = NULL;% K% n3 G3 P( h9 F! }* v& p# p
    }
3 s- B* I6 y( T$ U& e( E    return 1;. b' @+ v6 z/ ~6 V& o5 n
}+ m9 _5 U. N+ y% m. r* B8 |! k( D
/*9 H! }# H; u5 p. B
    驅(qū)動(dòng)注冊(cè)
% W* `' A9 j/ Y3 Y7 b*/; |4 D2 Y& E3 d4 m6 T: H
int cola_device_register(cola_device_t *dev). ]! I8 G3 q- y$ K9 R( V4 r' z
{
* m/ s/ A) }3 c9 I4 Q8 j    if((NULL== dev)||(cola_device_is_exists(dev)))0 I- f9 K. D7 N0 `& D
    {
3 ?" z. B$ h' ?- v& D        return 0;& H4 J/ {: ~% X6 B/ k1 g# r3 _( x
    }1 _& z0 A5 z6 U. X! Q
    if((NULL== dev->name)||(NULL== dev->dops))
- C/ D# j' C" W* G* ?0 W    {
- h7 @3 S; o; }, J# K        return 0;% d2 B) L* x9 w" G5 u" `2 V  v, K
    }
" l% u6 a; I8 ~" H    return device_list_inster(dev);2 c7 T/ _: i* `- v) B- x
}
# x! h4 U* i  m8 x/*
' h+ D( O" }- x6 }$ K    驅(qū)動(dòng)查找2 `5 d( I; J% P- o5 t
*/
: X/ i# e9 h3 s9 `- ncola_device_t *cola_device_find(const char *name)) I, i4 I: I# Z9 O/ i4 h
{. r$ y3 i4 T7 @% m( j/ L
    cola_device_t* cur = device_list;: I: L2 B0 K  K/ N: t/ f8 Q! ]
    while( cur !=NULL)* l$ f2 t  b6 p- b
    {8 ^4 Q* @4 Y& H: \1 {
        if(strcmp(cur->name,name)==0)+ `& ~2 [1 P( w# G& }1 L0 d9 C
        {. g9 N5 z. s4 _' y" \: D
            return cur;
5 D. }( k) L' M6 K- \3 t) I        }/ C* n% D% l% n8 G+ {
        cur = cur->next;3 H# }+ S7 c4 e4 I+ w7 u
    }* M4 l: z- _+ I  p3 K
    return NULL;9 t* Q/ V( v$ E" i8 @( ]
}
) z9 k2 O+ r0 o( p/*
. d2 `7 P& _3 y* v& I1 a! r3 t# w    驅(qū)動(dòng)讀/ ^/ N& Y: r( D) ~: h3 |
*/3 O% c2 N% {; M5 `
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
; x: f# Q( e/ t8 h# y/ n' w{. n. R6 i  Z+ u/ @4 |
    if(dev)
- i0 _) C( a5 e4 X- k. f5 j' c    {8 o3 u/ l9 D) \8 V0 H# C
        if(dev->dops->read)" u2 b# Z/ h4 C
        {& h1 T" J  ]" {" k; C( X2 O  H( G- J
            return dev->dops->read(dev, pos, buffer, size);9 L8 j+ p# O' R" k: N
        }* d7 r, Z4 c3 B/ v6 s  u
    }8 }$ Q0 s9 J5 q) V  Y# I/ ?+ J
    return 0;
5 a) U! d' Z% D4 A9 f- o# e. J. P. O}
* r3 j) T! H6 M/*
+ |+ Q0 T1 ?1 B9 `( z# z1 S6 k6 q/ B0 [. h    驅(qū)動(dòng)寫% D  W4 [/ p2 b" ~8 M0 U% `1 ~
*/- I' o! o3 b/ _
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)- L  E. x2 I& \4 g: W9 k$ @6 P+ P
{6 T0 D/ e: c: R: O
    if(dev)6 {% Z0 t( m: e
    {
. w$ k& S# ~; `        if(dev->dops->write)
! Z: V3 N, z2 K7 B7 u1 J" l        {
9 u# P9 U* Q6 C% N. P5 U5 r            return dev->dops->write(dev, pos, buffer, size);% y' Q6 [* y* Q9 P! z
        }* \" w% _5 z; B. ^
    }
6 M! l5 `" l  l% t4 l, K6 V    return 0;9 L* L! T( P8 E; g$ o8 l: c$ N3 \5 o
}
; |" G5 T* `1 u, ~7 n/*
" n0 k6 u9 U& C$ b5 e0 W0 `    驅(qū)動(dòng)控制5 R% s8 z5 R1 A
*/
$ Y9 u& F: f) g' yint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
# P: j# W  v5 T{" U1 e0 L/ N) O- f8 d& i! ~; S
    if(dev)
$ R  C6 j* i0 a    {
. ?/ j/ n  j! O, g        if(dev->dops->control)5 ~# p. {2 ^9 }& F- C
        {/ x3 z! O8 l/ o
            return dev->dops->control(dev, cmd, arg);
" A- ~4 M9 c0 v9 g7 c0 p        }
- I7 E; D9 N- \0 X+ Z3 y: R    }
2 r& b- C0 N, k    return 0;
  X+ w. \0 `+ M- p* a: ^! b+ g}硬件注冊(cè)方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。6 j7 ]& e+ v- D$ K
#include "stm32f0xx.h"
! d: M) Z3 Y" ]0 r- B  g#include "led.h"  ^% D; b8 s5 e  w1 Z
#include "cola_device.h"* d. Y# Y: R3 z4 B" p
#define PORT_GREEN_LED                 GPIOC                  
  n7 [0 i; C- S) x#define PIN_GREENLED                   GPIO_Pin_13              % P9 c. G: m6 C& @/ p. Y- \
/* LED亮、滅、變化 */
# }" j5 m4 @+ j0 s3 `#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
& g% P3 T8 l1 ?6 [1 _#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
- _* C' b0 C$ ^9 i0 u  b#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)0 `- ~  `/ ?' R% f; w3 ]7 [; \- z
static cola_device_t led_dev;0 L4 q! Y2 e- L# t0 g8 U$ v
static void led_gpio_init(void)1 Y( D' ~, n0 {. F
{( G5 k8 J# t& h' X: O5 z
    GPIO_InitTypeDef GPIO_InitStructure;! `) W4 d2 P" G( {3 @7 V
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);' d7 B. D' `8 x% W" {
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;, C; D: f$ C6 d  u. W
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
$ `& [& Z8 [) n5 X; |7 F    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1 ?  t8 O) `3 E) F, @0 K    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
. b2 o) E3 O9 A7 |) u: x    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
" C% s. V3 E3 w# ~    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);+ d) K! F4 Y0 n' ?! \+ U3 O
    LED_GREEN_OFF;: O  E! K  Q1 q/ Y4 W
}
! a; i+ p; f& C5 W
3 ^) ]3 e/ R2 P+ k/ R0 t1 jstatic int led_ctrl(cola_device_t *dev, int cmd, void *args)
# Y1 S) p: m; ]2 Q+ h+ I% Z{' Z  D7 I+ M. O; G) d4 P
    if(LED_TOGGLE == cmd)- e' p/ [: N5 x  S
    {
4 W: a! o' z  a. E5 @2 X# {( c        LED_GREEN_TOGGLE;
3 }( j; \2 H4 C, Y+ _2 q! w    }5 x% C) d8 W, M
    else
; t! t" O, M; U, N. j  f9 e    {
% f. G# a! k: M    }
: v# w  x+ g2 ^1 ^% l    return 1;  a* G1 {: l3 r* b3 T+ b* J
}
- U5 j8 ^2 k/ d% }) r4 o+ Mstatic struct cola_device_ops ops =
! |4 A; m- s+ i: H) u{; |1 ~" T  b3 _/ z+ Z3 [4 o
.control = led_ctrl,
4 L3 m+ D: o- g1 o% d};7 \5 r  m0 T  j: ?2 H$ f1 R1 W
void led_register(void)6 |8 V3 k+ v& m* Q+ W
{  Y8 H$ W3 ~( B! r2 s: B' @
    led_gpio_init();- \) S7 d' l# q* t
    led_dev.dops =&ops;
6 c# i6 _3 r5 J) N+ F/ k, _    led_dev.name ="led";( D5 a6 V8 Q( C$ c4 h/ l
    cola_device_register(&led_dev);
* ^# R+ ]- \$ [. M. W2 @}應(yīng)用層app代碼:
  N6 @/ b2 W  S# [! k; _' p#include 4 {3 C: P, Y* e" Y- h4 `2 w1 C1 f
#include "app.h"
! r5 v- v2 a3 g0 O5 x. M#include "config.h"3 D6 E2 |, r* B! W7 Z7 d6 e
#include "cola_device.h"$ i; S9 |8 v  x
#include "cola_os.h"# `. [) Z  O$ D# e
static task_t timer_500ms;
7 ^( g; J2 s7 Z% ?4 Gstatic cola_device_t*app_led_dev;
) ?1 q: l# Y& q" ~//led每500ms狀態(tài)改變一次0 f8 I7 y6 {; Z3 G0 Y8 C+ ~6 U/ s
static void timer_500ms_cb(uint32_t event)
$ s# V6 V1 X2 @' p) k{' c4 `3 I( L9 ^* L+ k: H
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
# B2 M2 q. B4 p8 r  A3 z}0 w! _6 ?# x1 a3 z
void app_init(void)2 ]% n7 L0 i& |* ~. h
{
2 ~; B1 o! O+ [, a8 w    app_led_dev = cola_device_find("led");( \6 {, d0 n3 |+ Q* O5 Z
    assert(app_led_dev);
' A$ w5 \. g$ Z2 X- I" h    cola_timer_create(&timer_500ms,timer_500ms_cb);+ V$ E- a6 J# C! c5 w, K" A) V
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);  ~7 Y8 @8 c& [1 n
}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。  h: m- a7 c! g$ P2 Q' _3 {$ p
四、代碼下載鏈接https://gitee.com/schuck/cola_os. M1 X9 _8 F, w: i7 l6 o9 W( V" d
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
1 v% X! f3 u' k; P) u0 Z-END-
( c  ?  `- a: I往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀* d: a2 T+ C: H* l/ M. |4 `
                                                       
" L  M  q1 O8 G, e# L/ k3 m                                                               
0 l7 U) o8 v5 f% e) G! H" _1 |                                                                        ) P2 O# ~+ I5 L/ S7 P1 @( J
                                                                                3 o0 ~2 W  }+ D# A" W4 g' ~. ]
  l2 X, u: Z+ w* k+ Q
                                                                                : W. A! j' R4 Q9 n* ]$ Q
                                                                                        嵌入式 C 語(yǔ)言的自我修養(yǎng)4 s$ ?; c- k5 O3 u& O  |
                                                       
5 n. ~5 {( [& w) z                                                                # c. G, n1 ?2 X$ v
                                                                        * m! _$ l# l3 a% r8 K6 h
                                                                               
( ^$ F) d, F3 v& t
4 Z4 S" p+ d8 f) q1 u8 r0 D8 G) ^                                                                                3 i3 R' s% K# x& k3 d) ?* f, s
                                                                                        被 char 類型的變量坑慘了!
! n" s7 L" K. @7 i. a4 Z% Y                                                                ) N0 e, K; a* M9 L
                                                                       
! }4 A& p5 K6 `! {, T, p$ x                                                                               
* w" d- B9 D6 W 6 w3 t+ j$ M6 i- V" s0 u( I
                                                                                * M" G2 R; U$ `9 S  W# k
                                                                                        嵌入式 C 語(yǔ)言知識(shí)點(diǎn),動(dòng)態(tài)變長(zhǎng)數(shù)組! R3 Q) m6 U, b' x' `* U. }8 S  @3 `" Y
                                                                               
. g% b# b1 ?$ Y' w# E                                                                       
5 C5 ^* X+ T% t0 o0 H                                                               
% R4 E8 m9 n# F                                                        我是老溫,一名熱愛(ài)學(xué)習(xí)的嵌入式工程師
  g1 h0 Y, B* k/ m3 _關(guān)注我,一起變得更加優(yōu)秀!

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

本版積分規(guī)則


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