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

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

搜索
查看: 133|回復(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í)的嵌入式工程師
4 N8 _# }$ k( S" q4 r關(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ì)顯得很亂。
* E  |: j1 ~. }. G! P使用過(guò)Linux的童鞋們肯定知道linux系統(tǒng)無(wú)法直接操作硬件層,打開(kāi)linux或者rt_thread代碼會(huì)發(fā)現(xiàn)代碼中都會(huì)有device的源文件,沒(méi)錯(cuò),這就是驅(qū)動(dòng)層。5 q* v& z. h# }+ [5 ^$ a9 e

( O9 `7 o  h( |, C二、實(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í)間。
" c; ^* t" U% H! x( \8 J- r- x三、代碼實(shí)現(xiàn)國(guó)際慣例,寫(xiě)代碼先寫(xiě)頭文件。rt_thread中使用的是雙向鏈表,為了簡(jiǎn)單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
0 H/ ]/ f! y$ w/ |頭文件接口:
; D) A( P) E# \2 u( j$ O本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):" O* |4 Z. j; }) v2 S
/*6 u$ F! N1 v& o2 p5 |
    驅(qū)動(dòng)注冊(cè)5 H( i. X! w. t3 N/ V' W/ @( C# a
*/3 k5 w# }7 q+ g7 h+ C4 g+ E# g
int cola_device_register(cola_device_t *dev);
0 s, h( v' C! O/*
- ~8 r. g$ w$ m- [1 @    驅(qū)動(dòng)查找+ U5 n* H. G3 U& l5 D1 a$ m
*/$ W- B2 {5 W/ T  k$ j. U
cola_device_t *cola_device_find(const char *name);
: ~5 M5 u8 v1 w8 ], F# s. P/*, t) _# w# T8 w+ S" o7 v8 o3 c
    驅(qū)動(dòng)讀- R  s8 ]* @2 b5 @: m& H* B
*/
* ^8 i/ v: `% V+ O1 X2 Uint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);% N1 Q1 r% d6 M4 w& t( O
/*
: T! |8 U8 M6 M* l1 w/ r" T# X) c    驅(qū)動(dòng)寫(xiě); T* z7 E4 D# }, [' D8 R
*/
3 \/ ~7 T: w# w$ D$ o- |6 eint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);7 K' J5 Q- m5 F& [7 y7 \( Y
/*
) U! ~; l. n0 a3 ?; a" A: {2 H! G    驅(qū)動(dòng)控制
, g5 J6 ?! A# x. ]5 s- g% ]*/; n4 y% s3 F" \5 D8 L; @6 O
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
! R8 U4 x/ l9 ?; N! r! T  u#ifndef _COLA_DEVICE_H_4 i- F% S  t. O6 {# F
#define _COLA_DEVICE_H_
; F8 Z5 A! p+ B" b& m9 f! Cenum LED_state
8 \/ u' T8 r8 v8 B3 h$ O{- q' [, F) f1 [( ?' h
    LED_OFF,7 v# u0 G! r- \8 ~- I8 V: s$ Q& u* Q  i& K
    LED_ON,5 d3 V7 C- r8 b
    LED_TOGGLE,8 s. _4 d  F& w" v# y0 b
};
' E6 l$ h% U% g1 G7 Jtypedef struct cola_device  cola_device_t;
$ u8 @" C4 }, U$ @* z0 e: q" M( rstruct cola_device_ops
8 ^/ z( z) U9 ]! J; s! `{
) F: l* d( M4 _2 O% Y% y    int(*init)(cola_device_t*dev);
9 K1 h3 h6 F% c# a" G2 s    int(*open)(cola_device_t*dev,int oflag);
: V/ C/ F2 m1 u  e    int(*close)(cola_device_t*dev);
# Q) ?; R* a( p8 H  W; q6 v    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
3 \4 t6 \( Y) Z0 S# q    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
+ W9 h! h" t/ f; B# T    int(*control)(cola_device_t*dev,int cmd,void*args);+ Y4 i' _3 d, O4 P4 i
};$ F1 Y+ f4 K! C1 Q% o3 m
struct cola_device0 r# p$ K- \+ a* r3 h
{' A! R  q) Z. {9 s$ G" O" S
    const char* name;
0 U! Z' B6 I2 t  U4 s    struct cola_device_ops *dops;
+ [) J) H, h7 F9 h/ c7 {    struct cola_device *next;. w% M1 q4 T8 \' |% r2 S: ~
};& V3 i* i; h0 ~
/*
$ H$ t- t) _- I( N6 i1 o    驅(qū)動(dòng)注冊(cè)
! r7 e- v  ?) I*/
" X; l, D% G$ Eint cola_device_register(cola_device_t *dev);
! j# R, b5 [7 v3 E- {% S/*1 i! f# s( a" ~: s8 J
    驅(qū)動(dòng)查找
  [5 H% S5 t" N1 f9 V5 g*/
; ~- @7 S) J2 S/ _+ ^cola_device_t *cola_device_find(const char *name);  ], A+ u9 D  p4 \7 }  c/ }
/*
, B8 X, Y7 R2 |+ a& U+ Z; I6 C1 d" q/ l    驅(qū)動(dòng)讀  Y: [- V9 u" i* I7 N
*/: x8 a9 @: u! ]: W: n$ R' S6 U
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
. r- q) s0 z, s  @% `/*# A" J( Y+ j% [0 `0 f1 B
    驅(qū)動(dòng)寫(xiě)
; a3 o% l- h, B7 E# E2 }*/% q; P0 b( e/ e) \
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
0 {6 {- B& I* `: n0 f& M' n/*+ x. S2 R8 h5 m- Z( {
    驅(qū)動(dòng)控制
- I* T4 [5 b$ H*/7 R6 f3 e8 j( N% i
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);0 n. l$ D. \0 P; q' o
#endif 源文件cola_device.c:
( d3 ~* C6 v  J9 Y3 Q9 `8 O' x2 `  p#include "cola_device.h"5 j7 V# d* o& N8 n) Y
#include
3 i) U1 ?5 j" {/ m* I; s#include
/ ^# O& a9 @+ r$ Ystruct cola_device *device_list = NULL;
1 O3 G5 W8 `0 K! i% ?7 i. D/*
) F* v$ ~% T% Y    查找任務(wù)是否存在
4 q0 c2 p) C! w! G( q; [' ~/ t# D*/' l: b" O7 v- j+ L) f$ F
static bool cola_device_is_exists( cola_device_t *dev )
7 ?9 k" U' A' t& H/ {{
. P, G3 B, p/ O* e    cola_device_t* cur = device_list;
8 p+ o' m' {% A' i    while( cur !=NULL)
+ I) u; `2 c4 ?5 F+ \    {
0 r2 _9 d. X: c% f4 k        if(strcmp(cur->name,dev->name)==0)9 }; v  b5 c1 v- U$ [
        {  V2 I* W% C& ?1 F
            return true;( t% r" E) b% \% }# d1 k3 c8 v5 t
        }
7 F* |5 T6 d! u3 r/ n1 M) V& ~        cur = cur->next;+ h; l. Q  T- S- y- |  `# \
    }& J* n! W8 c0 c' ~
    return false;& n5 ~$ i% j# I
}
; ^6 @( ^' j. Kstatic int device_list_inster(cola_device_t *dev)
3 J0 n- @- H1 ]" ^4 ^3 M{4 {6 p7 p  ^& K3 m. H( s3 A
    cola_device_t *cur = device_list;% _3 s+ w! {& s" C& t6 g5 J
    if(NULL== device_list)* _  A; r" J4 @1 E  T: h
    {9 Z$ ~& `5 V; c& j$ v
        device_list = dev;
. s5 E' f  X2 [9 X: j$ }5 a        dev->next   = NULL;; y2 Y* }, l2 k$ c& g, f
    }- p2 w5 Z& i" W+ w
    else9 N# }3 J) q( h2 p( T+ z' F
    {
' F0 `* w3 ^2 ^' z; ]) C. P7 [        while(NULL!= cur->next)
. e# z. R7 N* m2 C        {  w# [" ~3 q1 ~3 j$ W$ ]
            cur = cur->next;1 V  b; w8 @# V, t- ~
        }, ^# Y! \: R( H" v# D
        cur->next = dev;
# E0 Z' H( x# |1 @7 `6 n3 C        dev->next = NULL;
6 m$ e4 s4 L# K9 @8 P    }
' D" F& N5 b/ D) w6 U+ W0 c    return 1;
1 K4 T' ~5 X  G) U9 n( k4 `/ ^& n8 s}
0 s# A+ G" y1 C/ t6 Z. \/*: V( d0 m/ X4 P' q. b5 R
    驅(qū)動(dòng)注冊(cè)
! d: [- D: ~9 m% R*/+ Z9 i+ P5 T  S5 G5 F/ ~. s
int cola_device_register(cola_device_t *dev)+ a/ ^/ R2 j- d( ~( y, @, Y+ w8 \
{! e! k  d# S3 h
    if((NULL== dev)||(cola_device_is_exists(dev)))
' l" m3 U8 S* g; [    {) r$ H, O7 x, W/ H
        return 0;9 ~5 D1 g( ]5 j+ t1 q1 c/ [" q
    }* t' C$ u6 G$ }: _
    if((NULL== dev->name)||(NULL== dev->dops))
8 z8 X$ F1 _. Y- \( c: N0 _) N    {
+ B+ Q+ F2 f: F* u: G. W        return 0;
; w- r: O; I% m! S7 p- K  [    }
; b  d7 D. T7 o/ ^0 N    return device_list_inster(dev);
- w8 h" d9 W; L6 h4 I}
2 U/ S! M; m( y4 T9 ]+ P+ c# S/** ^4 P& l  ]9 v% @3 H" J! `
    驅(qū)動(dòng)查找# e, C" G6 @! ?
*/
; T) {. F8 }3 X3 y; [0 R7 B# t5 _cola_device_t *cola_device_find(const char *name)! }% s$ a; F! @1 e
{$ M$ Y$ J& n% m1 v
    cola_device_t* cur = device_list;( @: V; J9 E& Q  u, Z9 C
    while( cur !=NULL)
% ~8 f9 E+ c8 h! s/ D# y    {
' `1 n& R, J! D( H1 z! L$ K        if(strcmp(cur->name,name)==0)9 L8 `( j# z+ h) M5 d4 T
        {
7 o/ D! e" \( T0 }5 m2 _) c7 f            return cur;
6 Y2 e5 j3 w& B        }5 V7 ?7 N# t; X9 q9 X
        cur = cur->next;. R. s% h  h3 Z6 X2 {
    }
4 k- m; @; H; ]3 z- W    return NULL;/ y, P9 v' x3 h, }7 X
}/ }* [7 T. d8 B: A
/*
/ P# h) f* A: Y3 b  l; T$ I    驅(qū)動(dòng)讀9 H  Q% u. M9 U
*/& N; M' x* w% Q+ n+ W; i
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
; J7 Z  y# ]" k8 l{& ?. H! o1 p6 Y) H
    if(dev)
, L' f# @  m5 c7 [6 Y+ t: z/ ]  f    {/ J: {- L3 Y* H' ~
        if(dev->dops->read)
/ v5 @: a( Z- f5 w' U        {
. \+ k5 p4 `0 k, w  V  ]            return dev->dops->read(dev, pos, buffer, size);7 \% R' O/ q8 w$ ]3 y$ f0 W
        }
' s& t% ^* ^& a6 q* l, P    }- V7 p$ J/ O) I( b% _1 h5 f
    return 0;0 @! H+ h5 W0 F+ x" D0 C
}! O$ V4 e; G  \/ S" \
/*% b+ D0 U: }2 r  @
    驅(qū)動(dòng)寫(xiě)
' |8 j) v; _1 R2 @*/
7 O( `2 U. A* p3 ~- o. qint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
7 Z& F" i) X; T7 z# D6 N* ^9 w{/ a& g7 a$ L0 S3 A
    if(dev)
, r0 j* F2 `) Q, U1 Z4 ]    {" S" B, k* {9 t9 y7 \
        if(dev->dops->write)
! W( F3 M5 n2 A4 {7 L        {5 U: R# P  n/ ?5 b6 S0 i; k
            return dev->dops->write(dev, pos, buffer, size);' C3 u  o8 j6 z" B
        }
% t9 W* {0 b( W- M; _: j2 h    }
1 i" s9 x6 R9 y    return 0;" H4 Z% P/ I3 g0 z* e+ C- r
}
. z/ {" v4 ?8 ~" h0 y/*2 u  y8 w& x- ^0 x6 f( W4 [
    驅(qū)動(dòng)控制- |6 C0 |( g; p$ [+ k( ?# t' V
*/
/ V1 S, B& u: C$ nint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
- q7 T- {- }1 ]1 E{8 X2 q' u  Y: z7 O6 D/ P; g5 c
    if(dev)1 W; Z$ K# I- O6 Y$ V
    {) F! t8 s; r* I
        if(dev->dops->control)2 y( P: t! n6 b, }6 o6 S% g6 g! ~! D
        {5 K& Y" }2 O6 v4 T% f, u
            return dev->dops->control(dev, cmd, arg);
& H4 Z+ T+ h, f/ U$ y, Z; E        }; a) k& z/ i7 d
    }
( X$ O7 r' Q5 O5 e, x1 h4 [    return 0;
. i% k: H7 l- I" A( M0 @}硬件注冊(cè)方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。
5 \# p3 I0 s4 `#include "stm32f0xx.h"
+ S" i6 ?3 v4 P' H; z8 M#include "led.h"
" v  p! l4 b* d; }& D: F! [0 k#include "cola_device.h"5 |6 u/ {! h( L" H, `  E( H, q& x
#define PORT_GREEN_LED                 GPIOC                  
. Z0 L8 ^0 C4 }#define PIN_GREENLED                   GPIO_Pin_13              
4 }. V0 H2 Y. h9 I/* LED亮、滅、變化 */7 F8 C5 ]  I7 `
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
% l8 a4 v7 k0 G: x& D; W#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)4 M5 c( f- u% H/ X* A( G" L" n1 s3 g1 D
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)  t2 Y1 t  z9 J) d
static cola_device_t led_dev;
  y, c' V; W% Gstatic void led_gpio_init(void)
% Y4 @2 m4 O. X& l7 }$ P# U{1 c. k- F; k9 I7 p3 ^1 a/ e9 S1 ^
    GPIO_InitTypeDef GPIO_InitStructure;' _1 n: b2 r0 k- C8 b
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
2 Q& a& w- M  L4 @7 T! o" d- g    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
$ ?9 w8 H# N0 ~2 _    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
) ]- ?: `; b6 Z2 t- s! U: c    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
. N4 I& p3 K. l% T* T7 N/ _$ x: d    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
) f( _: J' q+ B: }1 z4 z    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;1 c+ z, u5 k% C
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
; a* R" O6 K* H4 l/ s    LED_GREEN_OFF;
5 a1 X5 @3 x& k/ E}& z8 h' m0 V9 ?$ v' P5 f; A
* ]  O/ i1 C: s
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
7 y0 Z. f$ J3 _# V, [4 j. ~1 {{3 B4 V1 `; r; Q
    if(LED_TOGGLE == cmd)# `: `- f( l. o7 [  y& S7 l% z
    {
6 Z/ n# |  I6 C        LED_GREEN_TOGGLE;
( Z" f  L8 S9 L( d% X! s    }
6 ?0 }: H. K. O+ E9 i- U* p    else) \" Q6 n+ g$ t* t' B
    {
8 c& I* h0 I8 ~5 F6 l, y& Q9 s    }
% t0 L9 Y9 ^5 O( v    return 1;# v5 e3 d0 y9 P% J3 R+ y
}) p6 [$ \! _) h+ O
static struct cola_device_ops ops =6 L3 J' o3 O  A: W6 K7 r! y
{5 G/ A3 U+ V: [' t' t
.control = led_ctrl,9 N5 A' a! ~" v. a
};
- Y) f8 @  |. ?, z) dvoid led_register(void)! n: J. P0 A, f( s& t7 S# `2 v1 o
{6 _. X+ f, u: `9 E( `% r9 {2 k! Q0 z
    led_gpio_init();$ K. x0 c' }9 @0 {- l
    led_dev.dops =&ops;) C" F/ D1 S$ P  `: P3 b
    led_dev.name ="led";+ t8 W( P# d. k2 l0 M
    cola_device_register(&led_dev);% v  H  |) L3 N. T
}應(yīng)用層app代碼:" h$ l/ }+ x' R2 d8 j+ N+ o; z- Y
#include
3 h8 E2 H# V5 k4 y* R/ J#include "app.h"# |0 v$ p& D: q; D5 W& G6 a
#include "config.h"
5 M* `; m4 a( S4 d$ U#include "cola_device.h"6 b1 I7 f, W. D
#include "cola_os.h"7 _7 |4 f9 J2 v( e# h9 G) h* O( `3 G
static task_t timer_500ms;. n8 s4 s! w7 `) c
static cola_device_t*app_led_dev;
# q8 j' C/ S' a4 B, j//led每500ms狀態(tài)改變一次" i8 z! ?. ^2 e: _- w0 `6 k8 l
static void timer_500ms_cb(uint32_t event)
6 @$ ^4 T2 g3 z% ?/ I/ I% q% D{/ M9 C0 U! D- L! F$ K# S
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);$ V2 s3 L9 o3 ?: u" Y5 q- b$ y
}
, G& b+ R0 L( W3 tvoid app_init(void): M  F0 q' L. [$ W
{" n1 d" d& C/ F) u$ h, A8 T
    app_led_dev = cola_device_find("led");& G6 Q; E0 g! n9 O" F
    assert(app_led_dev);
0 h6 B+ \2 w; z    cola_timer_create(&timer_500ms,timer_500ms_cb);
' E. I% }. S4 U+ J$ g    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
5 e' m2 E4 j) q5 `) I6 k" Y' Y}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。5 I5 ^, k6 q/ B4 W7 H8 K
四、代碼下載鏈接https://gitee.com/schuck/cola_os
  @8 a9 j- {  Z1 G8 m
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/1015127226 v; ]0 ?% x9 G0 h9 p+ U
-END-+ _$ g$ H3 F7 M4 Z
往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀
  O2 n2 N8 a0 X, u                                                       
1 f. V! O& Q/ V, Q: `  @( Q                                                                # Y2 f$ a# V- j! e! R
                                                                        ) J! T# e  d( P: e
                                                                                6 U* y5 J  E: Y6 p7 ?
/ n  `% B$ `5 U/ v. y$ `; ?
                                                                                0 j$ E" ?" Z. `/ i9 B8 |: |( z3 t$ ]
                                                                                        嵌入式 C 語(yǔ)言的自我修養(yǎng)
6 L; p9 m% X2 c) B6 c" v                                                        ( x  ^4 i$ \0 j- o5 t) G0 T
                                                               
; D, t) Q" n( T& N& z( Z$ Q5 X# q                                                                       
5 t* p! w2 S; G, v                                                                                + S; ~" s+ S" \  \4 ^$ O

' I" o+ n) y, z; o5 x. M; y9 F! h                                                                               
- R3 _$ `0 b0 L& \7 t                                                                                        被 char 類(lèi)型的變量坑慘了!2 q! @/ ^7 I! }# E
                                                               
# I: E8 U0 T1 o                                                                       
0 e3 ^5 D, o8 y                                                                                + G; I) h" u( @1 f
" k/ H9 l6 E$ R; C
                                                                                : X! e) f0 b  X! Y
                                                                                        嵌入式 C 語(yǔ)言知識(shí)點(diǎn),動(dòng)態(tài)變長(zhǎng)數(shù)組
/ F1 m$ M0 S2 A3 q3 W                                                                               
( j2 _2 \2 y& {2 y                                                                        & b9 W5 ?5 l! S1 G  G! G
                                                                2 b2 z1 A4 q8 w( n
                                                        我是老溫,一名熱愛(ài)學(xué)習(xí)的嵌入式工程師& Z9 {% ]: _$ b8 z
關(guān)注我,一起變得更加優(yōu)秀!

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

本版積分規(guī)則


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