电子产业一站式赋能平台

PCB联盟网

搜索
查看: 206|回复: 0
收起左侧

如何实现嵌入式软硬件分层处理接口?

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师  v% S/ s; [: \
关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
% h( K6 P8 F8 ^# O! c* l& |使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。  K- R) z4 _2 u% d* F0 F/ p

kgq5x1duezb6402851105.png

kgq5x1duezb6402851105.png

: N- V8 C4 U" b- ~% {1 y# P5 M) j二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。1 @. k' w: n8 g, N
三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread% M. C! i4 x9 _1 L
头文件接口:1 J, X: K0 P# B* r1 F9 F
本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
$ ^0 t* a: l) _& w: ~* V' ]/*: x7 T0 j: W: W' A' Q9 f4 P: E
    驱动注册
; [& }" h% L0 u, t; z: L- w4 G*/; c8 b9 C& Q3 x! l$ V9 S! I# h
int cola_device_register(cola_device_t *dev);3 U1 o% s! ]0 d; E
/*
3 I1 I  r, g- f, u    驱动查找
- t5 D3 w4 X2 S6 V*/1 _2 r* V' g2 n
cola_device_t *cola_device_find(const char *name);
' g/ E0 r) G  @5 ^! v8 R9 L/*/ W# U  y4 @; x* _. Y4 j" M7 `/ C
    驱动读- y" u! v* j( `- V
