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

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

搜索
查看: 45|回復(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í)的嵌入式工程師
8 Q8 A. s7 ?6 f. x關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開(kāi)網(wǎng)絡(luò)上下載的例程或者是購(gòu)買(mǎi)開(kāi)發(fā)板自帶的例程,都會(huì)發(fā)現(xiàn)應(yīng)用層中會(huì)有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來(lái)時(shí)屬于硬件層的,如果軟件層出現(xiàn)這些文件會(huì)顯得很亂。& j4 S) P. g. j6 x8 r
使用過(guò)Linux的童鞋們肯定知道linux系統(tǒng)無(wú)法直接操作硬件層,打開(kāi)linux或者rt_thread代碼會(huì)發(fā)現(xiàn)代碼中都會(huì)有device的源文件,沒(méi)錯(cuò),這就是驅(qū)動(dòng)層。
3 y# f+ A: w/ [7 w, O) ]; Z
% C4 t; ^6 d: g% f; b5 f4 X& l- w二、實(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í)間。* h* R" q6 d% \% t% s
三、代碼實(shí)現(xiàn)國(guó)際慣例,寫(xiě)代碼先寫(xiě)頭文件。rt_thread中使用的是雙向鏈表,為了簡(jiǎn)單在這我只用單向鏈表。有興趣的可以自行研究rt_thread1 r5 s  L% u% p; G9 p
頭文件接口:
2 n5 w' x  h* X& k  X0 g! M8 t9 ~本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):
" \  C+ V8 M! n; P/*
& v3 T9 ?. m3 [3 o4 B- |7 V! I3 Q    驅(qū)動(dòng)注冊(cè)
8 j' r1 m  L- b& R3 H  w+ ]*/
* Z& l1 G7 T9 d9 {! ]! e: _7 i% Y) pint cola_device_register(cola_device_t *dev);3 W/ m) S6 b; e! ^
/*
9 w' B" ~- x6 p    驅(qū)動(dòng)查找
& e) T% K& G0 o*/5 C, M- t8 t5 O8 X+ N
cola_device_t *cola_device_find(const char *name);
5 h. K- ?( v7 }% f# \* E/*
1 r  T) G! F1 B8 l3 H. J    驅(qū)動(dòng)讀& y- x  X& ^- A0 `: ^
*/
% ~7 a1 m; M8 J4 p3 o+ E0 p0 Kint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);4 O1 g. t4 `# V7 H2 _& R4 j* o7 y
/*
$ |" O( w9 `# w* Z: s    驅(qū)動(dòng)寫(xiě)9 }9 Y5 H0 h. T) g" U
*// ^$ _* w$ t5 ^3 i5 d+ w1 M8 Q
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);- y! d5 y" I- c, M5 D8 ?. s
/*
) ~7 S: X+ R8 y& {/ _# ?    驅(qū)動(dòng)控制
1 ~' Y. ~5 d) o: ^*/7 |8 Y6 a0 ?3 E, f* k9 T+ o+ X5 E
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
# I. U1 d# v9 n: }, n#ifndef _COLA_DEVICE_H_% @( D  J2 S6 v& P
#define _COLA_DEVICE_H_% X; y- {; F/ ~
enum LED_state
  J: R2 R( k2 r% W# ?{
3 V9 i& ?6 H  D  v" W# h1 r    LED_OFF,$ ^9 C* [" n" ?* P0 X: w! q7 d
    LED_ON,
( A( l. L' ~! g/ Z    LED_TOGGLE,! N2 Y. Y9 _7 X5 C% N. P
};
# P7 h. S9 G1 ?' \& G% R; U: K) xtypedef struct cola_device  cola_device_t;
: s) A7 M" a6 V- `% Zstruct cola_device_ops
7 Q* K- S, B6 ~: O7 _. L$ q{; o8 x" @3 g' v9 Q3 k8 T
    int(*init)(cola_device_t*dev);, i* q+ X3 M9 }
    int(*open)(cola_device_t*dev,int oflag);
- ^' w  \3 k; s4 x2 Q4 n9 E    int(*close)(cola_device_t*dev);
+ n1 w7 F, h' b6 v& }: z1 h% {    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);3 t0 o! G" ]( D# W' Z+ L# @! }
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
2 }; X/ O) f" N/ n    int(*control)(cola_device_t*dev,int cmd,void*args);* E: f% K1 g6 A0 F2 Z
};+ `* j5 e8 t5 }. L8 [' S
struct cola_device
. o8 T0 Z5 g5 G6 j6 f{
8 y: @2 o6 @: z    const char* name;/ o/ v  Q: W  p  a5 F3 i
    struct cola_device_ops *dops;9 t7 D" e4 P! W9 G' D
    struct cola_device *next;
6 c. E  P: V  ~6 J) \# y; y};2 b& \# S; L5 o4 q) z
/*% T1 `! `0 R$ ]4 h/ G, y5 n
    驅(qū)動(dòng)注冊(cè)
5 {5 [4 L3 l, F; w& K/ P*/  H  v5 ?7 R: y4 J& h8 p( e
int cola_device_register(cola_device_t *dev);
$ \* c3 S9 X( w: U& B: N# c0 E/*( R+ @; I4 H! `( w5 G+ O
    驅(qū)動(dòng)查找
0 r, Q) M7 _( Z9 c' S; f*/
% R4 a9 B9 D, {9 zcola_device_t *cola_device_find(const char *name);; `2 c+ g* c! O+ v: {9 \
/*2 Q* N( l  c- W4 W
    驅(qū)動(dòng)讀# Y) q6 s. g2 x
*/7 C9 U; {8 U) s' ]: u8 F
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
& ]; x) N+ Z1 L, @  r/*
4 B2 |/ o( t* u1 z# o8 v$ b1 }    驅(qū)動(dòng)寫(xiě)' t) w' {+ I) k0 l/ v$ o2 [8 G
*/8 h3 s4 B) W! ?5 q' ^
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
8 C# ^" Z3 z7 D# m% x) y  w/*8 ]6 i  D( F2 y
    驅(qū)動(dòng)控制
. h- I, u# y. g* v5 A% F2 m*/
) A/ L4 V; F4 ]% a2 U; mint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
" F9 G6 m) R& M' a/ A4 e#endif 源文件cola_device.c:
% g0 c  O( E2 K' n$ j! U#include "cola_device.h"$ t; P% |" O  q* Q7 y
#include , J: L2 C) m; B5 u
#include
( E6 U9 J# ~* b7 I8 Dstruct cola_device *device_list = NULL;
$ E3 G, V# I* B0 S' r( G+ o( V/*
; o8 u" s5 h# y, X    查找任務(wù)是否存在
& a+ g  J8 \2 x3 Q; j1 [( f0 z*/$ T% |/ b: ~* d# d) |& |
static bool cola_device_is_exists( cola_device_t *dev )! i2 w' F3 @9 Z
{
6 S* _6 U) h& i. P( e$ R/ \    cola_device_t* cur = device_list;
, m( w3 O; C3 J& B$ Q5 u# \5 }    while( cur !=NULL)) l0 h  S) _; q+ d) J
    {- R2 F1 H2 ?, i# M
        if(strcmp(cur->name,dev->name)==0)
" V4 i: F) j- k        {
; F+ M- |0 x# M" H            return true;
( R- c2 R* Z/ v, J7 ~- J        }
! ?. \# X; l4 c5 S6 G; N) `        cur = cur->next;1 N+ `; W& q' s$ K# L! X
    }
/ Y; r8 u/ _0 V, a) b. F    return false;
- d# J3 T3 |1 A" L% s}. r5 f! Q) I2 f+ h" c! t
static int device_list_inster(cola_device_t *dev)% m9 @- a) A5 F$ o
{+ w# w  d- \; m% D9 \8 _) }) Z
    cola_device_t *cur = device_list;6 k$ D; s7 o/ C2 Y6 I' Q
    if(NULL== device_list)
4 S- P" V4 _6 @1 C    {& P0 r/ d" d4 D
        device_list = dev;
" [) V  V$ \) ~        dev->next   = NULL;
8 K, A% [/ w$ g- {- q) s% g    }
7 C7 N  y9 p  g    else
7 d7 U) F6 b; T0 ^$ _- j8 w! ^    {
+ c, m% e$ L! O! A        while(NULL!= cur->next)9 D. j: Q) r) [0 H8 b. E
        {  J0 R- g2 i) \; l3 c; V
            cur = cur->next;
5 A2 X6 T9 w6 L. _        }6 q5 |/ A; T- j' V8 @' S
        cur->next = dev;2 \, L7 v; f' h- o1 F% k- V
        dev->next = NULL;
* h+ S) b& s5 G& {. g% d    }4 H2 |5 e: B$ N. g9 E( N
    return 1;
* Q) F! o, ^8 V}( }/ Z8 _* ~7 y  E( w6 Q& S8 `% l7 E
/*
( J$ c2 g0 b  A; K8 {. H2 d9 b0 M    驅(qū)動(dòng)注冊(cè)
! I3 N- z5 c5 j( \$ Z*/
) K7 d7 G* O5 r2 H! }4 k) f  e+ p" ~! yint cola_device_register(cola_device_t *dev)
( @6 V* V8 e8 X9 E" |6 q{
% \" C; k! z$ `( H7 P    if((NULL== dev)||(cola_device_is_exists(dev)))
2 u) E& S9 B, p' W/ l6 r& n3 l    {. ~/ e3 [6 j7 Y, Z# @  C
        return 0;
