电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师! q1 T* w  N' ]2 c( g
关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
! u9 _: g, O1 m0 ?使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。
( h' g/ i! }6 R! n8 E8 c, Q* X

z1mhjlnzuzp64016688011.png

z1mhjlnzuzp64016688011.png

& O  S# }7 X& j1 A1 O二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。! g# P. i6 S- ]1 |" W% \2 V
三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread" n& H: n/ g& @& g( A
头文件接口:% o$ |6 {0 X7 Z5 a7 w$ Z
本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
* S. _+ c7 `. |" z2 P9 c' `! {/*
! O; M4 f8 h4 j( K" c7 q4 s    驱动注册% H! T5 i6 z8 `
*/
7 ~, W  t, C: _! V8 ]& {3 Q" yint cola_device_register(cola_device_t *dev);& h0 U6 H: h2 K- ^
/*1 N( v( O/ ^  W9 x
    驱动查找! P( g/ X# l( o3 M. c
*/
  L! p8 F6 l3 ?- f' y+ p* `cola_device_t *cola_device_find(const char *name);; q! e4 g' s. V  p1 f' c
/*
. i; Y- S4 P, _) ~$ c! [    驱动读2 Q4 @; J$ ]& G
*/% v9 s' f9 `' L/ T, I; d  k4 F
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);% t" n( U  J. w: m
/*
) T/ y0 a' B  M    驱动写  ^7 p3 R9 u) C3 g6 x
*/2 B9 F' s/ I0 i
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
& h' \/ m3 D7 f- x8 C/*" C# z9 y+ A  I3 _( F
    驱动控制
. p3 U0 ?5 [3 s9 T! i  F8 l" \3 v2 S*/
( L$ P) X9 e- ?int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:; `0 k" t. r* b7 P& N
#ifndef _COLA_DEVICE_H_
7 b. _1 k( e% O: |2 l% i5 N#define _COLA_DEVICE_H_
: H* r- u: T$ k' {1 m; ^( u7 l$ xenum LED_state. Y" x% J4 Z1 e- t6 U* \5 y
{
  Z8 V% d+ q. `! P    LED_OFF,$ |7 R9 A, T, C/ R! ]" }
    LED_ON,0 B) |, ~/ q7 D$ U2 E6 j
    LED_TOGGLE,/ f9 C. m- K& ]4 b4 n4 W
};* ?: y; h" {! j& \
typedef struct cola_device  cola_device_t;: T  X: E5 C$ Q3 ~
struct cola_device_ops4 ^  m7 `& X4 ^( s6 N+ Z0 l4 @: b
{
! k4 e' x, N: l1 Z  b4 H$ C    int(*init)(cola_device_t*dev);+ R' H9 I, y3 ~0 d. C; ^# }. _9 Y1 Q
    int(*open)(cola_device_t*dev,int oflag);
* Z, s7 ]5 T* I1 A( H    int(*close)(cola_device_t*dev);' `1 F% T, `0 B! j% C& ]6 @& M5 B
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
  z# `3 i# j7 y5 d4 w4 |  n    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
