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

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

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

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

[復(fù)制鏈接]

437

主題

437

帖子

96

積分

一級會(huì)員

Rank: 1

積分
96
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
- n. y$ D8 N0 C% i關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會(huì)發(fā)現(xiàn)應(yīng)用層中會(huì)有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來時(shí)屬于硬件層的,如果軟件層出現(xiàn)這些文件會(huì)顯得很亂。# h6 Z9 p# I. j) U* R
使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會(huì)發(fā)現(xiàn)代碼中都會(huì)有device的源文件,沒錯(cuò),這就是驅(qū)動(dòng)層。  ]# C. `% _9 Y0 ~

1 v( Y9 w& C6 o4 B- B0 }" a二、實(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í)間。
' j8 A- _* k. |三、代碼實(shí)現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
6 d/ d6 {7 F2 Y: G$ Z9 V頭文件接口:9 }" c/ {7 [: Z( Z% ^
本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):# u% E, l4 C$ `- ?
/*
) b( D7 e0 s$ }, u* Z    驅(qū)動(dòng)注冊
& u, n( _! b5 }*/
9 \6 u6 R+ p1 J2 J& ~% z$ dint cola_device_register(cola_device_t *dev);8 y) T' X3 ^1 V2 O* _, n4 w
/*8 K9 i4 m# c( C2 u8 M* P, I
    驅(qū)動(dòng)查找9 I6 u+ k8 q" ^$ P' U" K' T3 }
*/; p* [! p% d1 L, m( i) m9 E5 G! B
cola_device_t *cola_device_find(const char *name);
' t* E+ ?, i$ l( g/*
* B, g7 a% i' }( N    驅(qū)動(dòng)讀# H5 v5 j( Y5 g/ X5 F
*/
0 }; S) b% n4 x8 I1 Z7 Wint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
( T3 Y) m( M/ u% q$ o/*
% g3 b: d5 e+ `! I5 O7 f- \# a1 X    驅(qū)動(dòng)寫
. V- d0 b' n+ @*/
1 w5 d  r, @# e, h0 S; x; Oint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
& z- K5 {3 _& G8 v- a/*
4 [6 ~* N* f: S    驅(qū)動(dòng)控制
- F! e( J9 `4 J, v' m- k9 {*/
6 t8 @% j$ l- g' Fint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
  P; J! k* o, F% ~( b7 Q* ~" Z#ifndef _COLA_DEVICE_H_
6 o/ \1 A" Y6 l9 }1 P#define _COLA_DEVICE_H_1 C  H/ Y6 w2 b
enum LED_state
% C3 @+ [( ^6 U% K, l7 w% c5 j{
$ c, X  j& x  Y6 ?% ^    LED_OFF,
6 q- E% R6 J8 w% Z4 p  C    LED_ON,
! Q: O4 x3 t: D: ~8 l( k* L6 }$ M    LED_TOGGLE,
$ S+ R; W% n' v5 m, g0 c# ~};
  R! {# K6 ^9 z/ F3 k" m# z+ q4 A; n- Gtypedef struct cola_device  cola_device_t;3 }. ]; d! R, r! o) q
struct cola_device_ops0 j1 A) Y  Q9 S6 c% w9 ~7 h
{1 E9 ~/ d! i3 Y0 B: ]) h4 _0 w
    int(*init)(cola_device_t*dev);. G7 T0 B! [0 P* J  M/ h
    int(*open)(cola_device_t*dev,int oflag);
# `/ O) i4 n4 s$ q2 a. ?. g5 K9 R    int(*close)(cola_device_t*dev);# X6 e- t4 p" R! v, I' {: R
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
! @4 {/ z: X4 Q; P; Y    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
( B7 S$ o; O( `" J8 o    int(*control)(cola_device_t*dev,int cmd,void*args);
; q! n( H: ?) k; v" X. \};
& Y) _$ {0 V- p& Ustruct cola_device& L  @/ D# ]# e' `4 I/ |' O% f
{
( l2 @3 C4 j: P4 I% z& o    const char* name;
0 H! N6 D* X- Q4 s7 {4 t    struct cola_device_ops *dops;0 ]; s0 E5 C* j1 I  i
    struct cola_device *next;( ]. R9 ?% S$ r, J/ e
};
; P( N( W, p, e* h/*8 n- c/ d+ o  Y$ x* ]2 h+ [( h  C
    驅(qū)動(dòng)注冊
  x4 e0 g4 B  C8 E% u, c*/
0 E! N6 `2 E/ m1 {& S5 Pint cola_device_register(cola_device_t *dev);6 n# e/ M% ~. K8 |, q
/*
4 |" ?, U; a) s8 l9 v    驅(qū)動(dòng)查找
* M3 g7 s* e2 S' [5 \5 n*/! W% H2 ~+ o' F
cola_device_t *cola_device_find(const char *name);, C& a! Y- n+ E- d0 H
/*
0 k) [# ^- \4 l! _: V2 {3 \    驅(qū)動(dòng)讀+ K' t9 t; S+ w  L* n1 m7 `
*/7 q; c  I4 j, k6 ^' _# L& B
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
& l  ?* N7 I& f' n2 p/*
: J+ f' Z! D' H" \: d( c    驅(qū)動(dòng)寫
) y% D" x7 l# B$ y' v1 G*/0 G$ Q! {0 O5 ~- `+ v: @. H- o
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
; ]& A- y0 B2 y- A" F; ^/*
/ T5 M; O6 N0 \# M. I  i  l    驅(qū)動(dòng)控制
. c( f* l) u( z2 ?9 {*/
- E* A9 v& Y0 l7 ^  n2 Z( dint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);/ Y$ l! m, t. v5 V2 }: m- |
#endif 源文件cola_device.c:0 _& l- X# ^9 o5 C
#include "cola_device.h"
( g" C  @2 r' H5 F& V( a#include
3 e7 q) `' E% b# P5 G5 y5 ~. ?#include 7 M, r3 T6 c: F; K, U
struct cola_device *device_list = NULL;
4 ~& U* \0 Y  O/ B2 e/*
/ c% S. ?% O& l: `5 S    查找任務(wù)是否存在) T$ f- w- v. y
*/, e; G" H6 W$ ~% A
static bool cola_device_is_exists( cola_device_t *dev ). P' L0 H3 t7 @  P1 u  W
{
4 f& @, t7 H, j0 J: D    cola_device_t* cur = device_list;8 V" @0 m  K9 U: Z
    while( cur !=NULL)
6 i% w- m* Z* \9 A! t7 F    {
, N2 [- ?4 F/ S  _9 `/ W2 Y        if(strcmp(cur->name,dev->name)==0)
8 [7 J3 n5 s0 I        {
7 A. f) h3 o7 X  q( S            return true;9 j4 q2 C6 C5 m# h1 F; C- [: E3 x% m
        }5 Q! q7 Y, h/ S9 G
        cur = cur->next;4 v- V7 C' y2 p8 S; u, f
    }' }. S+ m4 q2 o
    return false;# f) Z1 H2 L/ q* Q7 u) n. b
}
, k' ^+ Z" `+ a( v9 p9 V+ f& Fstatic int device_list_inster(cola_device_t *dev)  M" T+ }) A' p  m( b6 p
{
+ v) n3 z* z8 {& j4 B8 f    cola_device_t *cur = device_list;8 Y# g  `- h- M
    if(NULL== device_list)' e# j6 @) {8 r' g( [9 h
    {
$ F& f  a; }1 }+ W3 ]$ C/ k+ Z        device_list = dev;( [( j. R: X) W* f! b* U
        dev->next   = NULL;
3 H" a* ^- r* b; i4 _6 k) `    }
/ v2 R1 }, f$ Y) i% g8 ~    else
/ O) G0 y8 @5 j4 [& u0 `    {& s. Y' @/ a" X; G
        while(NULL!= cur->next)1 h6 O0 a* \$ r/ j
        {, }0 ^6 _) J8 N! ?8 i/ v
            cur = cur->next;# W$ Q7 p- a# f
        }! n+ }5 Z# H8 J4 c5 e: p$ C
        cur->next = dev;8 Q  T  g; b0 F6 B
        dev->next = NULL;
6 x7 H. p6 L! q& I% |9 j; z    }: p- |7 y- ]4 B7 k: f
    return 1;# P$ u! J/ O# X
}
4 j8 z# ]( q5 l/ M7 Y/*# r/ V, O. j% c
    驅(qū)動(dòng)注冊
3 A! y# [0 `9 t, U- T9 t4 u3 s1 b*/
* x; U3 H. U8 C- a, h# ^; @- [- [* Jint cola_device_register(cola_device_t *dev)$ x/ G1 `# v) f, Q9 ~+ r
{- d, }: I# Z6 z6 f" P! I
    if((NULL== dev)||(cola_device_is_exists(dev)))( F9 K& `+ |4 a6 V& Z9 R
    {! J3 A- y$ F# W  H) B9 }
        return 0;# G( Y5 z) d9 e9 S' _
    }; m8 x5 b  s) ^! ?! @( h) o
    if((NULL== dev->name)||(NULL== dev->dops))% z) s  J5 s' Z3 e- e2 [8 L
    {
! s. s" m: f+ L: _        return 0;
! F% ?- P6 o% q4 _    }
+ U' Q, Z1 T/ f' y) @7 _    return device_list_inster(dev);" V3 Y9 z: v& _1 C, Z: j
}
& c8 \6 }+ T0 r% u/*0 l& ^, r2 S! C# O* I; H% z
    驅(qū)動(dòng)查找
! s+ x: u: t3 u, N2 e, M# \*/+ H0 g4 v* V1 P0 x9 u: W" S2 H
cola_device_t *cola_device_find(const char *name)6 ~4 R5 x- Z' _; Z0 D4 B
{5 w7 V* v- X( ~! }3 y  r7 X
    cola_device_t* cur = device_list;3 M5 R, v' |, n, Z. i* m8 w
    while( cur !=NULL)- i% M6 T; z  c" j! n$ U0 p& c
    {# B/ O9 B! S! w7 Z9 n% r& t
        if(strcmp(cur->name,name)==0)
: b" w5 s5 j) ^5 `6 Q        {
6 F" j% F, ?9 f, j9 q            return cur;
4 G6 r& P# A( T6 n        }
! p% C# t! b4 W6 p+ {        cur = cur->next;& c- z1 }" g) c8 T& o
    }5 q( J" s+ y% b, c
    return NULL;
( O3 E0 M0 s, A( x! X7 _& I" Q}
+ W1 J. a, F* v, v1 w, H" a/*0 `. h1 a6 d, \7 E; U) N
    驅(qū)動(dòng)讀
0 r- a) l% L5 ^* q! H: W8 N& U*/
; n+ X' \' F& kint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)9 K; X; r, H) U" X# d, a
{" e& h  Z8 V$ I# I
    if(dev)
/ Q. b* e! [' j) U    {
  o. ^0 Z" Q/ [& w        if(dev->dops->read)
9 v' m4 |- {$ Y0 u3 _        {
- P7 B( [6 [! l$ J0 X9 o            return dev->dops->read(dev, pos, buffer, size);
8 u  F! b5 R; s/ f; F        }
  C$ N# ]! w) X- ^  m& N# M4 L/ C    }
( x& ^" g+ ~- q/ O1 y( P$ X    return 0;" Y5 K! `8 j/ {$ J; n' Q
}
1 D$ ?# l' ^5 Z/ s* n/*
* }4 y2 Q- ~/ Z: U: _  m    驅(qū)動(dòng)寫; T5 H- ^- l; F  B8 Z- ]" N/ r
*/
% ~4 q  n, {  ?/ g/ ?( C# ?int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)& e, m: y; Y% ^, X& d
{4 I. t% X3 K" [! {: g  s+ w3 B
    if(dev)
* Q2 n/ C. v0 Q' v- x    {$ K1 I' o0 o/ }# X
        if(dev->dops->write), D7 R$ f' i" z2 T7 D  p/ `
        {
. P2 I# e) r% s0 Z            return dev->dops->write(dev, pos, buffer, size);- E' V- Q5 {" ]  K5 Y8 U
        }" \" |5 V9 a; ]
    }
+ j1 s- Y' X$ q6 J$ x    return 0;
+ U0 H0 D/ T* R# s- C# i}" \6 I# q3 l) l  t& _3 w' r& _1 z: E' ?' w
/*$ l4 P8 W+ v6 N
    驅(qū)動(dòng)控制
& _0 p9 f8 B) z6 `3 Z*/
) k2 p2 E/ _' D# i% ~- R- j: k- `int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)9 l, a# V! ]9 F7 Z3 \& w3 D
{& y( i) |- v% V: e+ b# Y
    if(dev)
5 ?8 H% z7 ^) y  U9 n% T    {
0 T2 \4 |9 t3 i( `        if(dev->dops->control)
" @8 a% }& Z! F2 ^3 z1 T) F+ Z* ^        {  O$ f. o7 e+ M
            return dev->dops->control(dev, cmd, arg);8 {6 U! x) n- N+ P
        }- }: l: A: \3 g( g8 _4 Y0 ~
    }, d' [+ F, F" E4 y* x1 s7 |' H
    return 0;
) d8 n, a1 V/ p1 Y& P( {}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。9 P6 `" }1 C0 E) W; R: j5 _
#include "stm32f0xx.h"
! y( P4 Z2 z0 y2 L* q, [& w#include "led.h"% |; \5 p) v2 Z8 T
#include "cola_device.h"3 L5 z" o$ A& T7 h/ h9 E, O
#define PORT_GREEN_LED                 GPIOC                   ( x7 I, Q0 d( R& E$ H$ y+ m) E
#define PIN_GREENLED                   GPIO_Pin_13              # b' [& Z: o9 U2 X
/* LED亮、滅、變化 */
/ c+ k9 R: I# m/ I- V#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
5 O3 S) Q1 T/ @3 o" u" W; u3 r3 v! @#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
) f$ s2 D$ s* d+ n9 X5 J# ]1 r. {#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)  x* s( k- h+ V5 e; _, x& ~
static cola_device_t led_dev;# B4 O2 H3 m9 j1 k# ~$ v2 `& a
static void led_gpio_init(void)8 l$ R$ K# x" ]! z
{
- A, F; {( m. t7 ^    GPIO_InitTypeDef GPIO_InitStructure;
6 @- S! c: u3 t" u+ V0 ~9 K. L3 R    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);" e+ [" b$ y# m+ V" |6 ^& _
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
- l7 X# \# J5 C# w  ^9 A8 ]    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
8 F5 [2 j4 q/ U) e& z: T  |    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;; a% u2 D1 q0 w* L
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
6 e8 i! S. g3 V0 n$ p/ i( V    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
, J) {7 j9 R% _3 ?    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
  R) T+ Y8 P4 |    LED_GREEN_OFF;
/ P- U" p) h5 N4 g}
. z) O7 G3 O3 W: z; j* \- f
: `) K* j+ P, s* E1 {. i* Istatic int led_ctrl(cola_device_t *dev, int cmd, void *args)
" r% _2 M# t8 ?{$ G% ]; ]0 E) I6 ]& _& R# q
    if(LED_TOGGLE == cmd). Z6 ]- W+ }9 C+ ^1 K% W* B1 e
    {( t9 Z/ R! r1 e3 z) {; @1 v
        LED_GREEN_TOGGLE;
0 W& M% l, k1 J! t5 W  z    }' F. X) m0 N; h( L; H# B  y
    else5 G0 v+ k+ p6 d9 t# r7 l
    {
, U, J, z, e% J/ `    }2 \; [! n# P) g; i
    return 1;6 E) w" \' a* l$ ?8 D
}. z# h& s$ O( ?
static struct cola_device_ops ops =) K: \' P( \  \. v
{7 v+ O- Y. M( T6 l: T6 B$ U- u
.control = led_ctrl,% @1 }  b. T+ I& A
};
1 z3 _+ F0 g/ K8 X7 ?void led_register(void)
: Y$ K3 j8 i* x{
% ?: v$ {  |. [. @6 u& q    led_gpio_init();! R: Q; s& @- y( z
    led_dev.dops =&ops;
6 x, W' |8 m- T" n8 U' ]- G# z    led_dev.name ="led";
' z$ P) Q7 @/ y/ F    cola_device_register(&led_dev);' `; B; |7 H$ |7 X8 T2 V
}應(yīng)用層app代碼:
* n4 v( j. D7 R& ]# S% }( n0 S% |#include # y5 n$ r$ N% `+ P# e5 e; F! ^
#include "app.h"8 @" ]* H1 J/ |7 l" R
#include "config.h"
( \9 ?1 u6 ^' K, u# V$ ^#include "cola_device.h"
4 R. }  E" Q4 e- c3 n7 z#include "cola_os.h"7 F+ H: \" J. P4 W; w" K
static task_t timer_500ms;5 @. I! r3 \( I7 b& z. d- w& h
static cola_device_t*app_led_dev;
, G) c2 N7 B5 ]5 ]5 ~  y//led每500ms狀態(tài)改變一次. Y  E+ s: {/ M0 I2 ^  W' `" r
static void timer_500ms_cb(uint32_t event)
0 L# G6 V7 z( q- l9 d4 l5 T6 x' l{/ ?( b/ W1 W8 j! O6 `/ X- H
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
" ]  F1 y. \0 `" e  ?5 O}
% f# T% Y, @9 I& g  qvoid app_init(void)
1 U  c+ A( a, F+ I{9 k( C' q# S0 V( F" h" Q2 n3 V4 }
    app_led_dev = cola_device_find("led");- X5 e) n" w9 W( [3 E3 j& p
    assert(app_led_dev);
- }$ w$ x4 l3 l5 K    cola_timer_create(&timer_500ms,timer_500ms_cb);4 [/ W- B# D! D- B3 [" k( c2 k; i
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
& S3 w3 \1 r9 j9 p}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。* L8 S' R: Z; l) Z4 p
四、代碼下載鏈接https://gitee.com/schuck/cola_os
: b& C/ H( L) W/ I
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/1015127222 \( k# L$ T8 R7 f0 J9 ]
-END-  q; B4 H) B6 j
往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀
* n' \  h# k8 n/ |, v% L                                                          ~( K( o' b/ N! f% s( q
                                                                * d: W2 e2 ~, }1 F
                                                                       
" b" r7 F: p/ {; q8 x                                                                                6 P' Y7 f5 Q. L* z" `
& {  s, l, \- K
                                                                               
1 _5 B2 c4 f* ?  \                                                                                        嵌入式 C 語言的自我修養(yǎng)
3 G( f% [/ L* ]/ f2 @                                                        % }3 I& n4 O" r2 E5 j. y+ \
                                                               
$ u3 Z0 C7 _# r, ]' ~) d                                                                       
1 m3 L$ u! S7 z                                                                               
# K$ h7 Z( f6 K* y 3 b" C) B) X5 I8 F; w  O
                                                                                4 p0 @/ e& A) I1 e, \
                                                                                        被 char 類型的變量坑慘了!
" ]. Y0 R1 p4 e* z/ h                                                               
1 h, a6 Z: X+ p) r. h, I! E                                                                        6 k% T& `$ W# T; k- D" u
                                                                               
, v( L- i: U* v
8 v& ^4 \, s) y' f- i4 q* C                                                                                ; z# v0 P; U0 T7 ]3 `; U
                                                                                        嵌入式 C 語言知識(shí)點(diǎn),動(dòng)態(tài)變長數(shù)組
4 Y# B/ \, c5 h0 S5 s) P/ H* g                                                                               
3 j: {& N' R; O2 i2 m0 U                                                                        ' v" ?; m1 x( h) d4 P
                                                               
) D' X7 @% h% o- e( q                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師* _. Z" w7 m4 ^
關(guān)注我,一起變得更加優(yōu)秀!

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

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

本版積分規(guī)則


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