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

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

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

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

[復(fù)制鏈接]

455

主題

455

帖子

849

積分

二級會員

Rank: 2

積分
849
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師' E: P) c: p0 a: W- T& F
關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應(yīng)用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。- ~" u% {" U4 m, v: a
使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅(qū)動層。) P! h! l9 ^7 p2 Q, s, M( f: I
1 ?. t+ ^. k1 ?* L) M: p5 a
二、實(shí)現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動鏈表上,在驅(qū)動層實(shí)現(xiàn)device的open、read、write等操作。當(dāng)然這樣做也有弊端,就是驅(qū)動find的時候需要遍歷一遍驅(qū)動鏈表,這樣會增加代碼運(yùn)行時間。
# e. `) Y; O- A2 r4 N三、代碼實(shí)現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
/ _7 I3 a$ R8 z- i7 i$ Q6 {# s! D( \頭文件接口:1 y. w6 L; D1 g$ l) a' S
本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):1 g2 u) N) O& K! n$ j& @4 n$ C% _
/*( Z9 q( i3 C6 i: W7 o' M
    驅(qū)動注冊
0 |6 w3 o5 _& _$ }" K6 |*/
& N9 T  y# ], N6 uint cola_device_register(cola_device_t *dev);4 L6 n3 U, ^7 |0 r2 Y$ z
/*
2 ~3 Q2 Y1 S" P. I# Y: R    驅(qū)動查找1 N! b% ?/ T9 O2 G5 i
*/
1 w/ e$ ]4 d( z3 n) A6 p1 u& Gcola_device_t *cola_device_find(const char *name);
# Q1 j+ H7 _% V2 K8 N# \' n/*
& `8 n" |) ^' g+ f$ f    驅(qū)動讀4 M8 Y# Z* M& o2 r4 W8 n; B
*/
/ }. a. v% Y! R- c8 Jint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
+ j3 y$ I! p, G7 z/*/ w2 N- ]& E& {  k# o5 u
    驅(qū)動寫% E' c/ {  b) M, M+ B4 l0 x
*/9 T% A8 b0 {& [) S# Q0 v
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);( }- D# r+ t9 V6 A
/*
* S! r; {" U. }! t% b7 x% L    驅(qū)動控制
  E4 ]2 Q) p& f- l* b) t*/( f/ `* Q% L$ l
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
. M1 f  W/ ^! {8 `) x4 i7 B#ifndef _COLA_DEVICE_H_6 l) C9 H: F4 E! X" z5 m( ?& _
#define _COLA_DEVICE_H_
% z4 ?4 q) x# Q1 Senum LED_state
6 N! @9 }# U' g9 ~) a. z+ A{! F8 Y2 X; B. c, S
    LED_OFF,2 R4 V  l4 J: u  |* b* c5 C, a& G( k
    LED_ON,: ?7 w" A& I. a( r$ w
    LED_TOGGLE,% |1 o9 W, ?& X9 U" k( q
};$ ^# r& X  s) \; `& k
typedef struct cola_device  cola_device_t;$ |/ G3 O& i. W: b; n: g
struct cola_device_ops
% V" @; S5 y, H( @! @3 i# Z{6 n4 V2 F0 m8 Z+ ^, G' v3 |% N
    int(*init)(cola_device_t*dev);
4 M: |& g( r/ d    int(*open)(cola_device_t*dev,int oflag);
2 ^: y8 _2 S) w    int(*close)(cola_device_t*dev);
9 h1 i  t$ Q6 ^! v5 v2 `' L; r    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);" ~9 [! j* o4 k3 N
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);0 M- g3 n7 @# @5 x4 a' i! C; A' B
    int(*control)(cola_device_t*dev,int cmd,void*args);0 H2 a2 E) I0 H" B0 F/ I8 B
};, I7 w+ u) v- }& P2 f& M
struct cola_device$ P- C2 E' Q! N4 l5 i& ?
{
, N' J4 y% f) B# C1 [    const char* name;) U' R0 d2 Z5 ?$ G; Y4 c) {
    struct cola_device_ops *dops;
8 Z) Z' ^. L5 k    struct cola_device *next;
! f/ e4 v3 V7 E9 s};& c) O( U' z) ^# G( }1 J
/*
# _; p1 x1 _/ x# ~3 X* ^# w6 n( f1 e+ ^/ N    驅(qū)動注冊3 M9 H. H8 M5 f
*/
6 v; Z( @. C4 Y0 {. K2 [) U+ tint cola_device_register(cola_device_t *dev);" e! B% x& D9 [. i0 Y9 g- d
/*' h- P' C( [% L: X4 K
    驅(qū)動查找
- C' g. I0 ~/ R7 Q*/1 _$ z3 d; `9 D5 U9 h- q
cola_device_t *cola_device_find(const char *name);
9 i8 h  [1 G( i2 M/*  h3 d9 U4 P( P1 q8 s  }: B
    驅(qū)動讀& s9 i$ k0 J" O( p% N8 `/ I2 H8 S
*/2 v$ x% j4 ?( L# F
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);9 n5 L2 _6 K& r& I
/*1 z$ j$ l' u, B& P9 R2 E
    驅(qū)動寫
+ e0 [. ~* O+ d6 I9 F*/
: K% a) B+ \, H  `& Gint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
7 H/ M  u# {: _' p9 b" i7 Z2 _+ {! U/*
4 x2 ?( e1 B" c8 @# d% w0 J" E    驅(qū)動控制! N( a. `4 R$ p
*/
) \2 J) T: ?" ?3 a8 Iint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);; U! @% u7 u/ N. H; f( b0 d) H
#endif 源文件cola_device.c:$ H. r8 @2 h. ~  [3 j+ f: C2 F
#include "cola_device.h"
, w) u7 U  Z. k* y#include
) n/ M' x! m* _* d+ u7 B#include * b$ e" V2 j: ~5 h
struct cola_device *device_list = NULL;, J& ~1 m/ o+ q) H8 t0 q! i
/*6 }# P5 R; L  E  Q: @
    查找任務(wù)是否存在
9 ~3 g9 W5 [" M6 [*/
  b4 h. s& R* o9 n# K2 {* Cstatic bool cola_device_is_exists( cola_device_t *dev )% i- Y- \+ w' ~# [$ z) m0 V
{7 c1 ]' [( G2 M" X
    cola_device_t* cur = device_list;+ s) o8 i1 r+ }7 r
    while( cur !=NULL)