*/
) ^" [0 G) v1 I8 \6 G! ]int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);7 P2 d8 F5 f( }, w5 q
/*% k( L) B# D7 Q7 R4 l6 H
    驱动写( o0 l  v- }( V
*/
, W9 L" F4 x. k( o# |& V6 Nint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);8 u- O7 U! o$ ^, {/ G( `
/*( W' Q. M/ M. `5 D$ q! N% ?
    驱动控制& ?) {9 p1 B- ]5 g0 Q3 i2 P
*/4 `  `9 y9 ?- e# J; [
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:
7 G7 I' a) M* U#ifndef _COLA_DEVICE_H_
" j0 O$ O9 x' `$ R6 m#define _COLA_DEVICE_H_' q8 w5 }! V+ P  q3 z
enum LED_state0 U3 n4 g0 `8 y
{
; i$ f: @* c% A# N2 b+ n7 F) \    LED_OFF,9 L5 k6 _) ?: V/ ~, Y3 w  U
    LED_ON,
, E/ _8 r1 X: c5 H    LED_TOGGLE,
& [) e+ X2 E- _7 w# r% v9 ]6 w3 u( U};
1 r! ~: [0 }: z& Ctypedef struct cola_device  cola_device_t;9 G* u/ X& D5 P) V* G2 I6 c
struct cola_device_ops
5 L0 [  k3 r' n: `: P, C5 A4 k6 ^{
! b% j1 _# s9 B) n' v' s    int(*init)(cola_device_t*dev);
/ u# B* x! S& g; X9 K; ]) V& Q" X    int(*open)(cola_device_t*dev,int oflag);+ [: R  }* v& X
    int(*close)(cola_device_t*dev);' H, {: \0 x2 F/ s# F9 d( m3 K" h
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
: R, u% f1 u* o$ T    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
, Q$ X' `: e- g3 b: _7 d    int(*control)(cola_device_t*dev,int cmd,void*args);; Z$ |# y" I: t" o9 c+ Q( D3 n  K$ A
};" y) k1 g5 `9 ]
struct cola_device& E5 j! e! l+ D$ c/ q+ I) h
{
1 H! P( _! T2 M. |0 B    const char* name;$ g% ~. A) [) ~3 u
    struct cola_device_ops *dops;
6 ^9 I, c8 A4 Y5 N6 u5 ?& i3 q    struct cola_device *next;
5 o2 r: O8 g4 A4 k) f7 L};3 x/ Z: \" Z% C2 z0 |
/** }* Y2 i+ P6 v
    驱动注册0 Z+ Q- y  W" Y
*/7 m- t/ `0 P" z/ Z4 b# v# `
int cola_device_register(cola_device_t *dev);
2 q# z% V" N( @& {4 L0 H/*
3 S( c4 k) h3 b. h( B5 W0 T& b, S5 |    驱动查找
4 R8 n. _4 N/ F4 ~2 _*/
9 _% V* T- q4 y9 ?8 |9 Ncola_device_t *cola_device_find(const char *name);- e# P8 X5 U5 s5 T
/*
% ]# d; R" w* B2 Z. R    驱动读, M7 {. r6 Z8 ^( e  r
*/' B0 J) H7 s8 u! g6 G
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
/ L3 j  Z3 G8 \5 J# _2 s/*$ k, ]7 t0 ^2 P5 w$ H: |: U  d
    驱动写' w7 j2 D; A1 _* r& T
*/
# z+ k  \  p3 e2 K% E$ U# Mint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
& `5 b; o( S% O  n" C: V. _/*  q* o: l* a4 B9 F
    驱动控制
7 `5 F, V7 `# e5 H; L% r4 [! [*/
0 e2 q$ E9 J$ Z* lint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);7 P" I8 |; ]0 Z- l# E  ^
#endif 源文件cola_device.c:
! \6 a$ V( [1 d#include "cola_device.h"
% K2 c2 V9 g. }#include
! X* S% @9 {& {0 Y% w3 y#include
0 s! C: x0 e7 m+ astruct cola_device *device_list = NULL;
3 \6 U0 _7 O9 F3 l; k1 h/*6 ]2 a4 S* c5 s
    查找任务是否存在
  X, ^8 ?! R& l( K. G" Z*/( a' e8 Y) [6 H4 s! t
static bool cola_device_is_exists( cola_device_t *dev )
3 }, x2 F: E3 \$ U. D0 [{
) t* o: `9 b* l  d! l& X    cola_device_t* cur = device_list;4 e2 X& f* W9 W1 T
    while( cur !=NULL)- T% q( C6 x% {6 }- I% u# l
    {3 H( B1 }3 q& }' P. _! R
        if(strcmp(cur->name,dev->name)==0)
- b, B2 n( b  U( e$ w        {4 t9 |8 l6 Q; p( Q" A) w
            return true;
; o4 I+ ^& [7 s  `        }% _) [2 m0 D. m/ m1 S
        cur = cur->next;; d4 x% I) P# K9 h$ O9 o/ Q
    }
% @. s1 i  F7 ?+ T3 s+ t    return false;
# P8 M3 U0 ~$ Z9 J}
9 J% ]! n6 X: I2 m3 n0 X1 s& astatic int device_list_inster(cola_device_t *dev)6 K1 b9 T1 i1 l: k3 k' R
{
( @' t  s! J* ?$ H) G    cola_device_t *cur = device_list;$ g9 E5 _  ~9 Q- W9 B  l2 X/ x; D
    if(NULL== device_list), O, ]+ M8 _7 Y4 v, l% b6 [# ?
    {. z2 a5 F/ k. a8 d- w8 Z+ }5 U
        device_list = dev;
' o! t& l3 L9 z* M. N  F        dev->next   = NULL;
/ K8 O2 I1 C9 l8 X$ K( b    }: I/ h1 Y. r# v+ p. ?
    else4 z7 ]* _  Y' m# ^1 U2 z
    {( }" }& |: |9 S% p, [) T
        while(NULL!= cur->next)
! K- f8 n. w/ }8 j" N        {8 u# s: p: v5 ?* n6 T
            cur = cur->next;
" z2 {9 F! W& o/ W/ {* g' V        }1 G: ?9 N( P' ?& b5 n
        cur->next = dev;
7 m; e$ [, P  A* H        dev->next = NULL;
' u: l( g4 W8 n    }: P9 B8 h' Y- d
    return 1;" a, s$ y$ e2 Q' Z
}' t5 }% c/ y* A7 ?1 p+ {
/*: \' J% j8 a* S; y& x
    驱动注册" p( y3 L8 v9 l; \! P, c
*/
' H0 l, q4 ?& q3 [; N# lint cola_device_register(cola_device_t *dev), S3 t( x) j% f4 \3 w
{
6 S1 A( ?9 m3 b+ ~5 u6 v) {    if((NULL== dev)||(cola_device_is_exists(dev)))
( g4 O" K3 Q, N- {) i    {1 X1 W3 S' l/ m" q
        return 0;! W8 p. Q9 {9 P
    }4 M. L. r/ J% w3 C9 r2 j( z$ u
    if((NULL== dev->name)||(NULL== dev->dops))0 F. o% v" \# X1 b/ P
    {5 m2 v  M( F8 l2 s2 v6 K; w' |
        return 0;
" P" o% f: A- @: A) W  A    }+ k" T# b/ L7 d) [. U! H  `
    return device_list_inster(dev);9 M# t( v! D9 p% n" S& n
}: u  K. z/ l7 c, M+ {7 c
/*
% |/ \) R: y/ @/ a1 m+ O$ B7 G7 ]    驱动查找. y2 T8 a$ ~1 L6 e0 r3 I  ?
*/
2 j: g7 C* G$ L& acola_device_t *cola_device_find(const char *name)
: P" r, I" d0 L7 S3 `: J0 H; w{
( {  V5 ]! K( h9 w    cola_device_t* cur = device_list;7 {9 _) S4 H! _# p' }8 _9 Y' ]
    while( cur !=NULL)0 T5 F  s1 w( G4 R' [: P7 s
    {  g% J' M- D! N: ?: Z) M( v6 S+ d
        if(strcmp(cur->name,name)==0)
! K- H# H( j2 S9 T) R  N' ]        {- s7 q! s2 n, I( n( e
            return cur;1 F) F% w* H/ O4 Q" V/ F
        }+ a' m# ~3 j" }" e) j/ S
        cur = cur->next;0 o+ {* l' G! ]: n; I/ b9 |# }
    }
/ {! ?8 J8 O# ]# m    return NULL;
7 O" `) |- k- ?/ i3 J  q: J4 o}# g+ X, k8 d, _
/** u; P1 [! ]1 Y& k1 [% q9 x
    驱动读6 h& u5 j4 v9 ^% _0 U- y7 L
*/
/ a  l4 H1 G7 l$ r4 dint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)7 i+ d1 N# p" @
{- \( R. i+ m& k& T5 p; }. \
    if(dev)
7 n* i3 n# P/ A; ~7 U7 U# a    {
7 n* l% I9 O2 u4 S5 \2 C        if(dev->dops->read)
7 [/ }7 Y7 o8 G9 o* N' {        {& P( a. j. }9 y  \; i+ ]
            return dev->dops->read(dev, pos, buffer, size);
! K% ?0 N: Y4 ?; c% `3 q9 V; g+ F% ~        }
, v" X. z- Y$ }0 A% m    }
$ I" v9 z: j  P6 l' r    return 0;
, ~+ L4 C) p% G( g' J5 D}
" H+ L$ w/ y! [5 L/*
4 F) N, G* E3 ]( b# b    驱动写
- j* b0 A" I0 _0 ~% C5 P*/, J3 P+ [8 \0 f' L, r. M* L4 N
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)* B0 s; U* u* z- x1 G
{2 m" i2 A  e( R/ m
    if(dev), J: E* q7 |" A# L1 C6 q' p
    {
& f0 v" X7 W4 e' K3 w5 P2 i0 x        if(dev->dops->write)3 a* n8 {. ~8 N+ M
        {0 r7 ]1 p! ^. ^$ b: U
            return dev->dops->write(dev, pos, buffer, size);0 O5 V/ [$ q) H2 {
        }. G, j% t& o) M/ h) k* r; r
    }
8 J- U( J1 D5 G9 U0 ~- `    return 0;) n! z4 ~) W9 S0 A) A
}
: f: ?+ v9 E% v" Y% ?4 Y9 T( |/*5 q$ P# N, t! E% z9 G6 P
    驱动控制, t4 ]( `; a' }, c
*/
6 W" @. d5 M# w& Hint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
, |7 W6 {; |6 b% C" p. {9 z. H{" _& R6 P9 j% v, P* j8 i% R8 F
    if(dev)
) k& `% Q4 Y1 ?0 T; M% `: L    {* z5 C5 P) C7 @4 D  j
        if(dev->dops->control)6 e# I) E- x' s0 D0 v) k
        {
6 W8 A1 {( X( g: L4 v6 S6 i$ r            return dev->dops->control(dev, cmd, arg);# {* O! _4 O* a/ x$ B4 J
        }
* t2 U8 |; F& \* e    }
8 d$ Q9 ~. g- f3 r3 X    return 0;3 t6 Z& t6 B8 b' u( h7 [
}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。
$ K* x7 Q+ W2 q  g; H* L- W#include "stm32f0xx.h"3 l; h8 X+ {& P) X% o% ~+ `
#include "led.h"" G2 O4 ~4 Z' X+ j6 C  h8 o
#include "cola_device.h"
$ B' V9 J6 h+ R0 m6 K9 K) Y#define PORT_GREEN_LED                 GPIOC                  
0 W" |4 F8 k! T# L0 z#define PIN_GREENLED                   GPIO_Pin_13              ( R# b2 f2 l! P  }" ]! K1 F: F& h/ B
/* LED亮、灭、变化 */( _# z) ]0 t8 o; M: r/ Y: L! d
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)* W. u/ J- Z! x1 T4 ]# p) L* c- @
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED); V7 s! f9 V6 V/ W' `& @
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
1 D) z2 @" J8 dstatic cola_device_t led_dev;
" ]/ }9 j8 ~* q: }% P6 ustatic void led_gpio_init(void)8 X, [0 A% o/ q  p% ], F
{0 d8 |( s0 k/ ^) m
    GPIO_InitTypeDef GPIO_InitStructure;3 }1 t$ l, u$ X, [8 |
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);+ x1 k% z. R: Q0 ?% H' r1 y
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
$ E9 G/ D* v# B) V- i& y* j    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
; |. Q7 Q9 d. T' w    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
2 R' x3 ]% W5 I- }0 R    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
) {4 W/ b6 s5 @9 u! \4 v    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;$ k) o  c; @+ _) u( B; X
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
) r# E" U* h9 m$ |2 c3 ?    LED_GREEN_OFF;
' L2 i# q7 y& g( k}; R6 |+ R* V5 _/ u/ `+ n
4 E, D! N4 }% C1 g, x
static int led_ctrl(cola_device_t *dev, int cmd, void *args)8 {& W4 j' o. m% x' t
{
+ W4 n7 M' ?) E3 v: i8 e    if(LED_TOGGLE == cmd)
& h. I' X. X0 W: [6 {4 _. j    {
& r( b7 o" h" q9 M8 _) m        LED_GREEN_TOGGLE;
3 W( R2 F7 C9 M" j" {, V    }  R4 h6 ~# i2 C  U/ A
    else
& _  Q0 L/ [8 }( |9 J" z+ u; x    {! j) d; k" ?* D4 @- R. q4 X2 b
    }
  e. i$ G. u2 j# B9 o/ t$ T    return 1;- }% L* G: ?1 Z; z! d
}
. o$ ~9 d* ~0 e# R) \static struct cola_device_ops ops =+ {6 ]; H) x+ ]) j& J4 D
{2 {5 l) r7 {: X( \: `& E. V3 `
.control = led_ctrl,& |) f9 d' Q! v( m7 v
};. P. i" o, e$ _# X' r- M
void led_register(void)
- v" O4 ~) P) O) `* D. @{4 M- k3 F5 R6 I0 E6 @3 b/ M
    led_gpio_init();
1 |$ o$ |) }: s/ g" Z# |    led_dev.dops =&ops;! J1 N$ c/ v# Z; B5 B
    led_dev.name ="led";9 j9 @/ \* D/ ^: ~7 }7 l: h
    cola_device_register(&led_dev);+ \# |1 H1 f; o+ d' ^- g6 M
}应用层app代码:) N; i. a* ~$ D5 ]$ z5 J
#include
# ?* [  w( Y9 t9 K- ~#include "app.h"
& x5 n3 e6 H& Z# g% K: k8 F#include "config.h"1 w: g' `/ `1 M+ e* M
#include "cola_device.h"
7 ~% C9 m" v% e3 ~$ T  @2 q- Y1 v#include "cola_os.h"
. Y2 F5 L- W4 u" [& ustatic task_t timer_500ms;
; p3 D8 b+ C5 g8 k: g. {7 Istatic cola_device_t*app_led_dev;
; @/ O+ ]( C/ i$ X) V" d//led每500ms状态改变一次
1 f! {* J" [8 M# \- \1 Estatic void timer_500ms_cb(uint32_t event)1 s2 V) ^; o8 z9 K
{1 A" }1 N0 o% [# u9 V
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);  ^# c# c2 p4 m
}
' P$ f9 H2 k* q: G4 u& ^$ Lvoid app_init(void)+ _' F2 H+ u2 `
{
" }; z$ V, q# j# T% k6 H0 J$ a    app_led_dev = cola_device_find("led");+ O6 `  i. T9 z* K2 G% C3 n
    assert(app_led_dev);