6 y. y! Q: v- l0 I    int(*control)(cola_device_t*dev,int cmd,void*args);
; g5 P# F* l' \+ n' F! a  T};2 K. Z, ]% [( m
struct cola_device7 W1 [- x7 h1 V8 s. R0 @: t/ d
{. m: c2 e9 p9 J* D) K
    const char* name;
; G( n% h! x0 q% x    struct cola_device_ops *dops;
* S' d1 J& Z6 I/ ~) v1 U    struct cola_device *next;  h0 k5 }" M% f8 q
};4 }8 s5 d) v' `6 Z) d4 o# V* y
/*
! V2 X4 Z1 _9 m5 I" B+ w& o- S    驱动注册
- z; w- u( A  g" L" r% I0 n8 F$ V, x*/' S; P9 L: I4 M& K$ g5 N. B6 J" N
int cola_device_register(cola_device_t *dev);
$ A9 B4 A& D0 a& g1 o/*
- L/ Q6 n6 i) [+ G) t5 \; n    驱动查找
' D1 P  E, R: T& g# @- F# F*// H: F* l" }% b8 C
cola_device_t *cola_device_find(const char *name);
6 s3 I* `6 z% ?8 W/*% p- I, u' x" m, p" H
    驱动读- ~# V6 X/ G! t
*/
. O1 A1 r7 l7 h/ ]6 j. Wint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);, [6 H4 V; q: [- B* ~3 H
/*  c2 i5 h6 Z4 V6 Q. ]
    驱动写
( T4 g, }& F- w6 M4 g1 _*/
$ q( m& Z) u- U  \% Gint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);- o# D( ^" b, v
/*
5 [  h- s: t& h, f* ], `: a0 b    驱动控制/ D9 q( C6 ^5 A% {; U8 `
*/
9 w4 x9 v9 ?8 Y' H7 wint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);
# H8 B9 l7 p) t! p+ ]#endif 源文件cola_device.c:# V" k' @6 ~4 B# p$ q
#include "cola_device.h"9 M; O2 h4 l  [5 \0 _
#include
/ H8 x% w0 {/ Y4 `2 h#include
% h& Q/ g: ?# y( e7 }struct cola_device *device_list = NULL;
5 l: C0 `% K" ?5 h( z$ f3 i/*1 c! m) z; u# ~
    查找任务是否存在
( U: @/ E* p$ c5 E6 ~*/
8 L% W" F% w. W$ h1 g& \static bool cola_device_is_exists( cola_device_t *dev )7 }+ \0 Y4 Z& b
{& V% R9 k9 U9 f* z$ ?/ [5 }
    cola_device_t* cur = device_list;2 a' t  \4 q1 e) @: L( d4 M% Y
    while( cur !=NULL)
, z# o) y- ?4 x: e9 V0 ?    {
+ \, s2 B1 g3 J& o) m. q: j        if(strcmp(cur->name,dev->name)==0)
" l$ Q% e4 z: G# T3 _, H        {8 u- ]' U+ F$ L2 P# N5 R8 y# v+ l, `
            return true;1 y  M+ y" M6 O% w& b! c7 f
        }, p& P) M% B+ c8 d+ R
        cur = cur->next;$ E% h9 |: D5 R. W( G" {
    }" O1 E4 i+ h# b8 w' {# m; x9 r/ k
    return false;