, H3 ~4 G: W! ~. O1 m    {5 _9 x0 l9 f; B9 ?( H
        if(strcmp(cur->name,dev->name)==0)
9 T. e- w  F  H        {% H! o# u  Y, m- p  N8 z* O
            return true;
. g) g; r9 B3 R7 O: E        }. Z) J: P- C# q* d' ~
        cur = cur->next;( g0 z5 V+ r# h; P& m- P
    }) z3 |6 _& x+ J/ B+ {% M, F2 q% ?
    return false;+ o) p3 F- ]8 B- z. j  U8 y
}
* `2 ]1 `! E: B1 ystatic int device_list_inster(cola_device_t *dev)
, f4 C2 Q, S( U6 W7 m; L{
$ s" q. ^7 ]6 D6 ^, x    cola_device_t *cur = device_list;
! s0 ~# N: s' k  v$ y8 S% t    if(NULL== device_list)
- _, P1 Y9 l- ?1 c, Q    {, X: ^) C' S: Q& S5 u) ^4 U3 m
        device_list = dev;& A, C+ D$ y  O1 C. ]+ [1 G$ E
        dev->next   = NULL;( e: [3 m) ^" b8 T$ Z
    }) n( J+ L8 Q9 W% ]; J4 M3 i
    else
; `7 _& C2 _1 z, n" i    {, {; f- j. j6 x3 J
        while(NULL!= cur->next); i% }8 D/ A! ]+ |
        {
9 Q" m3 i8 }/ A5 S            cur = cur->next;
3 v: Y2 _7 B3 L, Q9 N        }
3 t& N( g' _1 f0 |; I, z  B+ p        cur->next = dev;0 ~2 K1 K  S- e5 a5 t; d7 h
        dev->next = NULL;
8 R- N  |/ l& g2 e1 F7 T) b# A4 O    }
* b/ o. h- N; T$ a. [! k: v) T+ h    return 1;
% T2 E$ M1 {# n! e. ?1 O3 D8 l# Q* j3 G}/ k; ?( K2 E; L0 h) d9 X. O
/*" h$ ]1 q' H" p; d) o: P$ D* `
    驅(qū)動注冊
/ J- v, k) d1 I3 X: B*/3 e' T* w& V& b# m3 e" d2 E
int cola_device_register(cola_device_t *dev)1 F4 y+ u& K* S& ~# Y8 X+ Y
{: X! [5 A, n5 }* d" b! A- {
    if((NULL== dev)||(cola_device_is_exists(dev))): v" R5 y8 M2 Y7 b
    {. }2 N! f5 @1 M9 h) |9 }
        return 0;