, O% v- a( G( q# R; u    cola_timer_create(&timer_500ms,timer_500ms_cb);
& f9 E: ]$ e  l    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);6 U3 N# V$ k" Q$ V8 t* F# p
}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。. {  a7 L9 k( @  L) u0 j1 [8 W
四、代码下载链接https://gitee.com/schuck/cola_os
* C3 g- s4 t! w& a) J# G# e9 z
原文链接:https://blog.csdn.net/ziqi5543/article/details/1015127221 R/ r" Y3 z' `) W) x
-END-' F! h7 ^7 d" L% c, Y
往期推荐:点击图片即可跳转阅读
* w3 a: q; c. f: e& Y) X/ K                                                       
  W8 K, N- V$ w- f3 K* U* v2 _                                                                ; _, g+ z% J. i) C
                                                                       
+ N) o! h, N: N5 N                                                                                $ z' d2 H! K  o1 @  D7 f0 ]6 S

b0beaurbwco6402851205.jpg

b0beaurbwco6402851205.jpg

( M6 Y6 ]: Y! M8 X/ }8 B; J                                                                               
# u' ?8 g7 G. \9 o" m$ e/ e                                                                                        嵌入式 C 语言的自我修养
: i# W" W3 O+ V4 R# M                                                       
( d) |6 u- H( Q8 C& [, d+ l" h                                                                6 D. [8 P6 f$ \4 a$ e. K
                                                                       
; z. F$ a3 K; V, `6 h/ x, _* B                                                                               
+ T& j5 s& P5 T2 E6 @( |" }  A

yh50034yjyz6402851305.jpg

yh50034yjyz6402851305.jpg
5 e( {! M4 ?/ I" U* r
                                                                                - S1 W* k1 s7 O! L9 `$ W/ w8 M1 n
                                                                                        被 char 类型的变量坑惨了!2 W* h* |  O- A( o" Z% S- P& |
                                                                ; e6 Q7 g: G: l* o3 W
                                                                       
. p! n! q3 h4 F4 f2 f6 N+ ^                                                                               
5 k' w4 _# q* @. u

wjvt2xsxnar6402851405.jpg

wjvt2xsxnar6402851405.jpg
8 _5 L) |# p+ }
                                                                               
1 M' a5 d& l7 C                                                                                        嵌入式 C 语言知识点,动态变长数组
9 a# M( n& e, R                                                                               
/ i( y% a; x- L3 Y+ |                                                                       
! t/ Y  c! i  x1 R0 R6 j# M                                                                / U' Q+ {6 f6 O4 b1 Y
                                                        我是老温,一名热爱学习的嵌入式工程师
5 h- L+ W9 N, m( x" Z6 m关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表