电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

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

echvysqqdf16408848026.png

echvysqqdf16408848026.png

( C& k6 r1 ?% _5 x. q1 n二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。
7 _9 Q# r% S# O3 \$ |3 l三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread  o: f4 E6 E& e0 p: R
头文件接口:; @) T; l: O* m: H. Y  r
本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
/ _# @% L% o- s- P, ]/*% E- m; o2 L# B3 z
    驱动注册
6 _- K; @$ _8 \9 I5 m7 E*/
% `: Y, ]$ j' L; dint cola_device_register(cola_device_t *dev);. b% j( Q$ W8 O: [
/*. c) A6 Y% F! U
    驱动查找  W6 n; \$ n( E; U8 G% @5 @
*/
, k, q) [0 t' a5 q* F9 Zcola_device_t *cola_device_find(const char *name);4 z2 G+ O' G* |& t4 C" Y" M
/*
$ F7 Y8 o% D1 C3 N# r- S( @    驱动读
9 Q7 {5 d6 \! f3 K- l*/
0 H! p* D* L- d( _7 A; dint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
/ h. o# q$ r2 s0 N5 U* T! p/*
# v& ^5 Q& f! i8 c) N    驱动写
- {; X! w( Y) h; u# j# s# x*/
# J/ A  b5 o1 J& s6 i6 r, \0 ]int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);; l0 ]- V2 e/ X# r; r
/*
: x( p$ R" A% k3 m9 e+ x    驱动控制. D( [, L8 `% V" G9 h
*/! f8 m4 H) k* b2 h) T, T- n% D
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:4 @$ @- _7 _: F
#ifndef _COLA_DEVICE_H_: I& d  [$ g) g7 B! v: Q, Y
#define _COLA_DEVICE_H_; A! E7 U! i/ I7 [1 M9 Y
enum LED_state9 [5 l4 ^4 `# J$ D  j: k
{* M" F9 _: s# U/ }3 r
    LED_OFF,7 r- i2 ?+ i: V' T( y- W2 V
    LED_ON,2 f" b6 L  J8 z, z
    LED_TOGGLE,
& I0 m9 E3 t$ P+ j};+ p4 H1 G  h. U* W' w4 s
typedef struct cola_device  cola_device_t;
% O; L+ i$ j: W6 lstruct cola_device_ops9 N/ S! }2 q5 s* Q8 ~% ~7 Y
{. F) g) \& R. ?. U: y9 t* Y
    int(*init)(cola_device_t*dev);
8 i4 z% m3 e' |' g    int(*open)(cola_device_t*dev,int oflag);, k, w' K6 m+ B) A0 [) X5 B7 S) J5 Y
    int(*close)(cola_device_t*dev);# L- j8 j* O3 M* h( S, X
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
) e7 D0 z: u- k: {* k    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);% x2 ]% F2 l* ~0 ^, d
    int(*control)(cola_device_t*dev,int cmd,void*args);6 O  o; M; x% {* f3 f
};
2 C' z" m  g# W- r" `- Q3 Jstruct cola_device
' H+ a! H* K0 ?6 n0 f% R# Y) U{
- @. y4 z! x" k  N    const char* name;
6 q4 T7 c0 U# G$ [/ y- o2 @    struct cola_device_ops *dops;: h  D" P7 E0 W4 f* U% }
    struct cola_device *next;; _# i2 |5 V% \! {
};
$ V$ }  r% w. T! Q. i/*6 H" p6 ~2 D% [2 ]; F6 X' t
    驱动注册
# {+ O  T; c# F8 t% i' h; I; w*/( b6 i# V% s; L
int cola_device_register(cola_device_t *dev);7 J5 R' f5 l$ y
/*
' L* R/ I  x# n9 K3 E0 @    驱动查找
3 r1 p2 p* m" B/ @$ g6 G# R*/# t. H" _: d$ e
cola_device_t *cola_device_find(const char *name);* @4 \2 b4 u: Y/ l# V
/*7 d8 @# j6 k2 }# U& w  k, t& N
    驱动读
4 E2 w) [6 M+ e% a) e$ f5 x*/
1 W2 D: {7 @8 s  tint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);( t3 m0 J) E# F% ?9 q" d
/*
' y. k+ W" ?* J% i8 X) K    驱动写
& @5 H4 w7 ~# P& k*/
" z- s2 |/ d  W8 Y5 cint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);0 Y# `7 k- q+ h' ]! Y% j
/*
( X  r$ t: \) B/ H, P    驱动控制
( w; i3 V' U5 {5 ]5 P( q/ [0 O- U; l3 x*/
: g7 \( t# m* ]0 {0 F& F$ ?" Uint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
* a* W3 H1 }; P0 V4 x1 s#endif 源文件cola_device.c:- h6 V" ?3 b/ x) K- K; u5 G2 M
#include "cola_device.h"
. D5 f/ G" o3 a8 X: Z/ O( E4 @#include
6 v. [/ {! W  G6 e  L* d#include
& \% C' _- q2 Ostruct cola_device *device_list = NULL;
3 ^" |3 e1 t+ ?: i, z/*& U" h+ `$ `# v! z$ g. h
    查找任务是否存在
$ k6 `- @0 B( g6 r$ G1 n*/2 r+ v, l2 @' r% F
static bool cola_device_is_exists( cola_device_t *dev )
3 s/ S: ?/ N' u0 T3 Q7 W9 @* C{! {6 X, t3 X3 q1 e% S) S6 b/ T
    cola_device_t* cur = device_list;$ s$ E, k* F  b* o6 n- F
    while( cur !=NULL)
6 T, B  F, n' ]5 A: \$ Y    {
, b. B" P! v+ T7 J, N+ F. z7 s        if(strcmp(cur->name,dev->name)==0)3 d& U9 v! y6 z2 b8 d0 S
        {7 Z( t9 f4 F# g; j8 r+ J
            return true;
- o( B! i) ]  p3 h9 K% r        }$ ~9 S$ b! w& r
        cur = cur->next;
( Y8 x" o( S8 C; e* m! H$ }    }7 n+ T4 ~+ u) ?  a2 w
    return false;5 @, q2 r1 j2 B
}) f0 M2 H: E; s8 z4 Z
static int device_list_inster(cola_device_t *dev)! w/ m; O& Q% m% m2 B- t
{
& X% c" J9 J2 [2 [* m, u    cola_device_t *cur = device_list;9 N( D( O7 [6 I5 Y- A+ m
    if(NULL== device_list)
, i  ~+ O  C+ A) k" l8 S    {
) W/ z  q1 S7 R" v# v        device_list = dev;3 ]# N! s+ [1 g, i* e: E
        dev->next   = NULL;3 }6 M& z3 D+ e0 _  ]. V$ _
    }! X- Y( c8 m, k% w
    else/ V% @  [, p- E! i4 y: M' S
    {
: C9 |2 w& i3 y7 V        while(NULL!= cur->next)
  q* E/ ~3 @5 |. O3 o7 m, m# _        {" f) g* y5 Z! [# D6 C* a
            cur = cur->next;" v* Y9 b6 n) l( Z: _
        }* ^$ V  K3 E2 p, m" `! d" ^
        cur->next = dev;
! ?! z8 \1 y# y( Y0 b        dev->next = NULL;
/ o/ c3 t% W- m! m    }' ^" o- J% o3 V; p: Q! F
    return 1;# e6 j+ _9 J1 A' r/ W4 B8 l2 t
}
* r* |5 B# u* s/ M0 N; Y0 m- T& f* P+ z/*4 i9 }( V' O  P1 Z" z3 q5 O
    驱动注册" X& S+ u$ S9 _0 m
*/
# {7 R) J% D2 h$ L, v9 h7 h+ |int cola_device_register(cola_device_t *dev)
, Z: ]8 U7 S! g9 O{
: F% D: K6 V. h, W  O1 z1 `+ a0 A    if((NULL== dev)||(cola_device_is_exists(dev)))( `# d) m8 n$ N, }2 X
    {
  }* {0 d: O$ k2 \        return 0;$ g4 N! Q: o1 K" \
    }8 [# G  z2 C* S. W! |) n+ t
    if((NULL== dev->name)||(NULL== dev->dops))- K5 a0 O* [5 D
    {/ B# G; b. q, M& a( K* l
        return 0;
' Y; m9 }3 U. G! t    }4 [5 Y# M& f1 Y9 W% p- |. ]
    return device_list_inster(dev);( @3 h4 q" f" p6 X
}  i7 H6 X% }- ?7 j  {1 ]
/*( L! j/ i" z+ p: z% `, @
    驱动查找
% [$ G0 L' a; x7 u+ d' b7 k*/) x6 X2 u0 J! S4 B. Z! D$ Q. H
cola_device_t *cola_device_find(const char *name)
9 I! S0 n% n6 B) x+ p8 q{
' ^5 g* f4 ~" T9 _) c    cola_device_t* cur = device_list;
0 }$ ]; _, e( j3 S    while( cur !=NULL)
" Z$ U( x2 g7 V& A    {
2 R2 U5 m3 V; I7 m        if(strcmp(cur->name,name)==0)
3 h. s" r; E1 N6 a1 }: d0 M% L6 \        {
: m$ z5 }  L) ^, n4 ?            return cur;) R' `. e: z( o+ y, J$ y( r4 y
        }