7 j  N' g+ [( [# J}! Z. p1 G- @1 L' d
static int device_list_inster(cola_device_t *dev)8 d9 j! p8 |" F
{1 }5 N( _! \4 P6 U! \
    cola_device_t *cur = device_list;
5 t! Z/ D/ X3 ~3 M% e( B# o    if(NULL== device_list)& u# p( P( l; c" D, w8 f/ V0 F
    {
7 T3 d: i' l/ `8 i/ h        device_list = dev;
: [8 S  Q, O$ |        dev->next   = NULL;0 q6 @/ ?. f7 z5 a* p+ Z/ x
    }
' a$ ~+ N* R& @9 X9 v% P    else
6 l5 ^) `' V1 Z1 F1 ^6 H    {+ U  w& R' z1 \! p1 [- [5 e% k
        while(NULL!= cur->next)
' k* H/ e5 c2 [! W/ S: X        {/ H7 Y2 s3 I% ?( R3 o
            cur = cur->next;
$ c. Y2 e6 C& @5 O$ C# C7 b3 R        }0 U* y& e# f* B# W6 x$ F
        cur->next = dev;/ g# W) x9 H- e& \% Y& M* L% V
        dev->next = NULL;( T6 R: w" s7 ?$ z" o( _0 s
    }
+ E- G: w! G0 [    return 1;, s: _/ u' L, C$ E) j6 M2 [5 n
}
' R9 r) z$ u; y  T8 t/*
7 I2 Z; q" I) |- v    驱动注册- m; U+ V0 _2 o) Z" p0 @3 H" r& C
*/# d. |( G! M  a3 V& A: |
int cola_device_register(cola_device_t *dev)
. {' p' H0 y- P1 v7 q/ P{5 _2 t1 ~4 R: G6 L2 j) n
    if((NULL== dev)||(cola_device_is_exists(dev)))
# k+ F5 n$ E% L. w, O    {2 y2 i' a4 {" H$ u
        return 0;# N! v  y: T, ^! A& e
    }
) r& T: U# ^6 [    if((NULL== dev->name)||(NULL== dev->dops))# h3 ~# Q" v) H
    {6 m( _6 q/ O0 _( d' O& w! C
        return 0;& ~9 X7 J- p& |5 p" O' ?
    }: i2 a( R6 M: X) L. r
    return device_list_inster(dev);
" O3 F" z! k4 ]3 w! X, o}
7 Y" \  X7 I# u/ b8 z& a/*3 O2 [& b. K- Y' n; w" G% i% B) i
    驱动查找' n* g8 v5 W8 Z- r, f
*/
7 H6 m5 W- H6 M  k% {! dcola_device_t *cola_device_find(const char *name)
  t/ t( R" j! N* T, t{# G7 i) F7 B& E  L7 W
    cola_device_t* cur = device_list;' w. ~8 l+ T4 N  `4 B$ l( r: s
    while( cur !=NULL)
  M7 i! V  m# L& t9 @* r    {
! ]! b. m7 D8 T: `  F% J        if(strcmp(cur->name,name)==0)
- ~% \/ W" t. U& L  f! [9 j; @4 ~        {
9 q7 N7 H* A+ v: B2 S5 t' W            return cur;# |* Q" ^) x/ ?6 ~% }
        }
5 O* p- Z! L, l8 A  _/ ^        cur = cur->next;
: B' d  Q* S2 x* V- {    }! c& @6 q! ^9 J7 z
    return NULL;
0 Z, O$ _8 `! M}5 \$ q7 [! m+ j6 o3 r! a7 u5 g- U! l
/*
3 r( k4 L/ q. N" e- ~+ h    驱动读
: y$ j- {  w& y  J$ {: m*/+ Y# g8 t1 _8 V! j/ Q/ Z
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
) g* ]" o# A! p" N' |# Y{+ n1 k* B) l6 y; N+ j; l
    if(dev)7 ]. a/ f& A  B, r/ Z
    {
* G: c# ]! C5 o, P5 X        if(dev->dops->read)
: |! ~" p* {/ r: p        {
! k( N& i0 R9 z1 X8 J            return dev->dops->read(dev, pos, buffer, size);3 J0 X: f/ D- H+ `# f" C" W2 L3 g
        }1 F, p* A5 d. s$ n
    }
# L- ]2 r, ~! [3 i0 V' c4 @0 l1 O    return 0;9 T3 R) r- v3 M$ p$ r5 ^- N; s
}& I8 |- m- H/ U6 I- R$ V* Y  ]
/*+ ]. A/ y- h- T7 h4 |
    驱动写
' f* T) N' U6 {# t& a5 X*/
$ h0 g& ^0 g" E: U( ^int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size): _! k3 ^3 J( W% Y, g
{) o3 r9 [6 T- {
    if(dev)
3 v2 [7 a! i0 ~. x4 _' Q% {( H& m! H0 O$ i    {
( w; i" D( b0 @- m& i; w- _        if(dev->dops->write)
! }* `& O& y  y        {
  y7 f1 a5 Z0 i0 |! |            return dev->dops->write(dev, pos, buffer, size);
+ y+ c; `  D) H        }9 p- L6 q! Y% E' k
    }' n8 O6 s( \7 q4 P: U
    return 0;! p2 u) x" Z, C& R' K' Y( ]
}
3 m/ r9 t: z3 G( n& n5 t. P+ P4 m7 Z/*
3 v- U% P! a1 O5 ]7 r' d    驱动控制
- v0 X6 z! G; n& O5 L*/8 y$ @  M: N, O7 L+ q
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)0 m2 @6 Y1 n7 `9 ?! l; M8 W
{
) l2 q0 l: z: P3 ~9 l    if(dev)  S; B6 U. M2 d
    {
0 z7 m; @0 L  g        if(dev->dops->control)& \2 s1 `) m& t% ~+ O6 u  h
        {+ Y% f% Y# M2 v
            return dev->dops->control(dev, cmd, arg);
# E. O/ {0 D2 g% b7 [        }5 {( u: i. }- \; f8 @0 @- S
    }+ f# ^8 `8 u5 l
    return 0;& O4 ~- D9 ]! x+ [3 Y' L- S5 C# W
}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。
! s; b  h4 K) }* y, k: J) I7 s#include "stm32f0xx.h"8 v+ o+ x2 v  w3 I- ]
#include "led.h": u/ ?, g7 k" U' F* k/ Y
#include "cola_device.h"
% e5 @1 V! Z4 B* U1 o) q#define PORT_GREEN_LED                 GPIOC                   ( U! @5 @/ M9 c, P* [' v$ C- X% u2 `
#define PIN_GREENLED                   GPIO_Pin_13              
% e" k$ R" U( e9 i, ~5 Q/ w3 l/* LED亮、灭、变化 */% K) ?* U  n$ J' D, i1 F7 N/ G
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)8 W  x& p! l! t, z
#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)5 z" a, `  f' X, u" W! G+ t; ~
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
! o3 ~  w- P: n- |: |! gstatic cola_device_t led_dev;% ?, _# L& n0 p$ c( T& ]
static void led_gpio_init(void)
, r+ |: O0 i  b1 u{
6 g+ P  q& P2 f* Z' A    GPIO_InitTypeDef GPIO_InitStructure;
' D, |# d/ s3 J. a" K    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
2 ^* v/ x% s+ l+ w& c3 B    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
2 V! c. p$ m3 V1 L4 h& Z9 g/ I    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
% \0 s# h. @4 A- L$ T" Q7 K    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;- ?  z3 U7 l2 Z6 L7 o
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;2 W. a# w9 [* }- \) r0 I
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
: O$ t! w8 c' [6 O, B( e    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
3 ?8 c2 ?1 u5 R0 S0 y    LED_GREEN_OFF;8 @1 T9 H, ?& j. S
}4 x5 Q0 S) r& X$ e$ H

  A6 C; [  g. \6 z# Bstatic int led_ctrl(cola_device_t *dev, int cmd, void *args)
3 d* I3 j8 T& O' A+ d{8 p! M: c: Q  b5 ~% A2 g
    if(LED_TOGGLE == cmd)
2 Y8 y: ^+ o) W$ B6 A" \9 O. T; B    {8 _: g5 _1 {$ C) G# h
        LED_GREEN_TOGGLE;# C, ^6 A; V% U2 ?  ~
    }7 m; `+ l5 b7 p# f
    else
0 C- b( w! \& r) E/ W2 r$ C! u    {
! Y. u( f- `: G    }  R# X, ]$ r( i. d, B  X
    return 1;
