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

PCB聯(lián)盟網

搜索
查看: 47|回復: 0
收起左側

如何實現嵌入式軟硬件分層處理接口?

[復制鏈接]

437

主題

437

帖子

96

積分

一級會員

Rank: 1

積分
96
跳轉到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
我是老溫,一名熱愛學習的嵌入式工程師9 w3 L' t: g' \. y/ j0 |
關注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網絡上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現應用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴格來時屬于硬件層的,如果軟件層出現這些文件會顯得很亂。7 V9 A* Z- W- g) D
使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現代碼中都會有device的源文件,沒錯,這就是驅動層。
+ v4 U; j) P2 Y 2 e% t8 q+ E# V' M6 ]# |1 B
二、實現原理原理就是將硬件操作的接口全都放到驅動鏈表上,在驅動層實現device的open、read、write等操作。當然這樣做也有弊端,就是驅動find的時候需要遍歷一遍驅動鏈表,這樣會增加代碼運行時間。
8 b$ y' j& u+ u三、代碼實現國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
- `" U, }& ~8 j% k4 v8 P頭文件接口:
4 M; q/ s8 ~& L" G0 n本次只實現如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應用層中只調用如下接口可實現:, ?1 n: x0 T0 |+ e" K
/*
, I% P) O* }: M0 ^/ n( e$ [    驅動注冊& f+ D5 q5 Q: y% E" {2 A* l8 X- q
*/
7 i5 a7 |6 M+ {( `% tint cola_device_register(cola_device_t *dev);
/ }% j: p, Y9 }- r2 D/*+ @- p) R! t  R4 a
    驅動查找2 W, u* o+ Z; S, l% U
*/; h& |, v& P0 s3 |) V# s1 P& K5 Y
cola_device_t *cola_device_find(const char *name);
/ T' l: d* d6 l4 b" b8 b; s/*
' s- [6 V8 t- R    驅動讀
  H4 c% C( T* o$ E. F3 m9 d" A' K*/
* Y$ n4 @. ?* l6 r4 L& cint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
8 R  ~4 ?& ?' P/*7 o' @9 ]( O  W6 d( [
    驅動寫
8 R: G' s- Y4 o  T( t) j' W*// Z' p0 I  G3 K: t( |  e; Q
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
6 x7 H4 L: R1 w7 @% j/*' x' c+ N; o8 \6 l* C
    驅動控制
2 k# r! {" q. O5 Y0 q! s3 i*/
" s8 u/ _* ~- T; Kint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:4 T3 r) Y9 F* P! ^% }7 ?3 L
#ifndef _COLA_DEVICE_H_# z& K& m4 F4 L- s
#define _COLA_DEVICE_H_
" i  A+ U& B( venum LED_state
2 S0 L) l$ F& [/ h! z+ Q{: L  }7 d# X. ~0 `
    LED_OFF,; ~/ O0 D: `2 f- S
    LED_ON,) J6 u; {  U  G0 `# S8 e" Z" U$ M
    LED_TOGGLE,2 H, q# g9 E. E( @5 a; k2 |5 t
};, R) `7 j0 R/ ^) j3 F( \
typedef struct cola_device  cola_device_t;
' t& V5 t, C3 A' Y- \2 g( `9 }struct cola_device_ops* F6 Z/ U, c( ^
{
8 F/ P& g2 s2 k% V3 S$ O" b    int(*init)(cola_device_t*dev);
/ J4 `/ F8 n! B" I2 n1 P    int(*open)(cola_device_t*dev,int oflag);
) w; t$ n) B- h  t, M1 B    int(*close)(cola_device_t*dev);
3 k2 E% J4 N# `/ l+ z/ |    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);' {1 [; u7 b- B" H$ G' C
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);8 E4 U% c& ?$ B8 g+ e7 R. L
    int(*control)(cola_device_t*dev,int cmd,void*args);