% q2 G; K( t. ?        cur = cur->next;8 E3 n$ {% x- ~$ h3 L
    }
" i$ D6 j* `' o% ?& [8 E    return NULL;
! {$ S3 [  \3 @$ ~}
3 d) p8 [0 f! n5 p" F( h/*
' v+ p% r. O( J' r- k" y    驱动读7 |. ]4 }9 d5 k
*/
$ Y) O5 C: s3 Wint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
' _; H/ \0 r' e/ C' f{* E/ |: @0 G/ S- z( X4 ^# i3 I, X' {
    if(dev)
8 A/ X7 n6 D2 k/ b  l' D+ w    {7 Y2 E7 g4 Z( ?4 G
        if(dev->dops->read)
2 T  G# q% F. T( ]: w        {
) Z& z4 R1 a0 I& Y7 ]* @            return dev->dops->read(dev, pos, buffer, size);
8 e1 h8 D% p' f( {4 y3 \/ y0 M7 H        }
; y% G( w) e8 Z% Q# K- r! S    }
! T6 u. P8 e( P3 X$ l, Q    return 0;! m! g* b" S/ L* D
}
' |) _1 J8 x  ]* \; z/*% s0 W; ]% r3 J5 y; g
    驱动写
- c  }* o+ L5 `: I( B+ l0 j*/
- C% S3 {! C- s( [- Y8 dint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
, w) q' K. n# N6 N' @! Z{. o. ]2 ~$ c) [
    if(dev)
- j- {) j8 m0 @# g    {
( G) @1 H% U8 C        if(dev->dops->write)
, k) _/ ?  y7 [2 ]. X7 X0 X        {. d% s8 Q+ ~1 V
            return dev->dops->write(dev, pos, buffer, size);
" W$ w6 C1 ?/ T5 g+ D6 N/ ^        }( V7 E% J% i# t8 a  ^
    }. m- G/ v5 \6 `& ?" j# I* ]
    return 0;