- q+ y  ^/ R2 j* |    }) c3 T7 y+ G3 j) A+ o8 q
    if((NULL== dev->name)||(NULL== dev->dops))
. h& |0 {/ n2 l3 G    {( m1 z3 [" x) V# R) k
        return 0;5 B! V" l" h: ^7 A4 X
    }; B4 ?- _# x/ h4 e* k2 q: z8 M8 B
    return device_list_inster(dev);3 F3 k' J; O! t/ Q5 e: Z
}9 {/ I# a  c6 [8 a
/*, M1 y# W8 y/ _+ x9 Q6 a- u
    驅(qū)動(dòng)查找
8 c( l5 Y0 b; _& @! P5 L*/( R" ?% C' Q* s5 H# K4 K0 |
cola_device_t *cola_device_find(const char *name)) `6 d1 z) r) d; S$ W1 Z, X
{
& h0 ]8 V8 E% I    cola_device_t* cur = device_list;
3 B$ g3 p# d; q0 g6 P4 ]    while( cur !=NULL)5 X8 S. \# i$ y
    {5 T+ r/ W- H! [9 ^$ Y
        if(strcmp(cur->name,name)==0)8 E! C$ }! s: C% S# t
        {
- B0 r( C. q# m4 c/ C6 d: h# a            return cur;
* g% e: i: D% r; Y  l2 p' c        }: Z0 y: F4 i, u3 D7 @7 W
        cur = cur->next;* P: V' Q6 w3 l; y$ Q/ I
    }
7 |- t+ f+ K0 [0 z    return NULL;
7 M- Q. t7 X7 E5 h9 u}
0 {& Z  E) j% ?0 I. e/*) I* ?) V6 I2 c* s
    驅(qū)動(dòng)讀
: S) |, N0 `) i/ x5 v/ W: T+ \*/$ T3 R9 L+ C1 o: g) T- l
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size), F7 m- z% r7 d0 h" [, y
{
) h( o8 s4 m" H6 m; _    if(dev)
! K* ?# @/ c, u- i6 C: z    {" T% A0 o; z, ~$ h4 ]
        if(dev->dops->read); x, D7 e6 y  o5 O# P  t
        {
: g+ m% o4 u& h+ ?- ]. q            return dev->dops->read(dev, pos, buffer, size);
! M. T# m7 M. c        }
4 S  z6 A' T# p: J7 g  d0 ?    }
' `. ]% f! P" l/ G+ x& l    return 0;; U/ O1 r0 F; {% y0 ?  Y! M
}) P$ e1 W) h5 e5 i) j  e% G- M( V
/*
5 x- ^% t; R6 S5 s    驅(qū)動(dòng)寫(xiě)+ C! v, ]4 k& u- m2 t
*/
4 @) v0 k. k6 q9 l# D+ bint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
: x' i  T$ n; y1 M/ {' {( H* R& D; H' H{$ T3 p0 e  e# J
    if(dev)
, ]& t- ^4 H( D    {% S- f( Y9 ^4 d2 D' m: p2 p) B
        if(dev->dops->write)2 I/ c* \! t! H( w. i7 ?% F5 Y
        {
8 d5 X3 M$ H  c) J; a' u0 d. U- L0 H            return dev->dops->write(dev, pos, buffer, size);2 m( L( g; u/ O. u
        }7 [7 _; L0 D9 e$ ^' W2 {4 @6 ^
    }
, g+ C7 t7 t3 \  A) u    return 0;
- {' {( ~, K4 b  m9 d5 \1 B  l}
- g+ f4 z% u4 I4 S- a/*; y9 j4 ~; z, U; S
    驅(qū)動(dòng)控制( b9 M6 i; E& p1 _8 r4 m& y
*/4 i5 q9 P, E* T+ h" |0 G! }
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)" V! B) U8 ~" Z9 n6 ?: c
{6 V/ A4 w) ~5 Y+ ?4 ?$ u* F# k
    if(dev)
- i$ q  u3 Y$ n# q: W    {' Z% l( E3 ~/ L$ ~# L! A
        if(dev->dops->control)8 J  O4 o) y; H/ ~
        {
0 R; y5 [6 i# y( _- ]            return dev->dops->control(dev, cmd, arg);
0 B( t2 d/ X) e, _3 |2 E6 }- ]7 A4 ?        }) D( w- b. J9 o1 s- u
    }$ ]* s, G0 i8 [  m& c2 R
    return 0;. `4 W: z% g2 B# {( x
}硬件注冊(cè)方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。5 O1 u3 @: p$ E% t" ~8 k" E
#include "stm32f0xx.h"+ J8 m8 m3 E- B. ~( u
#include "led.h"8 T& Y8 ^: d( R$ j
#include "cola_device.h"+ ]+ c0 A8 H) u# v4 A$ x
#define PORT_GREEN_LED                 GPIOC                   # A& C0 `+ C- P
#define PIN_GREENLED                   GPIO_Pin_13              
3 i  I- N, z4 h/* LED亮、滅、變化 */7 |: \. m" W" U3 m
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
! B+ g) Z$ i# i" v4 g; Y#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
5 k6 a& H6 g- G7 ~  j6 m! ~#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)4 H4 x1 v- e) F8 v* R2 b( |
static cola_device_t led_dev;" G" ^3 d2 |' _/ Z4 O; O' k
static void led_gpio_init(void)' M; L, k& F3 r1 D( k
{( F3 S( u4 H) h0 ]( S. i
    GPIO_InitTypeDef GPIO_InitStructure;" P. P1 H2 N2 a" a% t9 N# L
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
9 R- h( M" ?, V$ h2 c5 V( P    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
+ c; \- P, u0 w2 @; G" q6 c    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;$ f( O, F9 q" @6 z
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;+ b* d4 u  U5 s  R
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;/ g( t2 u% L- \" f0 s
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;# K3 N& p1 `+ b" w9 R( H  ~9 n( C
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
3 c# P( _7 k; L    LED_GREEN_OFF;0 H, J7 e& }9 f8 r$ l
}
: c: g( f# B1 m% k# _7 B0 A  V, ~, @* j( n" k! c
static int led_ctrl(cola_device_t *dev, int cmd, void *args); g9 B' p0 ~# X3 \1 o
{
' Y) F% P" K+ V* J/ o. \1 D    if(LED_TOGGLE == cmd). D8 j% y1 }' ?. P- U  B8 A
    {5 n' M) O6 H( {0 \- j
        LED_GREEN_TOGGLE;  Q. b. k. s1 q0 ?% H. Y8 g
    }
' i4 C  A5 T. @" e0 n: l    else
% a" T9 P! F) j* V    {
0 ]( p$ O3 h0 H! F/ Z2 C6 l: c    }$ y6 h% D; c* x; t, V1 ^
    return 1;
# e: h* e) ^1 i}
/ n8 V5 a" Q/ [6 S2 X5 ]static struct cola_device_ops ops =
4 n1 n# ^# w  ?{
3 Q7 E, d" T3 L2 K .control = led_ctrl,6 G3 X- R7 |( O7 x0 w
};2 H8 B9 Y: \0 v% Q! A. G
void led_register(void)
) I4 z( m) h+ ]3 w( |5 R{$ M- y" ^+ X3 l* O0 T7 z9 E& v
    led_gpio_init();
) T+ S" E6 g6 F+ p. S! }# H% }    led_dev.dops =&ops;# Y# Y8 U5 u( Y, {* W# U
    led_dev.name ="led";/ r! D% r+ b6 _  H
    cola_device_register(&led_dev);5 Z  o1 |! Q4 d
}應(yīng)用層app代碼:
: c! ?: Q( h) P$ x+ n#include 7 m& F) [+ R  l9 ?1 P7 ?3 w
#include "app.h"
$ n* o2 ]$ y8 h  R#include "config.h"* s5 J' s0 J& ~+ h0 _) |
#include "cola_device.h"+ u. a( [" a5 t; `3 j5 i
#include "cola_os.h"
7 M8 D* B* G0 \' Cstatic task_t timer_500ms;; ]5 q. f* B( h! R3 y7 o6 N
static cola_device_t*app_led_dev;' e, n% K& f: O* q
//led每500ms狀態(tài)改變一次1 E  R! n9 V4 z' U3 P
static void timer_500ms_cb(uint32_t event)) |- y7 `3 U& I' z. ~: y8 e
{
# {$ R  }' s& H8 N$ P' m    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
9 K( [. c; K$ N) g: @8 H}& Y' l6 i- C) H$ z9 }8 s8 d! S
void app_init(void), b$ u' h2 Y0 P8 i9 z0 n% q4 r  z
{- e& `! d4 T( h/ [# D* [, c. `& @: m: X
    app_led_dev = cola_device_find("led");' B9 t" f, G$ i3 R9 Z; X- Z; T
    assert(app_led_dev);* ?2 D! |: h- w, X  E6 H0 S: l  ?! K
    cola_timer_create(&timer_500ms,timer_500ms_cb);
5 h. b2 Y0 [* N, R, t    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);* _+ v* y2 U5 }  l" s* d
}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。2 v5 t4 X. v1 b0 u8 D/ W4 c
四、代碼下載鏈接https://gitee.com/schuck/cola_os
  |3 P- \1 g! l; }4 Q9 K( u; d
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
4 k* @, }9 H. [( ~: s-END-$ x6 M/ {8 I. J/ p- A
往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀- Y, T% l2 ?6 t4 |; k; d/ k
                                                        ; Q' T; `6 }3 r, x% O, @% P9 V
                                                               
/ \0 d( q8 B8 |4 c& c                                                                        * x( h* C0 k& \. ]& V, |
                                                                                / A: n& v* [* U% z  Y9 L

% v- o0 _6 c% g% z$ W+ x                                                                                $ \6 S5 a* `0 P3 }( R- R5 X2 k) E
                                                                                        嵌入式 C 語(yǔ)言的自我修養(yǎng)
# k" t, U. E  b4 K  I                                                        ' `* I& K- }& }# k9 R. N1 Q
                                                                + @: V+ B; m' I1 x8 Q4 G
                                                                       
$ y* t  u: Q. c3 `: b                                                                                % k1 v5 h( C5 Q$ r% n+ s

! |  j# h) I8 t+ k! o+ g- x1 e                                                                               
) J& F' T! P  H' U# ]  ?1 v. R                                                                                        被 char 類(lèi)型的變量坑慘了!
; o( D" V9 @6 O$ }# x                                                               
; b6 i* ~! H2 r# Z: e                                                                        3 p  {9 B/ _; H9 l: l# X9 Z+ d
                                                                                % I& P  m$ i/ c( q5 g

& _" Z2 W' T6 n* {& u                                                                               
5 E, B. C6 b0 S$ m                                                                                        嵌入式 C 語(yǔ)言知識(shí)點(diǎn),動(dòng)態(tài)變長(zhǎng)數(shù)組0 K7 z* N, ^3 c3 f& L8 |
                                                                                ) O3 M4 _( ?' N4 B
                                                                       
4 \! d' g# P+ B+ k  o2 G                                                               
! W& m; I' N. D                                                        我是老溫,一名熱愛(ài)學(xué)習(xí)的嵌入式工程師
7 k9 y) z2 R+ e& {( a% h8 n$ p  q關(guān)注我,一起變得更加優(yōu)秀!

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

本版積分規(guī)則


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