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

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

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

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

[復(fù)制鏈接]

437

主題

437

帖子

96

積分

一級會員

Rank: 1

積分
96
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
. Q: @5 Q  H. P" ^關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應(yīng)用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。4 Q# F& J# h5 m
使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅(qū)動層。
1 P; Y. O( n' I. x 2 }" V6 G4 Y* h+ L
二、實現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動鏈表上,在驅(qū)動層實現(xiàn)device的open、read、write等操作。當(dāng)然這樣做也有弊端,就是驅(qū)動find的時候需要遍歷一遍驅(qū)動鏈表,這樣會增加代碼運行時間。( Y" |3 d! `" y: V/ _2 s3 f  ]
三、代碼實現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread. w- M& [6 S3 a/ Y! S1 i
頭文件接口:
+ a- r3 m1 B5 i2 I7 L  ]" s8 |" b本次只實現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實現(xiàn):( Y+ V- i) }- ?6 a. D% f
/*
& Q: o3 a+ u. D( J- x" @3 G. K6 K    驅(qū)動注冊
7 o$ }' ?0 W5 V5 |+ Z*/# Y5 k4 }$ v6 U) L8 y1 o' j! W( _
int cola_device_register(cola_device_t *dev);3 Z7 y5 B! g+ o0 R
/*
' M1 s2 q3 t: X/ C    驅(qū)動查找
( Z, A" e! O$ D! h*/0 F" Q) {" E' \
cola_device_t *cola_device_find(const char *name);
: R6 m- B  p( }. e: H/ C- V1 N/*
" _9 {2 t3 _- V) \4 `  f    驅(qū)動讀4 E% S0 M' M( M# O; N  q* |2 q
*/3 W/ I: R9 F! l( e5 Q& }/ J% Z% o
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
( @9 x/ n( w0 y$ O- M) i/*2 a# @5 d/ r! _
    驅(qū)動寫
0 A/ j. `( j3 r*/1 m( V: ~: H0 W) ]( M
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
2 j9 o" P* m1 v: @* g/*
" m1 d! g2 X: ~2 K/ z5 j% _    驅(qū)動控制9 g- N8 p& O/ C$ V$ k. Z
*/7 w4 K- [4 S' g" y  I
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
# g8 [* _" O7 f6 m#ifndef _COLA_DEVICE_H_$ ?* |( _3 B7 b' L
#define _COLA_DEVICE_H_
9 {5 Z* r/ k) B  W7 G4 ^enum LED_state
; |3 {# W4 p  Z1 u{" r5 C% N. q( w3 e8 J( E& f, ?
    LED_OFF,; J7 n( |) |' T
    LED_ON,) i4 t. t+ n' H, N6 {
    LED_TOGGLE,
/ R- u6 v: M  y2 y};2 v1 Y4 P6 f5 A. X0 G8 |
typedef struct cola_device  cola_device_t;) O9 z8 n- e1 g
struct cola_device_ops) R2 @. d3 X/ M8 o3 r, V+ N3 n
{
) V" u( t9 Y. F5 W: S) k+ v2 ^! V    int(*init)(cola_device_t*dev);2 y4 ]9 @* U1 `; ^; T) a. I  `! ~
    int(*open)(cola_device_t*dev,int oflag);