8 u: H$ I8 D# K* A. D1 y# X7 P& g}
) A: Q! _3 M* R( B1 X+ p$ Istatic struct cola_device_ops ops =
2 ~7 S3 ]- y4 \  m# e/ H{. l% Q1 ?- f( ?. @  V' s- s; r
.control = led_ctrl,7 V4 W0 n  x% A5 L' u& [
};
& W3 d, b* y! S+ \) I/ K% x' G# Avoid led_register(void)
5 m9 Q; S& ?# Q3 C+ k  |4 F{- d9 A/ {1 Z1 O: q- [
    led_gpio_init();
2 M5 B1 ~% ?2 g, x' H. L    led_dev.dops =&ops;' C+ q9 Q4 T, O3 q9 c3 X2 W
    led_dev.name ="led";
9 L" r+ |! Z/ _) R8 a+ A  s7 N    cola_device_register(&led_dev);% I) N8 v6 b. A- c: }3 q: v, H
}应用层app代码:5 G6 D% U" z' F7 @9 f  z8 a) Y) i
#include
, a" W  j8 b* c0 o5 n, d5 k* u9 ]#include "app.h"5 ^* G  `" j5 u
#include "config.h"
  Z3 Z" e0 ^) J+ @3 Y#include "cola_device.h", g# E* |* F  _# u+ l" j9 w