/ K0 o. F; W' }};2 H. j$ C* D% Y
struct cola_device
( u2 N: }4 n  r{
  C3 _4 P" P4 m( K, Y9 n    const char* name;; j  S- c2 P# y$ y9 H5 p5 R: P7 y
    struct cola_device_ops *dops;# `. l) q% B' X5 m7 s" Q
    struct cola_device *next;
# B% U' e9 L- b. \$ O8 Q; S: I};
& X/ F, D" S9 \/ l) ?# \* e/*2 x( E1 K! o" U8 _- `$ c4 @0 H
    驅動注冊
! l# I* q1 @$ H# w) W* D*/
1 _% q, t7 \5 }, Z, b0 cint cola_device_register(cola_device_t *dev);! ]6 z# |) e9 h$ E8 G2 K9 l+ j
/*+ {2 d5 K$ L6 Z: w$ F
    驅動查找6 ]. P9 ?9 x5 w! w% r9 J9 \
*/  {; {- r+ r. u, H# B1 T) `
cola_device_t *cola_device_find(const char *name);! C# R" l& o" @, v4 _
/*
4 P$ B& @8 B' ^6 @( r    驅動讀
1 y7 X! `" p1 |% M0 w5 W*/
% d( }' L% Y$ N: P; K! E( Iint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);' [$ Y1 r" T5 V# K. G
/*/ S8 `4 J2 q% b- s' @$ @* ?
    驅動寫* n9 ^4 P4 |" _5 @
*/% I) y- t: {9 {: p) w. m
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
6 W- z6 A  y4 G3 t4 O8 k/ [& p/*
4 u# R  D2 [; t8 ]) j    驅動控制& U" d* K+ m1 y) F; ^5 i
*/( O1 X9 H0 G" ?  Z1 f9 T3 z1 }
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
' P, R4 D; c2 g: N" U/ U) N#endif 源文件cola_device.c:
! K$ \8 ~5 E6 n* T#include "cola_device.h"; y  \4 T1 r  L" |  x) w
#include # R3 C; C. B1 C/ U7 M. h# v0 m
#include ) J7 k& k% }) \1 P9 v& `
struct cola_device *device_list = NULL;# E. o, Q7 v+ I8 w% `) F; C
/*( c9 E) Y1 Z+ x% e
    查找任務是否存在; P4 I* H3 Q# \) ^# M( I
*/
8 K( J- _" u% \" \! R( ~3 zstatic bool cola_device_is_exists( cola_device_t *dev )
! d/ H$ V/ J% p1 a{
0 s. O" D) V, |; \/ A* T( w: a    cola_device_t* cur = device_list;  i  Y" s8 _0 G9 T0 f1 R
    while( cur !=NULL)" N4 n2 r5 U# @! w6 U: n
    {  N7 E. P4 R, ]. R: m1 s, J5 f3 ~
        if(strcmp(cur->name,dev->name)==0)7 l3 X* u% x: Q" _' y9 j
        {
  E5 P' D/ B7 ^5 N1 C            return true;3 J, S. [2 f6 s, }- C2 B; \
        }
) w) Z3 g/ i6 x        cur = cur->next;
. S( W( [3 c! R( E: i/ ]4 h    }
3 ]& x; r! ^! i, |& ~  L* M0 L) t    return false;
6 d  C7 f3 r* E6 s& _}  S; C# U+ e7 H2 r; l% N
static int device_list_inster(cola_device_t *dev)
. \8 z  E7 I4 n+ j9 T; Z7 O{
% K4 F+ `% e; Z    cola_device_t *cur = device_list;1 _/ K- k9 y' c* |8 Z. y# _
    if(NULL== device_list)
( j% F, s+ j  L' Z    {
6 a  V. U. M3 X& O0 w        device_list = dev;
6 f* M9 F( Y- ]6 ?0 i, c, s; {        dev->next   = NULL;
& {( M% A2 E9 }* T) F    }
) j; y" X/ I  a0 L    else
7 l* c& G) A# }' W    {
" f; V+ c) I! [' z5 V/ h; x6 F1 L        while(NULL!= cur->next), p7 d) ~) e3 l" X- m7 N, G
        {7 t) j* K$ L, q, A/ t
            cur = cur->next;: W4 V# n+ p  }& N4 ?1 x# o# u
        }
2 E3 o6 u1 E7 {        cur->next = dev;6 r- A; M1 S6 s  r4 _9 ^' w
        dev->next = NULL;8 U$ Q  C- c2 J  Y/ d# j9 u) T4 A* ~
    }. b- X  Q" {* [9 x3 m8 i" k
    return 1;' ?' ]0 [* E9 T5 ^: d
}
+ L0 J6 Z0 b$ O4 b# O/*
3 S& k" g% I7 w" B# S* i% v    驅動注冊' D1 j5 s( T* x" v0 z- I* k" A, N
*/0 D( N3 k  V/ t1 i
int cola_device_register(cola_device_t *dev)
% t& s6 S5 Z8 c: A{
# e+ t# {, h# |( ~) C    if((NULL== dev)||(cola_device_is_exists(dev)))
( b% E. U8 Z. ?- H5 ^    {
6 K9 n) `4 N9 Z$ W        return 0;  q5 A! q0 w' B7 B* `/ j! y
    }( d8 `6 Z9 z& C4 O0 a
    if((NULL== dev->name)||(NULL== dev->dops))
: h5 k/ H! c2 x- D+ X    {! s" x3 n8 K8 h+ M2 |
        return 0;
$ O# h, a9 A. a7 N: J1 I    }# C: S+ H8 z! d% M; t; o: ~  O
    return device_list_inster(dev);* Z3 ]$ ], y2 s$ i% V, s- d7 C
}
( l. H8 R. E. ~. X" |& L0 U/*) j7 Z& H% Y( Q/ T9 N7 U
    驅動查找
0 S& g' {# m4 l. M! l*/5 V9 O) i2 b1 |1 E! [
cola_device_t *cola_device_find(const char *name)8 ]. `5 P8 o. J7 b9 W/ |
{" w3 R* b+ i/ R. k
    cola_device_t* cur = device_list;
( c  b' f1 y3 P& A- L5 k/ m! L    while( cur !=NULL)
- h' [. i# j1 H2 H& r    {3 V) l7 v; f- W& y& m
        if(strcmp(cur->name,name)==0)
$ n. T  w' h5 }5 G5 ]5 Q( d        {
! @4 L. `" v( H0 q& W/ q. [            return cur;
' i- a- u' @& s. z        }2 A5 b% j( }! q8 s7 r7 {9 b$ L6 S+ b
        cur = cur->next;* k. ^& F! Y& g3 N
    }
0 v. N/ U+ U3 r/ {    return NULL;- @  {6 Q  }: U1 N" R1 V) l
}
% G. L9 }: h- d2 N6 O& X9 u/*' V! T& A$ a5 M% n& R) B5 r5 O  C
    驅動讀
2 g0 w: {) B: Q7 O: ?# ?( R: Q*/( I. P2 `  n6 |( f
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)! u* `2 A4 C' g: I! j( }  C
{; X/ t  D% o9 H9 n/ `, U0 X; c
    if(dev)
" f# l, [1 ~+ a: S7 e, u    {
1 E9 T6 X6 r  \" s0 q! ^  Z* s        if(dev->dops->read)/ y; {" `$ J1 V8 ^' R1 b
        {
% p! n0 P* g7 \* {9 l+ p2 q' d) I4 W! |            return dev->dops->read(dev, pos, buffer, size);
8 n# m. {; c8 Q( {        }& Z+ _3 n# C; q7 o8 {7 b
    }* h- U6 J# Q  j- b7 y: J
    return 0;; Y( h" b5 g. X, Z$ f) M% }2 o6 U
}
0 L. b5 t# Z7 q$ R4 k/*
# q. ]) [$ D0 l+ n5 m8 p4 F: V    驅動寫
0 p, s  J  S; y2 J. m*/
  ?" _1 H# c$ e5 x0 `int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)( P* S+ d) `$ L' o. }  I$ I- ?
{4 t" a. Y) c3 A# J7 g; A8 v7 o7 }
    if(dev)5 e3 {. b$ L# c, @* _
    {$ g# Y. V+ C8 F0 Q$ m& c
        if(dev->dops->write)# B; X* ]. J; ]6 {! P, a
        {7 W3 i0 D) s* [0 b0 o  K
            return dev->dops->write(dev, pos, buffer, size);7 y/ v; s/ \0 h( _) {/ e% d
        }
/ }* U, z) J; @1 K    }
9 }1 J( J- k/ N    return 0;0 w4 d+ B7 }; `& W, n4 M0 O9 h9 y
}
: D$ j5 e( c  ^3 k" l4 {; O/*& D& [3 B$ n/ d% N
    驅動控制
9 P) P3 ^& q$ a* [- ]*/
7 n: O' T# i9 K1 E5 L  U7 S: k' ^int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
/ _( {2 o& N  d$ C/ H{
% l; B/ W4 A7 U: }/ P    if(dev)
* Y3 }3 P' p8 n; G    {
/ k0 s, B: ~1 a1 e+ ~, J# U4 p# U; l/ b; t        if(dev->dops->control)
3 P0 F4 f. Y" i" z! K        {
! B/ I' I9 ?7 w: u+ D2 O9 u            return dev->dops->control(dev, cmd, arg);
! h+ X& `$ q, F        }
9 m5 V2 |' j! h( D    }
! Z* s5 I' M$ U" D; H; }    return 0;/ c+ k! z, ]& ~" M- o/ V1 ?
}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調用。9 i& Q1 J% q% C# n1 a- R
#include "stm32f0xx.h"2 |: x( @+ a' U
#include "led.h"
# F" ^( d& `9 j2 a9 }  ?5 u  s  h#include "cola_device.h"
/ W9 [5 j( B. M& F4 M% N3 t% }3 P#define PORT_GREEN_LED                 GPIOC                  
- a5 e9 G+ b7 \3 K. D4 h; |#define PIN_GREENLED                   GPIO_Pin_13              
. L0 R5 E  K' }" S- K( x  N/* LED亮、滅、變化 */& _$ H% q& {* E3 T1 {2 T% D2 Q
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
7 Y5 @: ^" i2 s/ {2 A#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
: H' ^5 }3 s/ ^4 @! [#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)( O+ z% i; Q8 L# T
static cola_device_t led_dev;- w# C2 ]- R1 D6 O7 i$ I
static void led_gpio_init(void)
' N9 m3 f  y5 K, ^{$ D2 n2 M9 y; b5 H; N" |
    GPIO_InitTypeDef GPIO_InitStructure;
- f0 X- U$ J) B9 n4 x& Q. t    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
5 F: m- @) i" _    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
5 a! n7 t) s% O6 \8 r4 c    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;$ R4 r* Y' l) c3 t9 D
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
3 z0 E# |9 `- i  c5 a    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
' P9 i# r# s8 d    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
: Y. ^! e5 ^0 k/ ?& U    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
; b% y# k- G, E& |+ a' k7 X6 `    LED_GREEN_OFF;5 I2 E* J1 C0 z  o1 u7 |, ~% z
}
5 n, M, z# w0 D0 O9 t1 G9 g( y3 h2 Y. d' L
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
8 Q, [9 `/ u1 g3 U+ M" T; p* a{  ~, R5 K( G4 ]6 h0 R, X# _
    if(LED_TOGGLE == cmd)
) r" C+ ~# ]  O7 h: _2 m; a* l. M    {0 v; r* k2 g5 H% v2 |, e" W7 K1 \, ^
        LED_GREEN_TOGGLE;
5 l  L# _* L) O. V. n4 P. Z7 j    }: |4 Y# _. y' O0 P+ j, i
    else
. |* `; |  |3 v6 h    {
. P$ ^5 ^1 C7 y$ C2 L0 p# F/ C    }
5 ?% {7 i/ k4 l% L- X! ]    return 1;' m$ ~. \- Q1 G
}$ a6 @! w4 v6 T1 T' @0 u7 [& A
static struct cola_device_ops ops =! z" [; _( B! Y" C& p2 Z
{
% v. O: I& S& g .control = led_ctrl,: [  ?; Z9 [1 g# J
};5 E( i/ @5 P/ s. l) d1 A5 S5 x
void led_register(void), k, d5 h9 F; f: K( ]" F' G
{
" A0 y* Z$ G; u, ~% r/ B1 [    led_gpio_init();5 o9 J% v1 C9 {6 l5 A4 h' x7 \
    led_dev.dops =&ops;5 q3 e9 o, p2 \+ |9 `
    led_dev.name ="led";
( O) d1 l& {5 S1 X+ i2 ], o    cola_device_register(&led_dev);
6 Q' z; M% W* T( x5 _: `1 k}應用層app代碼:& H* s, A( N! [; n/ [
#include $ }# a' m4 I4 ^& J: v
#include "app.h"
7 @5 p  a7 A7 y#include "config.h"
* X# Z" r: J( p, H, }1 C/ @#include "cola_device.h"
2 D7 C" h. x, L  R/ j9 S& r#include "cola_os.h"
' Z# L; \! p; S& R5 C: C5 Z9 Rstatic task_t timer_500ms;& O1 o7 m7 V2 h8 M, e& E* P
static cola_device_t*app_led_dev;
/ k1 f( r" p8 R' f//led每500ms狀態(tài)改變一次! O( `5 n4 Y$ v) M0 X. o) R
static void timer_500ms_cb(uint32_t event)
5 f; O$ [- p0 ]{' r- h5 |) ?6 h& u! x
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
$ _: Q2 ?% N6 u, a: d  k}
% W7 M( B0 a2 F' O. [# z$ x$ E: L5 G; Jvoid app_init(void)8 k0 z' i0 D2 n# f2 |
{
/ R- x- `" c0 P4 B4 L* D: I9 \    app_led_dev = cola_device_find("led");* P: K; [9 }% _+ u0 D( \+ b
    assert(app_led_dev);
2 _5 c3 X" d# X( s1 t/ M    cola_timer_create(&timer_500ms,timer_500ms_cb);' }( p3 f4 Y$ V
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
3 Q8 t; s( Y' c}這樣app.c文件中就不需要調用led.h頭文件了,rtt就是這樣實現的。
# C3 ^: C/ ?5 `/ i/ F% o- D四、代碼下載鏈接https://gitee.com/schuck/cola_os+ Z$ D8 [9 u6 g  F/ r0 B" ^$ o
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
5 e6 N. x8 K( @% C( |/ [-END-
4 Z: G4 l! x7 o0 {1 x往期推薦:點擊圖片即可跳轉閱讀
1 _# r$ l  v/ j/ u  N; O                                                        3 N( ~, z( y7 K2 V' Y/ C( k/ Y
                                                                ( T/ d1 Q) _( f: e5 u
                                                                       
2 {: ?2 u9 U+ Z9 n                                                                                8 ?, @) Q* H2 o" v
7 g* ^; j, @6 C/ f" F
                                                                                  w+ T1 V' H: c* a+ m
                                                                                        嵌入式 C 語言的自我修養(yǎng)
1 s# z* C* a% b' F% @  d0 u                                                        9 o) R9 d$ T7 N0 ~; ]/ }
                                                                ) ?& U( T7 w3 e, R9 t
                                                                        : t* I8 O/ d% a$ T+ g
                                                                                3 Q0 G8 i& E3 |6 w3 [
0 e* ~" N+ Y; `$ U
                                                                                2 X/ |, j. C! q9 x: N
                                                                                        被 char 類型的變量坑慘了!
" T7 H" [- {; J1 H8 U                                                                1 T& B6 h; ]5 E% K
                                                                       
* h8 u) G6 _7 M% R- w- }                                                                                4 @1 x5 o& @. j3 y- g' u2 V
  e  s0 m: g6 a
                                                                               
; [; @7 R1 Q5 e9 {8 {0 f( a                                                                                        嵌入式 C 語言知識點,動態(tài)變長數組* V4 M9 |7 D9 Q
                                                                               
3 b% D" C. l$ z( u' g9 {                                                                        6 M, g" L) Y! I1 R4 z
                                                               
  `! Y! D! I8 x6 ?) b                                                        我是老溫,一名熱愛學習的嵌入式工程師
) S, Q% c3 T5 P2 l* J關注我,一起變得更加優(yōu)秀!
回復

使用道具 舉報

發(fā)表回復

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

本版積分規(guī)則


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