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

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

搜索
查看: 44|回復(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覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師8 @/ L4 [! G4 L' J5 A+ a2 z& H
關(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ì)顯得很亂。
$ P3 B$ S. n2 P* V) J+ |  m3 p使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會(huì)發(fā)現(xiàn)代碼中都會(huì)有device的源文件,沒錯(cuò),這就是驅(qū)動(dòng)層。, K' W% b6 p. K( y7 H. a+ t

) Q0 L+ \; U+ z. R二、實(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í)間。' }5 h8 ^6 D; l: ]+ e; s
三、代碼實(shí)現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡(jiǎn)單在這我只用單向鏈表。有興趣的可以自行研究rt_thread- |( a+ y# e5 y/ O3 C8 ^% {* D
頭文件接口:  S, V6 a$ o5 U& c
本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):
( {6 s8 a( a( U& Y7 d/*8 m/ v  C  N' B+ M5 I, p
    驅(qū)動(dòng)注冊(cè). [: B& ^1 N, I7 a" `( I  e6 K
*/
9 H6 s  t# w& ]: Lint cola_device_register(cola_device_t *dev);
. R, O3 w+ I* \, s6 b/*
0 K; I0 e) {. g0 y2 L* w    驅(qū)動(dòng)查找2 i) @2 t: |& R5 R& @
*/
; m; y6 q. @; w# W4 a) y$ K; ?# ncola_device_t *cola_device_find(const char *name);
( N/ z- U: ^" O. r' M7 |3 q% D9 V/*/ P  `: Q; J- V
    驅(qū)動(dòng)讀
; s! ?8 n0 u7 [$ j*/
$ n$ P0 E0 I& r( D, J% Aint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
* o! Y5 L& F; g( B" W9 |/*
9 R- M; x, W7 p& z$ Y8 B- u+ d    驅(qū)動(dòng)寫5 c( q1 Q: j% |* I% r/ d: `
*/
$ K! R$ L" S  ~+ s; Dint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);* W$ u/ L" [- b6 W0 w: c3 H
/*: q- V) C* X3 u7 D* ?9 N) {1 Y
    驅(qū)動(dòng)控制
: b3 c4 y1 W, ]- U9 v6 E*/, _8 l1 ~7 \& X5 ?4 K. `
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
0 X: M6 h2 B4 t4 q#ifndef _COLA_DEVICE_H_
# N  N  m* c" Z+ A; S#define _COLA_DEVICE_H_/ _1 m4 U9 a  [1 H' C- B
enum LED_state
8 S  Q  X8 D# V{
8 z" n6 z/ T5 ]3 D. u- _    LED_OFF,
  _7 a- n' I+ Z: H7 |& G    LED_ON,* s, l- K9 V) ~' d: i7 A4 i3 F
    LED_TOGGLE,
1 x3 H) l8 x5 w# v/ y$ ?};
/ l/ M6 I/ N3 k7 jtypedef struct cola_device  cola_device_t;; U6 x, U7 J& t" s
struct cola_device_ops
3 x, F- Y' o- g) F{& L0 J( d! \1 R& ]  B' r
    int(*init)(cola_device_t*dev);% ~. R/ A2 @- o7 l# W) ]; G
    int(*open)(cola_device_t*dev,int oflag);
) ?4 V+ k, v5 W- I2 j" s6 }) Q- x    int(*close)(cola_device_t*dev);5 O# E- `* a/ e
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
( Q; a7 a" a# ~$ Z- S    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
- a$ C8 k. U+ \( B7 B$ f9 N. J3 T    int(*control)(cola_device_t*dev,int cmd,void*args);
) i' u! v, e+ F* X& I3 b1 t  o};) b; d' v; ?: P0 k$ W% Q8 w- ~
struct cola_device
9 X7 M7 o! H. ]2 P{
+ i. O, p, N* Y0 L" w; L    const char* name;
9 D8 }% T* U$ U8 w7 E    struct cola_device_ops *dops;
( l" M" P+ H7 U1 a0 H2 R: e, d    struct cola_device *next;
3 K- W1 q8 H4 D};0 O% h1 H9 [: o6 H4 e+ q. ~
/*( [! r* l6 W8 x+ D2 x8 {7 m
    驅(qū)動(dòng)注冊(cè)1 Y# N* {% y2 y4 `9 {+ D) o
*/' u; j; E% _' ]  x% }+ s, d. X
int cola_device_register(cola_device_t *dev);# e" V* L* {0 T$ J8 f5 Y& f& X
/*" C! X1 l+ F, |9 Y
    驅(qū)動(dòng)查找  ?5 e  ~! f- [" S* r3 z
*/  y. {9 L$ p, z0 R9 S* c! J
cola_device_t *cola_device_find(const char *name);
" O/ V: ]+ \0 |0 g! ]2 Y/*6 e, y3 H0 V' y4 s
    驅(qū)動(dòng)讀4 |* N1 r" n. A, R1 c( m9 m
*/8 _9 {9 Y  |9 l
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
  s4 Z# P; \! E5 N- R/*5 l( v0 _/ y6 L/ C- u2 v
    驅(qū)動(dòng)寫+ V( k8 {5 Y& |2 h
*/
1 s3 p0 z2 l& O) y; Eint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
2 K( d" [+ t/ k2 z& X9 A/*7 P$ K  V4 s2 G* F) T
    驅(qū)動(dòng)控制3 S; L0 B. k9 B, s0 R. d  B
*/
' p& }+ H% m0 s+ X# ]int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
/ f! d/ v' l8 j' t#endif 源文件cola_device.c:2 n; C) J& c4 A) z8 F& \) K' t1 r
#include "cola_device.h"
# G1 R0 ~" m) ?#include
, z( i/ {. Y) N& a( |#include
  f8 G5 t0 u; ]# V( k* astruct cola_device *device_list = NULL;
. [( b4 A. W. d% c) c/*. k. p$ E! U% a% I# u& R+ u/ r
    查找任務(wù)是否存在
5 \4 I8 P- G# x! S*/, Z, f) H7 q* a
static bool cola_device_is_exists( cola_device_t *dev )
! m+ d# D! d. z& p. [- J{/ z6 J; d7 x9 U+ s- r
    cola_device_t* cur = device_list;
. G9 M" f* o4 j    while( cur !=NULL)
; ~( K( B; I6 q8 D; v7 F7 w% A. t1 P    {6 W( d" v4 d- G; u6 l
        if(strcmp(cur->name,dev->name)==0)
- z- b6 y, j, O        {
  m$ D: f5 ^, X            return true;% ^. T* E# \$ ^8 a% }  x0 N' q
        }
& `3 \/ q; o% E; \# o0 B! Y, G        cur = cur->next;- S# h9 W5 H7 i+ n$ S9 E
    }
( ?7 |# ]1 _3 R; U    return false;
" M: B. ?/ ?$ ?* i}; i% z4 v  F# x# Z6 V: V. J
static int device_list_inster(cola_device_t *dev)6 q  r) i  \( O
{
! q" n) b* _4 d6 S* o1 A) T# w    cola_device_t *cur = device_list;* S9 ?  Y" h9 ]% s( B: U/ L  D5 I
    if(NULL== device_list)
# x3 q& D% @# `) s( {. o5 c. X    {
# \0 h2 L' I# E$ ]# k        device_list = dev;
3 b* D" e+ F+ V' m  Q. v. x- P        dev->next   = NULL;
" u  }2 z7 r! b3 g    }: m5 Z9 R3 w7 ^
    else: f) `- R. W- O# |% G. c0 k! |" `
    {" }5 s" j7 T7 b9 i8 V
        while(NULL!= cur->next)8 [8 X/ |" Y' @( `; S% c  S( ~
        {
  S4 H- R# m% l/ ?( C7 `3 J+ o            cur = cur->next;
" c" ~8 n, T9 |1 }6 M' n, u        }
0 U; E$ j* Y3 [8 m! ]        cur->next = dev;7 I0 T: W5 o4 l! t
        dev->next = NULL;
' C; d# }$ g$ c) K( d  b    }
3 X* F) Y! t7 f% B* y    return 1;
$ X# n+ C$ |( j$ e/ e}
2 q' \1 H+ c: M( n) A& Y7 W/*
4 M' u* f# ^, P, M) Q1 Z    驅(qū)動(dòng)注冊(cè)
5 |* f6 r1 j) s, W& H: l5 q/ S*/
7 H' d% s' H! t: rint cola_device_register(cola_device_t *dev)4 y3 _9 o( l9 W
{
- M/ V8 c3 b7 Q! r. y& S7 ^    if((NULL== dev)||(cola_device_is_exists(dev)))2 c6 O# i* M% |) W4 b% v% B
    {' a( S% a  j; m) N( y( [- R
        return 0;! B+ U$ V( r0 n/ L  K
    }
% V. h; J! B/ |! `& g' W" W' o" g( s3 ~    if((NULL== dev->name)||(NULL== dev->dops))0 E* i: d$ e# ~- R
    {
4 c. P9 r& M4 k* y* \        return 0;
5 t5 h3 ^- r+ \% u3 ^    }/ @0 Y4 y4 d% ?, }( z: d
    return device_list_inster(dev);8 g& t. L0 c8 ]
}+ @/ A( g# W- b8 c! R" i
/*
8 U+ t# Z$ C  k' U; a6 V  H8 Z    驅(qū)動(dòng)查找
9 H1 v2 W& J; f' R  D/ |*/0 q! p3 q" l) J3 c/ t- {" h
cola_device_t *cola_device_find(const char *name)' F, y) b% N( S& g  }; ?
{. E4 W; k+ T; T9 V, [3 h
    cola_device_t* cur = device_list;
/ Q$ P# t# h3 G1 c" c+ H    while( cur !=NULL)
7 L1 F& F! E5 `2 H- c. Q6 o    {
; ~. l+ |( b* h        if(strcmp(cur->name,name)==0)2 ?" Y+ w' V; X9 q5 W7 z  r
        {* m- s* ^0 B; l/ T9 W
            return cur;
7 m0 i& ?+ l7 |) ?$ K& A, x2 S- S        }
5 @2 y1 |7 c, O, [8 g$ s8 p& ~        cur = cur->next;+ E0 g6 n5 _) u! A6 M
    }( p3 \  i+ |- r. D# k
    return NULL;
8 b8 t9 {; [/ F+ F/ x) @/ L9 m  w}
$ P/ v5 h; B. U  I1 R" X+ d/*( I# v8 t) _' Y, u: g8 Z) W
    驅(qū)動(dòng)讀
$ o! P+ F& o3 B. ]8 Q; ~4 H8 x*/6 }, W7 }0 O& ^" r1 A- T
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)% U; {+ R$ u3 _3 c- ~9 {  [' s$ F
{" Q) f: A1 ]8 |4 I+ H
    if(dev)
; G8 Y' x) p/ U! a  ]2 X    {* c. k! \+ N. c5 R) M( Y
        if(dev->dops->read)5 g5 m: C7 G! Y  q7 m9 }5 D
        {. b' e" @) j  V' F$ v! H* m/ d1 F! Y
            return dev->dops->read(dev, pos, buffer, size);, k7 M6 W' t: o+ V
        }; `, H8 m; q( V! e4 v; F
    }  n$ K- _% \& f! r& c* n" H$ B
    return 0;
( j5 f1 j; D/ g6 E& K8 C" q}
) m3 ?/ ?+ y7 E5 w8 r- d0 w/*: h. a  q; w) D
    驅(qū)動(dòng)寫" I- C/ b/ x) ]; m# Z3 ?; \
*/7 f' B! S7 a1 Z9 b
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
: b7 G% n1 T' `3 p) [7 d/ B' c* P{
4 R, h2 {" w! }1 H    if(dev)
5 N3 c% ?( J; ^" a3 e, V" m/ m    {+ K; {. f& l& w; @0 U0 n
        if(dev->dops->write)
, t! P, f$ g# y1 F0 |        {  o# N/ n' f: X/ |
            return dev->dops->write(dev, pos, buffer, size);
/ T( e6 d8 ?$ x1 t        }; ~' j- X8 y& ^8 F0 u( @9 p
    }
9 `/ E; S8 K8 l6 m9 d    return 0;5 k9 I" N) @2 S: N2 v. w1 h" P" ]0 c
}, \# M! u& g( r
/*+ r. ]: l0 j$ e( D& [( q& \7 u
    驅(qū)動(dòng)控制
, q! B: X# }( A  u9 H( C*/
: k  w$ t0 E( }1 H6 S  yint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)$ L/ z* _  v2 F. `
{) u$ G' i! D7 C' ~& Z  L
    if(dev)
: q* b& G. h; @7 o" _5 X, m    {
5 Z' V& ^5 X5 Y        if(dev->dops->control)
3 f$ ?  ~1 ]) I        {
8 k  a9 U! h8 n9 a            return dev->dops->control(dev, cmd, arg);1 H' j& n/ r' @! x* _
        }
9 J. D& n' D! B" n- z# r: p    }9 Y& d: j! `( {6 U8 \
    return 0;
* ?2 X5 r; d; y; i  N8 }, q}硬件注冊(cè)方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。: @- z/ c1 {0 |
#include "stm32f0xx.h"; y8 V  t- ?8 K( m! m
#include "led.h"9 r% z- ?! H, r
#include "cola_device.h": ^, X( V" X" t2 h9 G1 ~
#define PORT_GREEN_LED                 GPIOC                  
( w  p( w3 N! W: o4 F2 j#define PIN_GREENLED                   GPIO_Pin_13              + X2 Q0 w0 E4 `, \: |% l  _9 [$ t
/* LED亮、滅、變化 */9 u0 c; r5 `& T4 {% x4 g
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
* O4 q$ C$ N1 f#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)" F2 D  y8 O5 T  y' K+ U  q
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
4 A5 `' ]8 k5 r9 A3 Dstatic cola_device_t led_dev;, l. T% C2 P) [1 _
static void led_gpio_init(void)7 V; N4 ~7 B( j2 M: e$ Q( Q" [
{7 z$ i+ P# ]9 h* P- J* T
    GPIO_InitTypeDef GPIO_InitStructure;
' l& K. e( o" F4 O9 g9 d6 L    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);( h4 \  O7 F9 a( Y
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;! z( n) B; e) J# B7 m7 E
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;' U  H$ j% P6 h6 {/ q
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;2 I1 Y+ u. K& J
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;, m1 y& ^2 A/ q+ o. ^( n
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1 s. ?  @9 U, C, E    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
$ I! [. T2 U/ K; a  |0 @    LED_GREEN_OFF;9 p6 u$ m5 f7 z$ q# [
}* K4 e) k" O3 ]6 B* o7 R

+ @% g- T1 C3 x# E: Jstatic int led_ctrl(cola_device_t *dev, int cmd, void *args)
% k& b6 `( m, p/ _{2 P) k+ H3 ~' O7 @% y7 ^
    if(LED_TOGGLE == cmd)3 x6 `; d# w( a
    {
5 t" z9 M5 z" f$ `2 q8 B. l        LED_GREEN_TOGGLE;4 P1 u3 I" L2 ~* ?5 E! N
    }
0 Z; D5 n+ y" l% l' ^    else
3 [+ ^0 S9 Q* d0 K" U# I" v, W" s    {! s! S; m. x7 E3 U2 f
    }
+ C! W- Y4 J8 _' h9 @' U    return 1;
5 [* Q' O3 T4 {3 r! j. i}" |( d8 c: U0 ~6 c7 Y
static struct cola_device_ops ops =
: ^' S- K% x3 s% j{+ h. b4 y% l. a: Z! a; O
.control = led_ctrl,4 i0 z* D4 e7 @- x7 }4 }
};
& X" g  g9 R* v7 mvoid led_register(void)
. L; F# @, Z5 d7 y: L+ z& S3 Y  D9 ^{
* H# w5 H: m' \' K5 o* K  c    led_gpio_init();" E7 X& q" I( t3 m0 I
    led_dev.dops =&ops;, ?- v# A, s6 k: @7 h2 L2 _
    led_dev.name ="led";
# ^) y# i. f0 _' [* z    cola_device_register(&led_dev);( L4 Y+ D. o: z  M  {
}應(yīng)用層app代碼:
! _* @" E0 W' p. P* }#include
; [; C( W! d, @+ x#include "app.h"( n" I+ m* M6 F  v% N5 x
#include "config.h"
7 o& C1 L: `& o2 b#include "cola_device.h"' [1 m; U( G$ D; I8 f6 S) F# e$ E
#include "cola_os.h"! k% P6 l( [6 _) l, B" K# V
static task_t timer_500ms;
% V, }9 R% j9 tstatic cola_device_t*app_led_dev;
# e) W. w6 w8 Q3 T* q3 a//led每500ms狀態(tài)改變一次9 G) W/ n4 W: x& Y
static void timer_500ms_cb(uint32_t event)( i5 x, w$ p: X& X! m
{9 R0 a) l5 j1 h+ s9 T
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
! y; R% i" E  g' W. I' j, n}: c  z3 y5 L' @0 E9 Y$ n9 _
void app_init(void)
1 H3 ]7 a  ?6 k  Y% i/ g! a{
# q( S! F5 Z2 c    app_led_dev = cola_device_find("led");" J# z1 k' E+ {( u
    assert(app_led_dev);
1 c+ \" Q, F- r1 i  C5 X6 ~$ I    cola_timer_create(&timer_500ms,timer_500ms_cb);/ E, o) W" z2 l% d  y+ d) p" s
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
& m$ M! o( v6 Q* q, b8 B8 c5 m# I% ]}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。
& B+ Z% _& x: l4 W, ^四、代碼下載鏈接https://gitee.com/schuck/cola_os3 D- v' W% }- q! B
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722: F( f, H* C3 ^* p$ L
-END-
! E$ w6 {8 T: r( {+ D往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀& Q' p- e. Z# {! q% h8 M
                                                       
9 g/ I  m$ l5 o( {; o/ _% \                                                                  o8 e, E. b' t( @% c9 C1 T9 a2 b
                                                                        6 q/ E3 z- @& F# M' z
                                                                               
3 q! i3 b5 O2 l % O3 D1 s# A4 ^; G: ]
                                                                                8 `1 C/ @5 c: O0 V5 z* r
                                                                                        嵌入式 C 語言的自我修養(yǎng)
3 O* b, q# o# z+ \                                                        * h4 u# ~  O& t+ [) Y2 A! F, N) D8 P
                                                               
. F& J/ Q( P! t4 ?' }+ G                                                                        ; I1 |5 ]8 q6 O; `) C
                                                                                % d2 W! X* x& Y: M

. `+ @8 ^. T( e8 q. q/ d  \  n3 R                                                                                " N0 ]* a  S0 E( K& V  D" p
                                                                                        被 char 類型的變量坑慘了!
2 f) j" Y9 R) m. i6 J. M  ]% B% I                                                               
2 E# d% x) m4 w                                                                        3 g3 ?3 |! y, K! l
                                                                               
: v  i3 \4 x5 j8 _6 a
2 |& s7 a; G2 }- S! j. P                                                                                , w& I4 [1 n( _% e- e7 R9 ^1 [
                                                                                        嵌入式 C 語言知識(shí)點(diǎn),動(dòng)態(tài)變長數(shù)組
7 o/ S1 d! e: V. N2 |8 }                                                                               
1 L" N' A% h% X6 _                                                                        ' o3 T6 q6 e8 r& ]
                                                               
4 i# E/ ?! ?- U5 N- D* F                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師8 x4 ]7 g. Q) I; h
關(guān)注我,一起變得更加優(yōu)秀!

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

本版積分規(guī)則


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