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

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

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

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

[復(fù)制鏈接]

437

主題

437

帖子

96

積分

一級(jí)會(huì)員

Rank: 1

積分
96
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |正序?yàn)g覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師# A& z: F5 h) v$ |1 X2 c* R* g
關(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ì)顯得很亂。/ `& F  L; ]' l! p
使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會(huì)發(fā)現(xiàn)代碼中都會(huì)有device的源文件,沒錯(cuò),這就是驅(qū)動(dòng)層。: o, c: I3 z. c, d3 ~3 z

( R! d3 R7 \/ B/ g) B7 E/ _二、實(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í)間。/ n. T" ?$ X$ V7 _- M  f. c. a& C
三、代碼實(shí)現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
  K  I; o0 H) b8 E. f% [  F# o. V頭文件接口:
6 |, G' z4 e( O) Y5 Q本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):' k" m- j  ?" E% J+ w
/*
& o: v8 h+ C$ ?+ r4 ], j    驅(qū)動(dòng)注冊
$ V# A# j$ m5 q5 T: Z*/
) z% x& Y/ ?/ bint cola_device_register(cola_device_t *dev);: d* C9 V7 X- ^2 x/ C
/*
7 ?4 ^8 [& G* A5 D    驅(qū)動(dòng)查找
. |3 |  v( c) x9 @*/
+ n$ Z/ K7 ]6 H/ M, Y: \4 Pcola_device_t *cola_device_find(const char *name);& a0 J9 h% `4 n
/*
+ o1 m$ L  b- K    驅(qū)動(dòng)讀
/ d0 d" s' P* g% O7 H9 _*/
3 u( M& r' f% K' q1 Aint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);4 `3 k( F! S6 {3 z
/*
0 H- @. @  B  U" j! W3 g+ v' a    驅(qū)動(dòng)寫. E- d( i0 Z/ H# W
*/
/ X* ?3 ^) I" [% U+ a: y" r5 Cint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);' s9 e1 c" w' R9 _8 b
/*
* y4 d- [& [0 I8 Z7 P0 p    驅(qū)動(dòng)控制7 w2 m7 q' h) z2 i
*/
* R# ?4 u/ E; t! {9 _% cint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
5 b. l# ^9 y! F9 g6 V/ n8 c. {) w0 {7 K#ifndef _COLA_DEVICE_H_
- J% ], `5 Z" y" d3 O#define _COLA_DEVICE_H_
7 G3 i3 `0 P0 J9 M0 Genum LED_state
. C" d9 n! j* Q# m/ @{& d: r) Q+ X. J4 @) |4 d4 Q
    LED_OFF,) D: S) c0 I" T
    LED_ON,9 ]3 q9 J4 ^" Y- {2 P# l
    LED_TOGGLE,
. @& A# G% c3 D8 @/ u};
; U6 q; J: R: C% b. N1 n7 Htypedef struct cola_device  cola_device_t;
: O* u0 t" X; I3 D; F$ B7 xstruct cola_device_ops
5 o) z! @& p+ I# D5 Y{
# E* {. F- L$ `- ^& G    int(*init)(cola_device_t*dev);
) b" [3 Q+ A! M# M    int(*open)(cola_device_t*dev,int oflag);
+ P% t0 U0 ?9 S$ o1 H7 v    int(*close)(cola_device_t*dev);! U& w! G: {+ ]& T) p
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
: Y: C7 Q0 P4 ?& k" S/ Z( o: B    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);4 |  f6 a$ @; r- i/ {# ^
    int(*control)(cola_device_t*dev,int cmd,void*args);7 M3 h1 ?( s  f6 n
};
/ g/ z9 s. h$ t6 N" b+ h' Vstruct cola_device* R# m2 F  m. m5 E9 }/ S
{3 h% T# m# X5 P: X, M
    const char* name;% G% W3 ~( L5 W; B; B- m
    struct cola_device_ops *dops;) \7 y! K* `+ x; i- V
    struct cola_device *next;
( y5 P  J' k8 j};9 t5 c+ I. _; v5 S) _: {) z0 Q
/*/ C3 f# g' T  ~2 ]; P: E9 w
    驅(qū)動(dòng)注冊1 n- H  t6 \& s, A/ S; T3 c
*/3 d" l0 r' S. q# h9 @. H- a
int cola_device_register(cola_device_t *dev);
' w! |4 o: x% ]/*8 X3 M% x' ~6 h1 J
    驅(qū)動(dòng)查找
! t2 k  j5 e) d' v7 G4 @0 e  n*/
8 I- c& M2 [3 [* G7 S8 xcola_device_t *cola_device_find(const char *name);
' P# q/ {9 K4 Q" V- ~/*5 v3 ^5 I  {$ @( u8 t3 M& I' z! Y
    驅(qū)動(dòng)讀5 t9 d0 ]* y- O- c# T! r! I
*/' r# a) C# u% g1 n- y! N8 n9 v
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);( v( F4 }6 S( N7 u! {  {
/** ~$ A+ a" p& N
    驅(qū)動(dòng)寫
% i( u5 S' q! ?* h*/
# m8 J0 S# K6 D& Y9 {1 yint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
: o3 X, X" f3 j8 D7 ^/*
! D9 b% p4 X/ ^  S2 D8 m    驅(qū)動(dòng)控制
* Z: G. \4 Z+ B7 D5 e" x& Y! g: o7 v*/" T% ]  T/ _# W1 Y( I
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);; u2 Q0 x! g* `
#endif 源文件cola_device.c:
. Z2 r+ Y; O0 F. U#include "cola_device.h"& b! Z0 x0 y% A7 Z0 w' }
#include - P! e4 k  l' ^6 f9 a
#include / i0 y! g" z. C0 G! q
struct cola_device *device_list = NULL;) v. d+ V5 F, R6 M& u  i- c7 u
/*: ~  c3 F% U/ R, [
    查找任務(wù)是否存在4 V* I( `6 t1 P" p
*/+ w8 P/ ?( A  t9 t2 r
static bool cola_device_is_exists( cola_device_t *dev )
' {0 S3 |; F2 T: w8 J{( E3 j! a" H! [7 W0 C
    cola_device_t* cur = device_list;
7 e/ g3 E8 Y! u# T/ }    while( cur !=NULL)( o5 o) i8 r4 V5 F
    {, R# V8 i% G1 q" ~$ t& |
        if(strcmp(cur->name,dev->name)==0)
7 W5 \: k2 ?1 d! d. ~4 Y        {
& R+ ?( R% h' G9 K! O! F$ D. C7 l            return true;
* e9 f: o& V8 u% m        }
& Q" G9 t! V" s        cur = cur->next;
. J2 \- p, [; W/ N    }
+ [+ l& R' ]. ]1 v$ n    return false;5 v% [  o3 z  R/ m" r
}5 t1 q. w3 m0 p
static int device_list_inster(cola_device_t *dev)
! Y- l. z& H) N3 q3 V: q7 C2 H{
6 o& n: U) i2 J: J, G; O    cola_device_t *cur = device_list;: K' `/ R& G/ T6 G9 r
    if(NULL== device_list)
; m  O/ V. z* i2 r+ `    {$ v+ G- x- P6 Y
        device_list = dev;
1 G  h# P) p" E5 j2 P( Y7 }        dev->next   = NULL;( f8 s) D& J" h/ e5 O, P" F
    }
8 Z* D. a6 S0 k    else
3 ?( Q& \* H4 V, v' i/ S4 j. s    {/ C0 L6 _8 f% Z% `1 l8 E8 L
        while(NULL!= cur->next)
8 j% b: ?8 [6 a: |& P, e        {+ c2 O2 I) Z5 m2 i# O1 [2 H4 s6 K( M
            cur = cur->next;
: R( I8 I$ F  y7 k/ a% }0 P        }
1 v# D, |$ x0 P8 Q% v2 k7 I4 O. |* `        cur->next = dev;+ `' [# z2 I$ _2 D
        dev->next = NULL;
2 A/ e' W' T0 W& q8 u; E" v2 c    }
: x" r9 X" r5 i8 u- W! ^- @' \    return 1;7 K' p# C. E) ]9 u: a0 Z3 ?, c
}3 U: F2 }( ]$ H! M6 d' V6 E3 w8 ~
/*
/ f& W( U& z; u    驅(qū)動(dòng)注冊
& {  {) q) p- u) J*/+ W5 ~, ~/ I8 P. V" z7 e% ~! t
int cola_device_register(cola_device_t *dev)
, }* c  W; d& {4 }9 p8 M{
5 u6 Z: A6 S- ]# O    if((NULL== dev)||(cola_device_is_exists(dev)))6 K- ~& F5 }% M' T
    {
- W* C  E# Y; I# T' h        return 0;
# p/ T2 p+ s- j0 q, G    }
* X6 @/ S4 \9 T! C    if((NULL== dev->name)||(NULL== dev->dops))# _0 r+ n1 g1 C7 e( _8 s' h
    {
# W) ]& ?: V+ G7 }        return 0;* F9 I: \" ~  P2 D& A) i
    }9 V# K2 j$ O% `% ^
    return device_list_inster(dev);
) q% p3 w, o  F) x: b- v}
- |+ g: D/ t( f% }) _. E; r& p/*
0 \; {6 d$ y; L$ i4 V    驅(qū)動(dòng)查找
5 n' w1 E4 B6 ?$ c6 f) J*/
6 D/ \, B5 g3 L0 W+ |cola_device_t *cola_device_find(const char *name)
/ y+ Z. x7 {/ f; o; l/ v: Z{
) S# h# B4 F; H: [* y9 L; r* K2 L" \' W    cola_device_t* cur = device_list;- g4 ^9 g8 o2 H- w* o
    while( cur !=NULL)
: ?# \! M7 D; C! P" j" ]    {: ^  \$ B* I5 h/ R. D/ o
        if(strcmp(cur->name,name)==0)  c& ~6 M. x* g7 r
        {2 J' r/ o* o; l/ c- T8 f; U
            return cur;
/ o# x0 Y3 X8 v+ e) ?' e( Y/ c, X7 f        }+ C1 {1 l: i  y& _
        cur = cur->next;
' I: U# n0 \) H8 }. F    }
) S! f" ?! P  ?" }; b; q    return NULL;$ `, u2 B0 E' d/ D
}) c5 {; t0 V  `3 l6 |, B
/*6 ^! Z. m. O% R$ f6 ~3 W/ j
    驅(qū)動(dòng)讀
: f' t8 i1 B! m*/
* M  G2 s" }' s0 c7 H: R, ~* P9 sint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)# x$ D: J2 m; e! u9 x9 }+ N
{) N6 e. t  A# M: D# F! P+ z. W
    if(dev)