; e% w+ A% y0 y% `6 ^2 D    int(*close)(cola_device_t*dev);
3 R1 L$ U; Y4 N0 H  v    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
) K6 i6 R' T" q* W2 B& o5 P4 w    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
1 d% {$ q- |6 R    int(*control)(cola_device_t*dev,int cmd,void*args);( z" H& Z, g' o6 R6 g* r( ]! Z
};
/ ]6 L6 I3 c5 e& J' Nstruct cola_device+ F  v$ w, b+ f/ j
{; T- P* q. }( P1 @4 H/ Y4 ~. [! o
    const char* name;& n* D) [, ^! o* B* Z
    struct cola_device_ops *dops;
: A1 B9 |. d/ H  k6 O- r* Y    struct cola_device *next;
! ^( j2 _+ ~7 X( g$ c};1 A/ U; A' N( t3 M" s
/*4 ~: c+ n! C. E2 F! j5 s; o
    驅(qū)動注冊2 G9 h9 a& L6 J
*/
+ `/ \9 x, C, vint cola_device_register(cola_device_t *dev);
5 C( ], A- Q/ t; `5 y/*. i) s6 Q6 j, j% Y6 o, [
    驅(qū)動查找
( U+ T) o  b( E5 w$ i8 k! f1 }*/  Y) G- n# ?! m" w2 P
cola_device_t *cola_device_find(const char *name);
8 O, W, A5 W! k/*& E* Z5 j9 W+ h
    驅(qū)動讀
( Y; q& L4 Y# z3 y$ [& n- G6 m*/
% B1 v# v6 p5 i/ c6 `! Kint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
: }  G0 c9 {# g% F/*( H& e" a9 e! g! J( d: C! V
    驅(qū)動寫
7 h# |: d- p  [  k/ D( |*/
. n# h4 B1 |  K1 G" \int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);/ v9 P/ d& P/ x
/*
2 b# s; H' C( B8 W: P    驅(qū)動控制
; J  [! ?' q  i*/% R3 G2 u( B5 U( x7 ]; S6 `& h2 u2 z
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
% E5 E- U4 U6 }- ]#endif 源文件cola_device.c:7 l9 c  M* W+ T5 r5 D
#include "cola_device.h"/ l* s# |5 P# q7 J& o0 ]
#include / w2 v3 n9 q! s2 m' q
#include ! p" E7 x& ^1 x! E
struct cola_device *device_list = NULL;
0 x" W+ D; |! t, W/ r! S/*
1 t! q, F6 l  }8 o9 N    查找任務(wù)是否存在
, _/ R6 ]( u0 {4 R*/
( _, B+ d, E" rstatic bool cola_device_is_exists( cola_device_t *dev )3 k* ?& H- C* y. u0 [8 B
{. v9 k: w6 \, \8 x" ]8 i4 p, i
    cola_device_t* cur = device_list;+ E2 q; R6 m  f4 R8 p/ U
    while( cur !=NULL)
. O" h, M5 \5 [8 Z    {* D9 |! w4 d2 y" b% i% v0 \" j
        if(strcmp(cur->name,dev->name)==0)8 H1 t6 [* y: O3 x, [. ]2 R( X
        {
/ F; |' r. ]4 a5 U! Z            return true;% a, j& ~4 y) q0 Q, U2 I+ _
        }
# g1 r0 J- H5 ]  m* M        cur = cur->next;) X3 ]0 g  w0 `
    }# `: l- ^9 ~5 O( }# c1 \
    return false;
1 s% j& g. U3 X4 k8 u}
; G3 s; m! p) |2 u2 P: {static int device_list_inster(cola_device_t *dev). ]+ f4 y( g# w- S! Y$ M
{
1 M) W$ S/ t6 ]* [) V* m4 Z/ T    cola_device_t *cur = device_list;& G7 p- z7 w% {. _# S* z  T& r
    if(NULL== device_list)
2 j7 x+ g% M) g    {
! b3 I' _7 q% [0 `  C7 K" z5 B        device_list = dev;0 c3 B9 E. ^" ]# k- t
        dev->next   = NULL;
5 ?7 K' T) T5 Z* r' U' n& W) j0 \  [4 H    }
6 y. _9 E. M" q( X9 X; j6 x4 N) t; T    else
3 _) Z1 h- E9 U0 I" E3 f, F    {1 T& @, J0 i: P5 S: L
        while(NULL!= cur->next)