0 }; K  B+ q0 T! c    }
& N. w% }# G) q8 \- [    if((NULL== dev->name)||(NULL== dev->dops))% k' P# r( i$ x& W
    {
. q; v2 E0 b( R1 h* b- x: I) {        return 0;
& ?$ _' e2 G2 J+ f    }! j0 ^2 @, {) @: c$ a
    return device_list_inster(dev);2 r  B$ K4 i: {- ]
}
' I1 S2 o, u$ t. }4 A2 P" {/*
. k2 G3 e/ |, W# G* b3 a    驅(qū)動查找
0 `, [* {( [$ [! E9 q0 W7 l. F! V*/" |/ b* d* g* W6 M! f
cola_device_t *cola_device_find(const char *name)
! j6 B! K6 Y3 F# X* g# m( J{  X& ^) D  r. R3 q
    cola_device_t* cur = device_list;3 l; z* H& q) W$ Y6 I' R
    while( cur !=NULL)
* D4 L/ A$ H& k" E5 R    {3 Q% |' ^: I3 o3 R# y2 l7 b& U4 Y
        if(strcmp(cur->name,name)==0)
$ F, d. n3 I; R        {! P  [" y2 R: P3 G* t. u% G" s! d
            return cur;5 k! S, S* L* E, ~* w1 H
        }
! P. ?. m% ~" W5 a, w        cur = cur->next;1 r( j* Y$ v7 [+ ~
    }& V0 f7 D1 K4 Z* A0 C
    return NULL;) o7 N" U8 l( _
}  V3 ?6 J% V, l8 |4 o8 x' M0 R
/*
4 I7 M" `5 U$ Q8 Q6 ^8 ?8 B: \    驅(qū)動讀
3 o6 T6 O( v5 C6 Z  ^*/
. ]; K0 K" W( U) Y/ iint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
% O9 Y; i+ B8 P+ F{! k1 C3 B' o0 C! v
    if(dev)
# k% X( {, x9 q4 V6 P    {& M- X+ p9 k4 U" v& S  O" _& u$ `
        if(dev->dops->read)
+ q5 {: |9 Q  Q2 p        {
5 Q" z" ?( L0 g0 T, W6 H" I            return dev->dops->read(dev, pos, buffer, size);
1 w/ A  @$ g6 a6 H" a        }: R6 L/ L0 F, S* L5 E" q
    }6 Z1 g' T) \7 `7 ^% w5 M0 P6 {0 z5 M
    return 0;; l" E# T' u% L9 Q" v, L
}% R+ [. E% C3 R' A; c+ B, ~
/*
" o1 N2 Y4 Z4 `    驅(qū)動寫
5 j$ N6 U8 m2 Q  Z9 A" m*/) A- y4 i% N  M* H* c
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
- A5 N) e  G. o  g6 b- i- m{
& A0 R$ }$ ^( i7 J3 n    if(dev)
' |/ x1 P, l- P    {* M8 X1 O6 D3 f
        if(dev->dops->write). q- m4 [$ M* _$ C3 R8 k2 D. h
        {
/ q, G# w+ P6 I6 W3 w3 V9 c            return dev->dops->write(dev, pos, buffer, size);0 p% X* q/ b5 y
        }, C7 W* w& {9 Q, I" S& y' @
    }7 }8 H! h( L+ y9 C
    return 0;
0 o* x; Z( h4 I, T( r4 ~4 h' H  T}% y( J$ s7 V+ g4 }8 B; Y
/*4 C: J6 m; P$ K% y1 ?' i
    驅(qū)動控制( u8 [: @4 K+ ~1 I+ N6 ^
*/
  K( `; y( k" ^int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
1 I0 E: f3 z1 a; N1 a% r{
# i: y3 b# B8 A9 ?# Z/ g    if(dev)
- ~) \. H# I$ p  m5 W0 Z5 M    {/ \1 |0 {# b: g4 e
        if(dev->dops->control)
0 W% N( p" {- e; r3 I        {
% o- J) P& x" C8 }            return dev->dops->control(dev, cmd, arg);
2 B' e, j! C! S0 N6 s        }
# p8 ~9 j& x: [  d3 L    }: l" u- W- d, `
    return 0;
$ x. d2 s/ U9 U: l  e7 |}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。2 r& A2 P7 a, C& a; y" A/ ^
#include "stm32f0xx.h"' V' l! q3 ~$ X" Y2 `2 K
#include "led.h"0 K6 P2 e" |, X: H
#include "cola_device.h"
; u0 m! f: @- `" m8 C#define PORT_GREEN_LED                 GPIOC                  
) [/ I5 R; J$ V$ y#define PIN_GREENLED                   GPIO_Pin_13              
3 M" L% l+ R# T( q" l* n3 I; ]7 t5 s/* LED亮、滅、變化 */; r* u: \$ O/ A3 |, R
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
) R! P2 b% X3 y* @! w* d#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
* [+ S* K) m0 u! z/ R; c#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
* ?# M9 x+ [% p/ ustatic cola_device_t led_dev;
/ h' x  D$ r8 J# o& ^& bstatic void led_gpio_init(void)1 j3 F& p' c) U- t. ~; h
{
% ^* N4 ~- ]4 h( H+ D    GPIO_InitTypeDef GPIO_InitStructure;2 Z' T. b9 N* g, m3 P7 p5 {
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);. i  c; g! T+ U; a& r- d0 b
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;+ L' h: o, o, G
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;! c- X, ^. B0 {) a
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
* @; q/ U0 {) p    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;) y* T1 {: F- R; ]: ^- |2 b
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;4 w$ h# P* T+ d( E& J. r
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
3 P, }0 l# F* {3 x  p3 W# c    LED_GREEN_OFF;
# G# v/ D1 }4 a* ]- U  C" i$ _}
! n) h. c3 t9 _2 X
( V6 Q8 @3 T& u+ g/ G" vstatic int led_ctrl(cola_device_t *dev, int cmd, void *args)  L9 y) S/ s* x! ^4 d7 ^* l) n2 H
{* s# X/ F4 ?% ^# u& u
    if(LED_TOGGLE == cmd)* N3 }/ g" H: D' s% B) z( p
    {
3 G2 ?6 A3 A) _) p% v        LED_GREEN_TOGGLE;- T! b. n* L0 v% N0 ~( T
    }
9 E3 J* d$ i. C  B  @    else! B& z( V* E1 o3 j. r
    {
: S# X& n! d& `6 l% T4 H    }+ y' v4 q/ O& O3 G
    return 1;2 x) N8 _$ g# k- j
}" l. v/ `6 G# a* W4 T, b
static struct cola_device_ops ops =
* G' b' E0 R! U8 l) i5 s{
$ O( p3 |8 b  a4 g0 G& g$ i .control = led_ctrl,7 y& x/ A8 A! N
};8 h& N2 G+ Y/ B- D
void led_register(void)
% \' W1 l, A! R{
2 A8 y" P) \" D! \- m+ s0 I    led_gpio_init();. N" \& e' e/ B2 E1 g
    led_dev.dops =&ops;
/ x1 s! ?, }1 s) K% J( k7 b9 g    led_dev.name ="led";) I$ Y1 s7 r8 u2 J, S4 [+ L+ ~% P8 O7 U
    cola_device_register(&led_dev);
% [8 j: M1 Z5 f9 Z& K. B}應(yīng)用層app代碼:& S! J, S! [8 W+ g3 J5 N3 y
#include
3 [" R- v$ q" Y( b9 i6 P#include "app.h"
7 v8 ^$ L+ f5 A. f, Y9 `#include "config.h"
6 y7 s% O0 d8 _/ x' }$ l% X#include "cola_device.h"
9 k8 R" w2 o2 w( x* ~#include "cola_os.h"
+ c0 _$ D) z: {% `- `, N( {8 Kstatic task_t timer_500ms;2 ^) N& E3 K- k( f
static cola_device_t*app_led_dev;" t9 U# {2 O& P- M9 n: M+ I
//led每500ms狀態(tài)改變一次
. p$ y9 Z' }# ~7 o, g6 [static void timer_500ms_cb(uint32_t event)
. T% t( y7 E3 k1 e{
( a: q( e$ C$ s" d* B    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
$ B7 ]9 y8 |; n! d8 p% t# a0 i}* U$ N" z2 b. b, f
void app_init(void)
$ b6 N: U$ V2 }8 }{
% t9 g& J0 J) w% r# N    app_led_dev = cola_device_find("led");$ D6 K$ N# C2 c0 v
    assert(app_led_dev);; h7 U$ u' ]7 N0 k! X3 V0 ^0 Q+ z  B" q# L
    cola_timer_create(&timer_500ms,timer_500ms_cb);: H7 s& ^+ C% g( g5 c
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
3 N! L$ @" g5 n/ ~' E}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。9 A' i/ n8 p3 D/ E+ I+ h
四、代碼下載鏈接https://gitee.com/schuck/cola_os; x; i* H9 t2 U8 m/ O- V6 m9 K1 @
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
  S; E5 v# ^0 d% V/ R; q-END-
; V4 t  `1 n! o$ z. P( S往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀
9 u) ]7 Z+ n( S3 O) _                                                       
& t% L8 t1 @" W; n  ?3 X+ A                                                               
% c; S, b! q% K& C9 Q$ \                                                                        ) b3 Z! T" E4 A8 w/ [0 z
                                                                                5 V, f2 V4 `/ w9 H
$ b. F  Z# P8 V2 `+ q* M! o6 z/ G+ F
                                                                                " D" V: v% J  `0 G7 h2 s  F
                                                                                        嵌入式 C 語言的自我修養(yǎng)3 R! N  b/ h, i& P! }( T
                                                       
3 j  u, z: V: b8 a1 x                                                                : |2 b; \( D: U
                                                                        % X2 P" e& e3 U$ X
                                                                               
2 n* O: B! U- ^* C' C 5 J% D" `8 m+ r8 \% o
                                                                                5 U# G/ E0 l; W
                                                                                        被 char 類型的變量坑慘了!
- L. ?" x* ?& c1 B- T5 }                                                                ( Y( [0 m) {, J( _/ @" [# [$ y# m
                                                                       
5 K5 h: O7 `9 O4 @# X% G$ u                                                                                ' T" [* T+ k! r" X4 G9 C

. g+ t# e5 l6 S* L/ d                                                                               
1 ]1 X! G  `( Q) w& B1 c' U( t3 q                                                                                        嵌入式 C 語言知識點(diǎn),動態(tài)變長數(shù)組
$ W2 {0 s$ ~- L. R, Y2 v2 I  o                                                                                ; d) f6 ~+ p8 \- l( z
                                                                       
& }' p' n2 x+ Y7 H; g& R5 n- U                                                               
( h+ G. `8 h6 I9 P3 j3 R" @. o                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師& {/ C1 A* Y; H1 N
關(guān)注我,一起變得更加優(yōu)秀!
回復(fù)

使用道具 舉報

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

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

本版積分規(guī)則


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