( {& M" U+ E/ n- j" X& \- k* Y/ \    {
6 D) s4 x8 P5 q: t2 E8 l( H        if(dev->dops->read)
- U+ V8 M, S* Y) y' N        {- F4 T- c/ X; i1 g
            return dev->dops->read(dev, pos, buffer, size);* d: V# e( B* e2 E1 K3 M7 a
        }) b5 o, T( x' K* i' h; s
    }
5 T. h6 g" c! o( o3 i    return 0;& @( }; a7 e* A& ]
}
) A3 O. N  d: w/*
0 I0 Y, _' ~; [* t! ~    驅(qū)動(dòng)寫! A7 ~. d3 T/ T- Q" O2 \* G6 f+ L* X
*/! S' I6 D+ ?7 v- Z
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size); o! Z% w, W. f  ?  d
{
8 }( [# C& v& E" J  w    if(dev)
6 O, r$ ^8 f8 y% @7 [    {
4 q7 q, k; l+ X4 X4 m        if(dev->dops->write)
8 d. i8 a$ }9 B$ |2 m7 s        {8 T6 V' T8 \/ i0 X1 [3 M8 Y+ y, o
            return dev->dops->write(dev, pos, buffer, size);
, @# F5 v7 A- L& K& R3 j' K- f3 {$ p        }! H8 R! k% W& n" B7 R, B1 z- E
    }
" \/ D7 V4 H3 O/ y) h    return 0;
0 d) @/ N* @  M7 L( M. B( ~$ \}
% Z; a) |* ~) I4 J! y. P4 m/*
( s9 Q! c+ B& _% o% t3 D# d    驅(qū)動(dòng)控制3 b& S2 g& T2 c) A# r- d( t+ s
*/
4 I* l" n% V: s$ t5 |5 w5 |/ I* U+ W# Zint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)' G1 I4 G) }  e" @; w2 H' E' n
{$ v$ m0 [  X2 ?" v
    if(dev)5 {5 r  ^# O5 i
    {! \9 b* v4 ?6 m9 I8 |6 P
        if(dev->dops->control)
" R, C6 N: I1 d2 x: E' J8 ?& N+ R. O6 {        {) m. s  a' ?" S  N6 i& o. |8 Q
            return dev->dops->control(dev, cmd, arg);
6 v$ |+ P6 [5 f% v& b: E        }) \, E- t7 x; \5 E& v# f  `3 Y  p
    }
5 o$ _( A- ]: t7 \    return 0;
( X$ ]2 @6 |: b, A}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。
7 ^% y4 w8 @* T  j; O, s- A$ e#include "stm32f0xx.h"( H" W1 Y0 y4 F( r
#include "led.h"
/ D' {6 f+ J* y/ p3 X#include "cola_device.h"
) w# o( y% r- s, n#define PORT_GREEN_LED                 GPIOC                   / {( N+ X+ @* q, q. W- t# H$ |
#define PIN_GREENLED                   GPIO_Pin_13              4 z. y9 c! f! A7 q
/* LED亮、滅、變化 */' g, y) |& [$ N- n! d" C
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)/ S) P+ X. |, Y' l# g. O2 _
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)$ o$ X4 ^1 J# H% e
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED). n6 y4 l& m( z( S- b
static cola_device_t led_dev;7 D2 \4 J0 t- F' s8 @: g
static void led_gpio_init(void)
$ r2 x! w/ O* [3 j8 s; v9 b) _{, e9 l5 a. ^% O0 v$ F2 U4 m
    GPIO_InitTypeDef GPIO_InitStructure;8 w' I% X4 |7 i/ f
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
- }4 K# u9 c5 d+ s    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
# I4 K$ }- D: }    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
* k0 i, u- `) J6 D( A    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;+ m3 C9 v) [8 [* R. V- f
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;! A( @9 f, P) j
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;7 w5 ]# ~: D- f- x% R1 J
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
7 u/ W1 C3 X# ^  M    LED_GREEN_OFF;: H5 l5 j, |( ^5 I' ~8 B/ J
}
( p0 h# [6 d; Z( `9 c; B* \' S3 I3 P  ^" {& a3 Y" ~! R
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
0 f, g+ u, E; |: O{
% U" I9 J9 ?- G3 o    if(LED_TOGGLE == cmd)& k2 s" c3 [% k3 p  y  x% `! w7 ~$ l
    {/ _3 a/ z6 [0 j* I7 n7 c
        LED_GREEN_TOGGLE;$ N% Y8 Q# s4 ^/ V! U
    }6 W0 I1 v0 d2 B1 |: B/ g
    else
6 ?% z; |% P6 e2 e7 M    {
9 g* D/ d0 ]2 }$ J! A    }+ X# t0 Q" o& n4 x2 G9 J3 i
    return 1;
8 B" Z& a( f$ L% D; m! M}
* U' k3 A0 v+ f. c- ]2 n) M2 Ustatic struct cola_device_ops ops =& c  S5 |' ^3 M' y
{% X: Z. T3 k0 u3 _. b
.control = led_ctrl,
% ?6 W7 J% w/ l$ r};
. v" ^& \0 n6 g( v! U( Jvoid led_register(void)4 t+ c0 [% C- v/ [
{
6 E2 }; B2 X. a! s    led_gpio_init();% r4 q4 M* g9 F7 n
    led_dev.dops =&ops;7 e7 X$ w% R/ y0 c
    led_dev.name ="led";2 g  u4 e) Z" P0 J5 R, M+ _. t* k
    cola_device_register(&led_dev);* [/ X9 t2 e% W/ t: q
}應(yīng)用層app代碼:
6 T# v) |! F: w0 I#include * V' B1 h1 S/ Y
#include "app.h"# L6 ]2 X) d$ U* m2 k- h  ~! Z
#include "config.h"( v. P/ \% n, [5 P5 a; E6 B
#include "cola_device.h"7 R$ M6 ^/ Z2 r: ]) V6 O* d
#include "cola_os.h"3 M5 p% I( B6 B& a4 A; Z" h
static task_t timer_500ms;4 c; Y4 \5 E' D, R& ?( |0 d, b3 J
static cola_device_t*app_led_dev;  H1 k' \; T- c2 v4 ~
//led每500ms狀態(tài)改變一次* d& Y; W/ c- y* |, x( D* i
static void timer_500ms_cb(uint32_t event)
, r% i. v4 I2 N) R0 t1 G+ w: A{6 w- K. v9 W$ [& `; Y- K7 M
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);) I9 K3 g0 z- h, E, ?
}
; \! Q0 {( q7 f. Bvoid app_init(void)' Y6 W( E8 C8 _
{7 E2 z3 [3 v* o) I3 X. Q+ j
    app_led_dev = cola_device_find("led");
: Y* ]6 J4 N8 C7 }$ }+ s    assert(app_led_dev);
/ G$ C  k6 W4 p/ Z7 ]/ y6 x    cola_timer_create(&timer_500ms,timer_500ms_cb);- ?! ]3 \2 P0 I5 J
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
2 b9 u5 }! e1 r  \1 n5 W& F}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。( q: ?0 {  q& U% |! Q% _2 X5 Y
四、代碼下載鏈接https://gitee.com/schuck/cola_os
; e9 W3 ~) L, t2 H' S- ?
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
9 Z- V" n. T# Q6 O7 A1 e-END-
" w$ x* W' M, K- F! F, g往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀8 L3 W9 i' s" m. ~2 k$ u
                                                       
$ D6 {8 q; T# Z2 F; j; n- A                                                               
* N, n3 `: y6 w; @. q3 ?4 K  W" f  l1 I; t                                                                        ; I8 t- [+ S2 `! c- Q5 r# C
                                                                               
7 @, E& s7 y- y* `  R( ` ) v5 [9 v/ b& W( l1 ]- z, n
                                                                               
) l4 O, m* `* {- i                                                                                        嵌入式 C 語言的自我修養(yǎng)
' w- M  Y6 ^3 n8 A                                                       
3 u: G! W0 A/ m3 d0 T1 K                                                                & ]& y! C& P( `, N8 N; y$ L
                                                                        : B( ?5 V+ O8 p9 ]6 G1 g& L
                                                                               
% u+ S1 B( J( q4 k8 x& F) { ) _( |# A  N: a, z) R( J/ K0 ^/ q4 H5 p
                                                                               
) G4 g) b) t8 `- p$ P8 Q2 [                                                                                        被 char 類型的變量坑慘了!! F: i+ @4 Q1 d  K3 U
                                                               
0 Q8 s* F' ?. a  ~! l  j( c                                                                        7 G1 M# _- e: F( G! z9 ?, U
                                                                               
7 ~% E. x$ L" c* ~+ [# ] 3 {# g8 H* v* @
                                                                               
3 I9 {; [+ Z& \/ H                                                                                        嵌入式 C 語言知識(shí)點(diǎn),動(dòng)態(tài)變長數(shù)組
( J$ a" P/ U- b* H+ q- A9 g9 b                                                                                . \; p) l$ D5 C! ^$ J
                                                                       
; X+ s7 M& W, R                                                               
! q& Q& }% P3 H* S5 ?% j( J. f/ @5 W                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
# R7 Q" Z$ Q' N, N6 o# ]1 _; _關(guān)注我,一起變得更加優(yōu)秀!

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

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

本版積分規(guī)則


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