% x1 C/ n" N2 `0 @; g+ I( ]        {
1 `) h$ {+ L. ?1 t  U: }            cur = cur->next;
- m0 k: H5 h  ~        }3 R: Z+ F  A: R& m) }
        cur->next = dev;
0 k" d% r8 e8 _! t0 b        dev->next = NULL;8 G6 }7 ]$ k' b6 b- p0 y- z2 b
    }
) ^4 h3 ^6 M+ Q- M    return 1;8 D: |) S% ?0 u8 n
}: k  t% |) F$ p: w
/*
/ S$ m. S  n0 ^9 _" N# ^4 w& \    驅(qū)動注冊5 R# |. D$ G! ~/ G4 w0 O! q
*/" M0 a3 O& ?- N7 q
int cola_device_register(cola_device_t *dev)
/ K% ]1 e) g; p/ u{
5 _+ O. R5 _8 Z2 H+ _- y+ h: b. b    if((NULL== dev)||(cola_device_is_exists(dev)))
8 y+ x4 K& E' R6 i9 V  \$ n6 ^) T    {6 o* R! s% a. A  O
        return 0;7 l2 J9 `/ [1 n( ~5 l  P/ W9 @- F
    }
( v  ^' B+ Y9 `9 s7 y/ n9 E+ h0 x* P    if((NULL== dev->name)||(NULL== dev->dops))+ P. x; M$ x8 ~6 H* b2 i3 G# }
    {
* e/ G3 g: g7 a9 L( V        return 0;/ p+ W8 i2 o- I2 Q, U  H
    }
& N/ M0 f+ ^6 h2 W* s" o    return device_list_inster(dev);
5 r! W9 g; @# B6 K( t; I}
% C) Z* M% |, B6 E9 F/*' ~5 P: C( Z1 W  P6 J% T
    驅(qū)動查找
+ q0 ?6 o. f9 I  P* S*/
+ S: h+ p8 }: k0 B* ncola_device_t *cola_device_find(const char *name)
5 T/ C2 Z8 n4 ^( }& U/ P{
& x- a/ ]) `- i3 E0 u* @    cola_device_t* cur = device_list;- n2 v0 J5 n% v5 Y) A
    while( cur !=NULL)
' o. n. H& p0 |- \" h# Z    {
! R8 g( F9 x  r. K8 H8 f* Z' \        if(strcmp(cur->name,name)==0)
. Q% F. s0 x7 I        {
7 t$ D  W: j' O: F  A) p            return cur;9 z# o+ ~- G% N' s- @1 C
        }
8 ^4 Q5 [0 T) A        cur = cur->next;
" A4 q* d6 Q6 S: [    }
" a; S* c9 f/ G$ j* m$ S    return NULL;
" \; C+ J& M; k}8 y5 A+ B: a& L# C) g+ q
/*
9 p; D' Z9 H4 |% X5 Y1 x4 K    驅(qū)動讀* ]( z% u& J8 {; f0 T' ?
*/
( B  n) v4 X. p+ v: t) dint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
9 |( N# P: ]* H0 I{5 I! Z( f% z) a, o. t' C' @
    if(dev)! ~6 L: x( ^  H. I; ~& V; V
    {
/ t/ J- d$ k) ^5 V        if(dev->dops->read)
  m' c5 O0 n0 U1 E        {
4 G1 }- ^& L. O1 g9 E! d. e' j            return dev->dops->read(dev, pos, buffer, size);: r! N9 T. ~2 ^6 a$ q) T
        }' o/ s. L+ J6 i
    }
9 ]1 S0 ^" M8 m, B6 U    return 0;
# S( s! w' o* v1 i}
* G& ~# f, I% x2 d3 W& m/*
' |, i7 \3 n  C, D    驅(qū)動寫. i# a! L2 u4 u) K$ u5 s) ~
*/$ B7 M8 F1 a$ l! J3 y
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)- i. f. e5 H: ?# l3 F
{  |( g) D8 ~) [4 E3 o0 X
    if(dev)- w6 I& q, e7 v
    {* H8 T2 n8 f1 Z
        if(dev->dops->write)
) G, H, Q3 i% P' z        {
0 C1 z7 ~7 p( f( k            return dev->dops->write(dev, pos, buffer, size);* f* Y; T- S: N& S2 X& `8 ~
        }