9 e% w8 t' [: f}- O( X" @1 }. @8 g1 V8 K
/*
. ^$ q$ F5 m$ h5 ^    驱动控制
8 F& S- p+ [8 i6 r$ V1 _$ B*/
# i# Y. A+ M7 J$ V6 H1 L! Qint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
0 K8 r$ D4 v. B9 N( M; r{5 ?( L* Z1 A3 ?8 \
    if(dev)
2 C1 E# i$ f  u! ^    {( J) |2 a2 N8 h: [& X  ]
        if(dev->dops->control)
0 f2 n" p. l8 Q, _. Y+ W        {
/ q& H; P0 n6 Y            return dev->dops->control(dev, cmd, arg);( u' j  {$ w: F( |* e. N2 t; N+ [
        }; M! E6 z- Q" ?! O, E
    }! W2 }6 V% v2 O& p, x4 b# @1 ~. y
    return 0;2 U5 a6 h4 ?) k( q0 Q& E
}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。* Y4 s8 I2 Y' P7 r
#include "stm32f0xx.h"
  l" E' x$ Z+ Z! t5 S! z8 M#include "led.h"; Q( r: T0 s4 S6 k/ ]& g
#include "cola_device.h"' O3 o( f. [1 o2 L- ^
#define PORT_GREEN_LED                 GPIOC                  
  H/ d( ^  h: ^0 P0 g# {#define PIN_GREENLED                   GPIO_Pin_13              
& [, y, z! l' C8 Y+ `& {/* LED亮、灭、变化 */
: f5 S! Q0 D! d" m$ B" }& g, m0 Q8 q#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)7 a  Q3 S. F0 F  D( O
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
  h/ e# D9 a! y& P! J#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED): `$ ^4 c* v+ @: U) n/ Z
static cola_device_t led_dev;
0 ^1 h0 Y: |. l; j0 F6 B% ostatic void led_gpio_init(void)
, u! A& C$ ~4 Q9 n3 f8 }* E{5 z1 [/ h1 e7 ~; H' R6 k$ Y: J
    GPIO_InitTypeDef GPIO_InitStructure;
# l. @9 g3 _5 H) T5 a  v9 v0 S    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);0 h$ }- F8 I- ^! W5 h( H3 ~; H
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;! Y/ v% J  ^5 B. y( r
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
$ g7 |$ _/ {# g  a2 s+ {% p+ A    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;! X# T: f! ~  f7 o
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;! I/ p9 c5 R; z
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
$ @- t3 U9 L5 M6 s: _    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);: f3 ^  G/ U, S" t: l
    LED_GREEN_OFF;$ d  P) d' }8 J: {6 M/ l1 P8 Z/ b
}. c3 ]& W: j$ _; u% x+ X( k

# U2 D$ W8 e5 [5 P8 t( l  ]static int led_ctrl(cola_device_t *dev, int cmd, void *args)
8 ~$ ]4 e$ x" ?2 x{: ]3 W! b" _3 K* B  F4 w7 z" w  H
    if(LED_TOGGLE == cmd)