#include "cola_os.h"
3 ^% U+ {* U. \8 X& v) _1 Pstatic task_t timer_500ms;
) j& W/ G8 ~) ]9 k1 Istatic cola_device_t*app_led_dev;
1 c! s' `2 y1 }, P# ]/ e9 I1 P//led每500ms状态改变一次! N) A! k4 J" E$ V/ \
static void timer_500ms_cb(uint32_t event)
7 a9 p6 O, i. j) u{( v4 v' I8 |4 j3 F
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
- y5 v- `" {* @3 y6 D  _% `3 v( V; o  G}
, y1 J/ E) `$ p; |1 o3 Q1 e& nvoid app_init(void)
9 [& N0 v' K8 W9 U4 F{
: d9 L3 c6 {. R' z* x+ U3 k    app_led_dev = cola_device_find("led");
; `3 g* q7 j2 c8 X5 R+ f    assert(app_led_dev);. q. }% B% h8 Z+ Q5 O
    cola_timer_create(&timer_500ms,timer_500ms_cb);
+ H7 E  X# z2 i) J% ^; z- A, a    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
! O& e8 b; ]$ _9 V9 {}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。' z& {2 R3 Y" O- i
四、代码下载链接https://gitee.com/schuck/cola_os: S6 _6 w0 Q5 r0 i' G4 T" d
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722; l, l- P* Z5 F9 A
-END-
7 t. s2 G0 G, z+ j1 Q往期推荐:点击图片即可跳转阅读
) h( E! X, A/ p1 }* J                                                       
* o& q& I0 s7 ^7 V" u                                                                6 C8 S9 q# g1 J6 c3 S6 E" d
                                                                       
4 ]6 I9 [3 p( `  _                                                                               
8 y9 c) z/ m7 X7 j9 ^

tpmooidoc3b64016688111.jpg

tpmooidoc3b64016688111.jpg

+ x1 U! C2 i7 W/ {, N1 u( @% k. A; _5 ^4 h                                                                               
' j$ I1 Z* H1 }) }2 c                                                                                        嵌入式 C 语言的自我修养
. A2 U! x& O, _7 J' x( ~                                                        . D- o! W+ S2 c3 _5 K8 a7 f
                                                                2 k' |" ]* I" z: [# c
                                                                        6 m) d8 J! V0 C* k9 N! |
                                                                               
& X; m0 z+ N1 I+ O) z

hlim1ktnzbg64016688211.jpg

hlim1ktnzbg64016688211.jpg
: i6 s! e2 v% V: [9 v
                                                                               
3 l. E+ [6 K7 x- P3 W# r                                                                                        被 char 类型的变量坑惨了!  L0 q8 ^& m; B6 _1 x1 M$ B: K
                                                                1 A. r: m  z# Y5 S& V* }* y
                                                                       
0 U& g  O: @& ?; ~- x                                                                                ' u  H7 k" j7 p# }! ^! a. z4 W

3lxaqgtm2wq64016688311.jpg

3lxaqgtm2wq64016688311.jpg
# ?! G) {8 `* k7 h. X
                                                                                - Z6 Q9 \1 H4 I
                                                                                        嵌入式 C 语言知识点,动态变长数组
* D0 H3 j0 v! j- v2 F: B: G                                                                                ! d& T5 }+ K; e
                                                                        9 S  a2 s/ A/ o* i% _# q
                                                               
8 ]8 m* J9 S0 H5 a+ H! {                                                        我是老温,一名热爱学习的嵌入式工程师
$ v8 T# A6 L, X. O% R( p. h# w关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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