& t) y3 J: L+ X( I- g    }
! @) o) q& Q& e6 q# H# t    return 0;' I# `; W4 D/ {- U
}( q7 |2 F8 ]& D. b, i( s6 w
/** b' S& `  B* b3 h' v
    驅(qū)動控制- j5 ~6 k: u. I7 {2 g' {3 d
*/9 l4 p$ m3 b# ]. v4 U/ \: o0 u. @
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)3 \* m$ [2 @: i; g& T- S, P
{5 \7 P! j, B1 V
    if(dev)- `/ w8 E) L- M  T/ U1 E" l" Z0 d
    {" q$ Q3 h5 F0 [6 b: ~- O0 e& g
        if(dev->dops->control)4 x, S, s7 D9 o4 l5 l! Q" L: H
        {% h! r6 P( Z5 [- o  G; h
            return dev->dops->control(dev, cmd, arg);
1 h; R" ]3 D9 Z        }
" |* z3 d; }7 P& O: M    }
: ]1 C6 @5 i5 [6 y" C8 v    return 0;; p- }+ B0 {/ E( s( ^& w9 e, G
}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。
: k- }# s, ~3 _9 d#include "stm32f0xx.h"8 ~* q/ a6 R3 d: [5 n+ |
#include "led.h"# u3 E* q( T' [7 P+ @; H
#include "cola_device.h"
# `6 l( L5 h4 s$ G) {#define PORT_GREEN_LED                 GPIOC                  
4 Q  s6 O- B6 }" _#define PIN_GREENLED                   GPIO_Pin_13              
1 p* _4 ]: D  u- D( B4 c/* LED亮、滅、變化 */5 M" a$ b3 [  p& ^
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED), ?' A) l6 \0 j8 A0 e
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
3 Y! ^( ?7 a7 \% k9 [#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
# ]* f+ x- Y+ U; cstatic cola_device_t led_dev;
( ^7 F" N2 ^7 e! W( J$ S5 Ostatic void led_gpio_init(void)1 y% D& C9 K( R) f) d  Q2 a
{
+ s1 z, I/ y$ ?1 w. w$ P" {    GPIO_InitTypeDef GPIO_InitStructure;& o- c7 [" q1 b- J
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);. M0 a: H. O. C
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
+ J$ z: f: U* x' I* Y8 c& ]    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ l! L2 O* s9 v4 T! E  a/ d) I    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;+ V3 W, U* S" S& m) b
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
! m  C9 q  [# N! R6 {    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;4 z" f7 P$ a6 ^" y: y8 ~
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);5 K3 A, e6 r  ]7 F9 f: z( ?
    LED_GREEN_OFF;
; f" a" ]  X9 ^  v7 E' ~& D}8 I. x$ c) d* ], H' o
5 j/ h! o# n) u' y
static int led_ctrl(cola_device_t *dev, int cmd, void *args)4 Y/ K4 p! {1 W- p) v/ G
{# x; [) u; t  `1 k& i4 Y
    if(LED_TOGGLE == cmd)' _9 Z' b$ F- O4 M* {" Q
    {
$ |; U" ~6 s* S        LED_GREEN_TOGGLE;$ w2 f, u; i+ i& v
    }
' a0 h% j$ g' {$ w1 D    else+ r2 d5 ]& W8 c2 O' f" B% |
    {
) H2 O! f  j) ?( a) }' a8 L    }
4 \9 n0 c; Y0 G3 D- l% a    return 1;
3 }7 q1 A2 ?  w2 A' ?}5 S: z7 M( K1 a. \1 V
static struct cola_device_ops ops =
" k: a; ]* l' W1 B" H) E{- H: e3 s6 T( d1 X. U/ H
.control = led_ctrl,
0 Y0 M! V) j" {, D5 f. o0 Y};
6 V/ O8 d! u! G9 Evoid led_register(void)
) y5 \8 T0 l5 M( ]4 b2 t8 G& H2 N{
, p: D/ b5 N& Z- c0 t) X    led_gpio_init();
6 G( |* |5 F0 m% e3 K8 Z    led_dev.dops =&ops;6 ?  s8 m& G' i" y
    led_dev.name ="led";
- i8 C( U" d6 ]' ?  f/ j- h  @    cola_device_register(&led_dev);7 |- w3 d( ]5 T1 ~
}應(yīng)用層app代碼:: h' e# {" Y4 Y% }- W* [
#include
0 @; C6 }. [/ N- b5 Z: ]#include "app.h"8 F6 T& B/ {3 q) m) t! [, n
#include "config.h"; X9 F+ [  ^# |$ `: X) x- a
#include "cola_device.h"7 ^7 }, Y% k8 v+ {( ]' r& D* W
#include "cola_os.h"2 P+ s' w2 v) ?+ V
static task_t timer_500ms;/ h9 O( ?+ f8 X, F: I( x- n
static cola_device_t*app_led_dev;
/ b' g) S% d5 h! D//led每500ms狀態(tài)改變一次# |* v. ~' \6 k) `
static void timer_500ms_cb(uint32_t event)  ~, @, h  d/ S( e
{
% C# G) m" }2 M: E4 a% R    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
+ k4 p  I$ n& b, E* U  @+ ~% e/ p}
4 E; H& e1 l2 v1 [void app_init(void)- J8 [3 G& z+ _8 b% O
{
! O8 t' u) `+ h4 R3 P! `  I' D    app_led_dev = cola_device_find("led");: U6 g+ M/ y" K9 n
    assert(app_led_dev);
6 V. O6 s  H) F0 b; |' O7 n    cola_timer_create(&timer_500ms,timer_500ms_cb);+ O* t7 V+ j! K' }
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);- W! A1 i: @4 z( y0 |2 \; p( U# v/ |
}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實現(xiàn)的。
2 E; ^4 s  w# ?6 M四、代碼下載鏈接https://gitee.com/schuck/cola_os5 i- n* t4 K" d4 C: m/ o
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
& T, K% T2 W9 I$ g( `) X' W-END-
. A% Y% l( n& Q# T+ ~往期推薦:點擊圖片即可跳轉(zhuǎn)閱讀5 {# D0 X2 O! j' Q+ {2 c0 F
                                                       
+ ]' r8 C+ \; r" N; h/ B7 M                                                                - m( u6 ^( f: K7 \
                                                                       
- [& }4 b6 \& J' _                                                                                6 y/ |4 U; {9 S3 i" m- z

! P9 o  i* I' u& Q9 m: q3 I' P                                                                               
9 I0 {. M) S; V' }1 x                                                                                        嵌入式 C 語言的自我修養(yǎng)
& B0 e# o' j- S+ S) \- g4 ?, O5 `                                                        9 ^+ i# U, i$ B
                                                               
: Q# n' d* w( M3 `2 R                                                                        3 h" ^6 y9 n5 ?6 X6 V4 P
                                                                                + o9 T* X, {3 O* b& w) _; y

+ e2 M9 Z, W( M) J                                                                               
2 K+ Y1 W& N% j' n5 P9 Q+ H/ \) Y4 S                                                                                        被 char 類型的變量坑慘了!; r5 t. G5 _" o$ O9 s8 y/ Z7 x
                                                                % H! J5 ]6 }1 ~8 I- z! i5 K
                                                                        ; f1 a4 e) @8 A3 K, @% U% X: h
                                                                               
  w( a0 C# m9 o# W   a$ n& K$ J# m% I
                                                                                5 d; }" e4 I* ?' M( T
                                                                                        嵌入式 C 語言知識點,動態(tài)變長數(shù)組
' t0 h. m" ~6 L                                                                                5 C) w3 L# J+ z7 m0 g+ X9 N1 O6 g
                                                                        ) z& P& x" v+ t
                                                               
/ }/ x% S. f; ~" Z                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
4 W0 m* X( s; b( q' x& O關(guān)注我,一起變得更加優(yōu)秀!
回復(fù)

使用道具 舉報

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

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

本版積分規(guī)則


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