- }1 Y7 P- ?7 R2 H3 `; I# h* P    {4 s1 Z0 ^. ]4 l/ i
        LED_GREEN_TOGGLE;( u5 H( |9 i% _8 ^$ c& M
    }  A% t$ c& }8 y) h
    else
: N# m! c2 z' O/ {5 e$ o7 v    {
4 H. ]7 y( B+ R$ t# Q7 j    }/ X! H5 `3 Q0 O7 f0 t9 C
    return 1;
" c( _5 _; Y( m3 `, a: [! p( \}$ F# z& N0 \0 k$ P% j
static struct cola_device_ops ops =
5 W! r' q" L. i$ K1 M/ L1 ^* V! _{
0 p- U! c0 K/ d0 e" W2 F .control = led_ctrl,
4 E" J3 k8 a3 B/ i0 D/ H};
. N' T  r0 h: Z* A/ J: Tvoid led_register(void)' l6 d3 V3 \7 j* v+ c7 Z, Z
{. C* S7 x& H, [& c
    led_gpio_init();0 E; p6 h# I! `# k5 h$ ?. O6 ^
    led_dev.dops =&ops;
" @$ e3 H) @; u0 G    led_dev.name ="led";: z: e+ g  b% \' V1 ]
    cola_device_register(&led_dev);, a  f$ ]( @7 A5 T5 [0 k* V
}应用层app代码:
$ b' z# {! L0 E" O$ H#include
/ ~7 H# Q; j5 @, L#include "app.h"
- G, C# M0 }+ |9 T! r' W- b#include "config.h"3 j2 y" I2 u6 W8 [" B) D6 f. o! X0 G
#include "cola_device.h"
9 m$ v9 [  c; f* i, p1 {8 H#include "cola_os.h"0 L0 ]# x- o% w: l4 x; w/ X( r
static task_t timer_500ms;
, B9 [) F  z7 m  M( Ostatic cola_device_t*app_led_dev;
8 K% K- b7 t5 U9 _* x9 D; u//led每500ms状态改变一次
; H7 J- V$ L( R) J: sstatic void timer_500ms_cb(uint32_t event)2 r6 I6 T5 u$ F; i/ W3 l) o1 E
{1 n+ q3 v* D, b' V; W
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);) K! y' ]' ?" v
}
+ s( s2 L& k4 v, D9 d6 Cvoid app_init(void): f# b! u; f+ F' d1 ^
{
, C! [* V+ @6 W; r! K" u    app_led_dev = cola_device_find("led");1 X; n& V/ O8 `" u# t# G2 X
    assert(app_led_dev);8 q# H1 K. i; i' c
    cola_timer_create(&timer_500ms,timer_500ms_cb);
: s1 |4 _3 ]) {    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);& T  }0 a# h5 ?3 l% M  T( _, Y
}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。5 |' n1 H! M5 b; [8 i
四、代码下载链接https://gitee.com/schuck/cola_os8 \' S% ?. H; n  a  s8 \; n$ F
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722- D! g2 c# w1 Z# G% f& z. O1 A
-END-
  l3 x- D* v  x  c# m, K+ w往期推荐:点击图片即可跳转阅读5 @- n/ e9 D+ \: Z8 [. b
                                                       
/ ]) T* x$ y5 o; a9 e                                                                % M& T! ?9 a5 o* Q! q$ F
                                                                        1 H: j& J# a2 r9 |: b
                                                                               
