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

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

搜索
查看: 49|回復: 0
收起左側

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

[復制鏈接]

437

主題

437

帖子

96

積分

一級會員

Rank: 1

積分
96
跳轉到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
我是老溫,一名熱愛學習的嵌入式工程師
' D0 m2 Q" f! U% v% n/ R! F關注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。
/ u9 z8 I8 v: t; L使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅動層。
- W% _' C# P' B. p* n9 {. z   I; H+ A! r! Y) \; ^$ D
二、實現(xiàn)原理原理就是將硬件操作的接口全都放到驅動鏈表上,在驅動層實現(xiàn)device的open、read、write等操作。當然這樣做也有弊端,就是驅動find的時候需要遍歷一遍驅動鏈表,這樣會增加代碼運行時間。
6 o; U8 k2 V0 T6 o三、代碼實現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread0 t! f/ B+ y0 {, c" r$ m* j& P
頭文件接口:* R& Y7 B  |6 |" M0 s
本次只實現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應用層中只調用如下接口可實現(xiàn):
0 Z: C, [. K& M9 `1 ]3 b- v( W- D/ G4 D/*
. ?0 h: b7 d) b    驅動注冊  n, q- C% V! p3 @: g
*/5 Z/ Q- e/ D( i
int cola_device_register(cola_device_t *dev);# e+ m, S- b) I: g' _, Q7 l, |
/*$ V+ x& y# B& K4 c
    驅動查找
7 @1 Q; V8 g& K% W*/
. a9 V  v( W1 Ccola_device_t *cola_device_find(const char *name);
, a- Z! T/ Z; ?/*
# ^# p# ~2 L  N- b0 e    驅動讀2 I: u- K5 L1 o5 A9 l6 ]
*/9 U4 L3 Q: J' P+ E3 w
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);6 d0 V: e; Y# }; m$ {8 o
/*
* U, n3 P3 ~4 {6 l- U' s    驅動寫
  z2 ]& q3 }7 P- s& f*/
/ X( t5 ?# R" F: B$ n( Jint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);" F) ^, m' T. u9 D2 s* f9 M* h" w
/*
- S( @9 ^% V) ], V) d9 P    驅動控制6 q6 s$ y: ^) D- m
*/
, X) @2 ?0 l6 n( |  E  `int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
8 t% L8 W  k# a1 b#ifndef _COLA_DEVICE_H_
/ p: V: i: U( Z* l9 Y" E#define _COLA_DEVICE_H_! Z% |& V% L1 x1 v. ?
enum LED_state2 k1 D  B: u7 G) J4 H* y4 s& Q' ^
{
% M5 t- [4 b0 \2 Z+ l    LED_OFF,
" q7 y* s9 o- n' ?    LED_ON,
' `; A' g1 V6 J2 E1 t( F" b    LED_TOGGLE,3 U" R- K, @) x6 x4 e
};
) W' q. E! ?" ^  c7 C: g6 @typedef struct cola_device  cola_device_t;4 i. X- O& d4 k) D5 c
struct cola_device_ops9 j  X$ l7 W' ?' {! \
{" K- }0 U3 `' O- E. m3 b/ S  Y0 q' n
    int(*init)(cola_device_t*dev);, b) T# @% J; }  l) w
    int(*open)(cola_device_t*dev,int oflag);
& S& k+ L7 t( J9 z! r+ F8 v  ^$ A    int(*close)(cola_device_t*dev);+ h, I) m2 R/ f) Z3 Q5 Z
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);8 _6 `+ J% [: }( f6 Z
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
8 q' J  `! D/ k# ^    int(*control)(cola_device_t*dev,int cmd,void*args);4 d+ {3 `7 }# c' N" ?) }' ?2 n
};' H' V+ h7 h) I9 f) r0 c6 h
struct cola_device6 u, J4 y2 ~5 C- Y& l
{' C5 o0 r+ ]' B+ M  k
    const char* name;# i* {* s+ }# a0 @0 L7 p$ L
    struct cola_device_ops *dops;& d# H, y5 H( ?# H/ _2 @3 G+ j
    struct cola_device *next;
1 c" I) M+ Q4 a0 t3 X! N};# G# C: [9 ]* \. V/ c: F
/*- N- [# x: C4 c2 g
    驅動注冊# l! A2 @  f* G$ W0 P& u' `
*/
6 r: Y# L% D0 t6 u5 h. gint cola_device_register(cola_device_t *dev);& `: c* R4 J! F; B2 {( k, b4 E! z
/*
& e' ~! c6 C: }( u7 L# ~    驅動查找- `6 J! C7 z7 T
*/: y2 O% _# h; ~+ V. z$ t" A* `/ ^
cola_device_t *cola_device_find(const char *name);
: O: Y/ A" S2 l0 Z5 g7 U8 B/*, y1 T% Z2 `# L# k+ u' c
    驅動讀
2 M$ l  i% y/ {5 ]0 F/ G" l* E+ F! i*// G2 i# }- n$ {2 ?6 ]
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
$ _3 I. [  S$ a) h- T0 B5 x/*
* I  W6 `2 v  X' u9 n    驅動寫
6 w- E# _5 W" U1 x% ^6 `4 z1 x*/2 R& s- z0 X* N+ |
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);3 A5 G0 r! ^  y; Q5 P5 G
/*4 V( T9 B3 i- n0 k- t5 ^( v
    驅動控制
/ Y4 I1 }6 I3 U* v( c3 r0 f! C*/% H$ V4 f. C) }+ b9 t
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);! y( _8 E" O" b7 c7 v
#endif 源文件cola_device.c:1 C5 y5 f- ]' P9 g* |
#include "cola_device.h"  |: J8 b( V/ c4 k2 ~
#include
, M; E) B0 x/ \+ Q% G#include % S) V: D% x  i0 B) O, A" Z
struct cola_device *device_list = NULL;( M. J& N' v, y5 x; ?; ?* z- Y( ]- z
/*5 V, x0 ]* [. \$ |& c
    查找任務是否存在
& I: D8 e* J& X$ ^6 H/ s% u* I, z*/; ?2 S# C3 @/ O- B7 e: k
static bool cola_device_is_exists( cola_device_t *dev )
. ]* T9 M+ p/ l5 b9 I{
. j) U: t1 p2 g    cola_device_t* cur = device_list;( N% A& J6 a3 I! P  z
    while( cur !=NULL)
) a6 A8 c9 w" J7 U- k    {4 ], _0 c( q& U$ o! m" N* p- u" ?
        if(strcmp(cur->name,dev->name)==0)
) G' l" d# ^$ G0 S: k5 j& h        {
+ E( J, |4 }3 a            return true;
8 L4 E8 f+ }/ B. A* U3 [        }
5 L: M6 m3 a! [" h8 i. u  r+ F        cur = cur->next;; I& i! P' ]1 @+ _& \  z
    }  ]1 ?( V7 g9 R9 O
    return false;) h4 \2 _" k/ Z& s& K3 L1 a
}
; g: D* o; t$ C8 hstatic int device_list_inster(cola_device_t *dev)6 _. S( G) C! g: J4 w# F
{
" S+ p3 G9 F' q- e% b7 C# ?    cola_device_t *cur = device_list;
8 J& a6 ^/ U, [+ c3 W& t    if(NULL== device_list), f4 ~  ?' e" c' O, t% m
    {1 C: |, p1 B* i
        device_list = dev;
4 m& M! u, b) N; Y/ v4 b5 z        dev->next   = NULL;8 R3 L: [8 |3 u% F
    }* q1 r) t1 p+ I+ H8 k' O
    else. Y# `4 V$ c- |" c1 n
    {1 l$ ^# u6 x- a3 L( i5 h- z6 |: y1 n
        while(NULL!= cur->next)
/ ^' {0 G& w; F3 s+ F        {# c; S, H0 ]( z1 u+ K2 o0 {' o
            cur = cur->next;
, P! k, E- \$ k9 b  k$ g& J9 K' I        }
( z+ s2 G* P: n( B        cur->next = dev;" F1 z4 A5 Y7 ]
        dev->next = NULL;
% `7 S7 O! I* u& ~' K" z    }
% I8 p* J( d& ^& h2 t" }' D    return 1;. j  ]5 t5 ]; t4 ~
}* q3 M) w, w6 E/ |0 w
/*8 b  T: `" Z1 N' Q3 y" d
    驅動注冊; M6 i% o* n8 d3 n+ z5 ~3 }) h% i
*/* O" c$ K8 ?. y: I# g1 o$ I0 X
int cola_device_register(cola_device_t *dev)- \# D/ V9 K; d0 ~7 @* Z% z" Q
{  q$ B0 S: G0 i
    if((NULL== dev)||(cola_device_is_exists(dev)))
1 P  V2 z2 [# m: i    {# R, W% x6 U0 N/ `" J5 q/ ~
        return 0;
+ K0 d/ _4 S  J( E" f: n    }
/ r. O& w$ T( R: I    if((NULL== dev->name)||(NULL== dev->dops))/ X  Y0 l# |; F; e
    {; d, @$ l8 s  z# Y  B* @
        return 0;% Q4 Z% q4 o: W9 |* g' j
    }
% K6 S+ N. F7 V3 {0 ]* C6 r    return device_list_inster(dev);
; K: \. G! s! |2 Z  z9 {}$ v4 `( p- ^5 H
/*
1 Z0 o. N! G7 \: P    驅動查找6 m& v0 O7 T( L$ b4 @/ K: c1 [: Y( l
*/
/ v! D& h/ E% l* i3 _4 @: Q/ Y: _cola_device_t *cola_device_find(const char *name)0 H# S2 M2 |9 A0 K; s, i
{" i$ z' K7 Y+ c
    cola_device_t* cur = device_list;
, O" I3 W8 X. U; d* e    while( cur !=NULL)
) F, {, h& T% L2 @1 P    {8 _; C& u" a  i( U. ]0 p% H- d8 S
        if(strcmp(cur->name,name)==0)
3 c0 \1 p4 {% U' m8 Y( d        {
  D% D* b( P6 D6 a5 x4 U            return cur;7 D+ f( ^* a5 M1 X" I0 h$ C. H/ E) w
        }0 K  r. x" R! a: L5 i# C9 E# R2 t; ^
        cur = cur->next;
+ Q) B5 d# {) Z  X    }
1 `+ m6 h% W  P8 V% B    return NULL;. X, j: {7 O' m2 ]( j5 [1 q
}
! e4 @2 s# d& o; |# @1 N/*
$ r: j6 k( b  t$ P) P3 o' L9 K    驅動讀0 _# q9 M  \& F" a
*/5 j4 l! R9 k! ^
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size), H+ K, e6 @3 h* `/ G, x
{
7 [7 d& b$ B: D/ D) S5 B    if(dev)- U1 m. R1 r& I; ^4 A+ _# f2 O
    {
" w6 l9 r' K- n/ {* M6 Q        if(dev->dops->read)
1 B: X2 x" x3 z  Z5 R4 n- E( G. k) A        {0 i0 Y: R, W! R; {) O2 v
            return dev->dops->read(dev, pos, buffer, size);% T% X/ }$ ?* E) y6 m
        }* t" G: f5 D/ Z5 i
    }
3 [' f  G' d% t* L# H) T    return 0;
! b: R5 ]: S6 @" B1 [# g}
3 y" q& S4 Q( V. n4 C  n* A# l/*
, h$ _% ]& S. c4 q" L1 q! j6 a    驅動寫
4 i. Q/ o  J' p*/
9 D  |( |7 O$ ^' T, \int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)" k4 N& [0 j5 D! n) U
{( X- J$ }4 j3 ~$ q! o; [* b/ V
    if(dev)
- p# f, y1 g9 S    {
- P8 |3 m5 L3 X+ c& |3 v        if(dev->dops->write)8 B2 j$ L3 W" g+ d; m
        {3 h( B: A: _% U) \0 o# U6 C& O0 ^- L
            return dev->dops->write(dev, pos, buffer, size);/ n( ^5 ~2 L) q" K. x8 ^
        }5 }+ p1 n2 j4 m. A% t% m$ ^1 u
    }2 U1 D( n* d5 r6 ?' P6 q
    return 0;, T  M" Z' g6 o4 t
}
9 |6 [- g- k7 @/*
9 \( F& u' h2 B9 ~    驅動控制" Z. M0 z: S/ D1 N( r: |& ^. }
*/
9 J7 P' c* e3 n+ Kint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
, v+ R4 i" Q7 G/ U" f7 _* K4 i{
# n% \- C5 I. z* L$ d! c    if(dev)
5 o' Y6 b& @1 |" t9 B    {
7 P8 O, _, f0 p. X: o! v, {6 m        if(dev->dops->control)
! W1 L( W2 l2 m. T% l        {  a$ B7 L3 [* n, i: h
            return dev->dops->control(dev, cmd, arg);) E  l; E, w) h! o$ C% K/ l9 U5 I% s' X
        }
) j  P) A" H- w8 ], C9 Q( K  Z    }- j3 x( u! z3 ?# \
    return 0;
1 s) B3 x# `/ B2 k}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調用。
) Z; M" n5 l% O. [, W8 L  h#include "stm32f0xx.h"; i7 a0 V7 [6 B2 d3 |+ l* ?
#include "led.h": c3 R  ?) {; N; Y% h0 x9 i/ p
#include "cola_device.h"
. V. R' P& P, {( `#define PORT_GREEN_LED                 GPIOC                  
% K. `6 K& Z' M4 D  j: E; z0 O#define PIN_GREENLED                   GPIO_Pin_13              
+ {* f$ @2 H0 \2 M+ k/* LED亮、滅、變化 */
1 @% I" ?4 [4 l1 n+ @" B#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)8 N3 P9 m/ q" s; E' e
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)  L% b  z  ^3 R! X  A! S& o
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
3 G. m! F2 R/ Mstatic cola_device_t led_dev;# d- A8 F* \& B9 I, N& K$ z  J% W
static void led_gpio_init(void)/ T. D% A; Y; Z
{: D' D$ b3 K* p8 D6 Q* L
    GPIO_InitTypeDef GPIO_InitStructure;9 M6 p" \3 m8 Q+ D9 S
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/ ]& |9 X% u2 Z* v- C    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
! z" y  w) k1 {+ i$ b  _) o/ s+ t1 R    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;8 @' t3 {- Q- m8 k( T( {: L
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
, J+ b: ^' m2 U. c7 P    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;8 J, s6 y  |" W( [/ c5 O4 _
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;. y1 b7 f7 j$ _- b& p1 `* x$ l
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
* n4 a* {4 s* S    LED_GREEN_OFF;$ W! B& \8 R1 Q/ p  E
}4 E$ R5 e+ a4 K9 I
: s: U  m& j* D; S0 m
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
- N6 T* t* c7 H  O, @7 U{
/ {: u+ O' E, h$ k& R7 r$ S8 C    if(LED_TOGGLE == cmd)
; ?7 Z! E% |( Y2 w+ `    {
7 ?4 b' k/ ~$ [8 J# T' N; P0 h* c        LED_GREEN_TOGGLE;. Y# B6 h: Y" }/ b; W7 f" `
    }
8 g" a/ X& g* ^* X# o/ Z    else+ W; B# s8 F: l, y8 e( r
    {! x6 [' g/ `  p+ `4 N$ S
    }; p8 b* V/ p) T( G; i9 O
    return 1;- p7 f& y" I1 i) R6 Z/ u6 b
}
& C1 r  k' }  s$ x6 }$ x3 w5 S7 K) mstatic struct cola_device_ops ops =
1 P8 ?. `# U7 w{. g; j- B6 Q: H1 h; T
.control = led_ctrl,
1 L2 S; D' M8 Q4 r9 u/ Q  `, G};. }* b3 ?/ ]; H
void led_register(void)
: s; y! C  ]8 C1 `$ r2 C4 @; c6 B{7 z. d& H9 B( d3 t) H
    led_gpio_init();! ?+ e+ B: P; r( r. x
    led_dev.dops =&ops;. _+ k' A1 Q) i$ J3 O
    led_dev.name ="led";
/ L; S: L! Y5 D: _    cola_device_register(&led_dev);
; i- n8 R$ z3 T8 w  l}應用層app代碼:5 m2 U& n  d0 l& m. }$ A6 W5 I8 m
#include 1 E6 g4 N( J% L9 [7 B
#include "app.h"6 G" H7 [$ P( w' T
#include "config.h"
/ z9 A' x/ ]& c2 |; U: t) b#include "cola_device.h"
2 g7 l, V; a1 ~1 Y5 j" n#include "cola_os.h"' ?& U/ z0 B2 ?' l# O* d
static task_t timer_500ms;
6 Z( \, P6 O! K' `% ^static cola_device_t*app_led_dev;# f5 |  u  T/ @$ o
//led每500ms狀態(tài)改變一次
4 T, ?. L* u1 {! i# y0 kstatic void timer_500ms_cb(uint32_t event)
% \( n) R4 K/ U* |) U{
' F( K" b% a! w2 K4 R* m    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);. G/ Y% V6 w- X  ~8 I( J, C
}9 j3 u  N8 E8 c" Q# p9 H" J
void app_init(void)& ~' I" H& T3 L" B6 g% W
{/ h8 I4 ~4 A4 b( K
    app_led_dev = cola_device_find("led");$ q' Q' b, E" C6 o% Y
    assert(app_led_dev);
. y7 T# X" `& w! K    cola_timer_create(&timer_500ms,timer_500ms_cb);
8 f( ~: c' ?: @' }! E. h9 s% i* X    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);9 c$ H( T) j* Z" A' o
}這樣app.c文件中就不需要調用led.h頭文件了,rtt就是這樣實現(xiàn)的。
( K) {- d; |5 B2 c5 r& w( {# C四、代碼下載鏈接https://gitee.com/schuck/cola_os
' R/ x9 n- c1 u/ P, C- o
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722  P) l4 `2 C( q) b5 i
-END-
0 N, b+ A) L. H往期推薦:點擊圖片即可跳轉閱讀& ?8 H+ h2 P8 r+ N$ s, ^, a
                                                       
! }9 F! Z9 e1 G* j) e+ j1 h                                                               
) \( r' P# v3 F7 ?3 H0 B9 h5 K                                                                       
0 D; b  W2 R% t0 g6 X. Z4 e                                                                                & c# o& J+ p" A" o/ _* N& x- Z

2 V7 H1 k$ E2 T' s& N  Z* w. _& {                                                                                3 z; q; |0 j3 n
                                                                                        嵌入式 C 語言的自我修養(yǎng)
  l  _. p: K+ J- E1 i+ d/ H                                                       
: h: u$ X6 Q2 u                                                               
  @5 j- W  K( z  V* X# X                                                                        & D0 ]8 s# X# w/ h7 O
                                                                                9 q4 p, r# D! {

9 l! n( N" P9 o# @: A, F& L                                                                               
# H8 k; q0 v3 ^                                                                                        被 char 類型的變量坑慘了!3 p" v" t) ]# w; u
                                                                ! U1 ?; Z2 x2 a" s( j
                                                                        * h/ S' }7 [7 o! u* J2 b9 H+ q
                                                                                1 t5 D7 J6 w5 R% ^+ R1 Z3 s

& j0 i3 s' A, f  N3 j4 ?/ c# e                                                                                5 T% C2 \! w+ B, ^0 [% Y, O
                                                                                        嵌入式 C 語言知識點,動態(tài)變長數(shù)組+ x/ i$ G/ O4 I' k
                                                                               
, b, M  y0 B, W                                                                        . z+ e5 D; b, Y+ D4 S" d6 V
                                                               
* r/ X  J' c( S- K                                                        我是老溫,一名熱愛學習的嵌入式工程師
) y8 e, `1 U$ O4 e+ @$ C關注我,一起變得更加優(yōu)秀!
回復

使用道具 舉報

發(fā)表回復

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

本版積分規(guī)則


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