$ B" R) w/ m2 A# }0 R5 q

gayih2vnbik6408848126.jpg

gayih2vnbik6408848126.jpg

+ t' V0 ~2 v! H3 N$ ^1 R                                                                                0 q) g& I; c$ m+ _2 D$ v( J
                                                                                        嵌入式 C 语言的自我修养
+ M5 Q3 n$ E- P6 K3 S% F6 e* r                                                        & X. S! f3 k+ s# z) @' T' H
                                                               
; Y5 e: o6 E# k' Q                                                                       
. ^8 {' V/ [1 Q$ Q1 F7 u) l  ~                                                                                ' H$ h( H. L7 M! p& b4 _/ v! v+ x

fybj3a4kykh6408848226.jpg

fybj3a4kykh6408848226.jpg
/ E2 J1 d, @( h/ J: T
                                                                                . K% H9 s# m* [# a
                                                                                        被 char 类型的变量坑惨了!6 ?5 y. _$ ]" C" R$ Y) E7 S' N4 Y; h% U
                                                               
+ q, A0 \! V7 I                                                                        ; E' N) r) j1 J6 T
                                                                               
) d5 o& ?2 f& a$ y$ A& h

b2kxjl1lw056408848326.jpg

b2kxjl1lw056408848326.jpg

! n! E4 L0 E, N- m. K. a2 G                                                                               
1 d% _3 D# g" b                                                                                        嵌入式 C 语言知识点,动态变长数组- c5 M: K& L$ Z, m
                                                                                / b& Z6 p" p9 ?
                                                                       
) Z. x& s8 m% \                                                                . E' `1 x6 ^' l/ H
                                                        我是老温,一名热爱学习的嵌入式工程师
, [" `# S! |. R& L3 G! e% ~+ ]' J关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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