电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师
- D& f' A( \6 d/ Y& u3 r  M# m关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
$ w( _' r# F7 @使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。
" C$ R$ _! Z; L6 m

fqgxqwhruxl6405408207.png

fqgxqwhruxl6405408207.png

& l) n' n% w( B0 F二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。
0 N) ?4 J( Q2 T# Y2 _) y三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread
( ^" t' S2 k3 |/ o7 S/ J. z- F4 g8 z, H头文件接口:
  S+ Y' y# O% h8 [本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
5 [% A* K) ^8 R7 F/*
1 ~% Z" ~' _7 X' \2 W    驱动注册" Z  J8 [7 U( r
*/9 ?2 f  Q' f9 {9 c4 ]+ p2 f! u) L3 d/ u
int cola_device_register(cola_device_t *dev);: L4 j& G3 i/ I
/*: j2 T- ^+ e  z
    驱动查找
) M, P( H: ]7 z. ~*/# e* n! Y2 G3 n3 D$ [2 A
cola_device_t *cola_device_find(const char *name);
+ e6 k/ ^, H$ {; R! @0 s/*
3 ]: ]. {0 Z" R    驱动读
: a' f9 K. S# l: O) ]9 Y*/" M' T# A9 Y! r. o: }
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);1 b$ c4 h3 V% U. [. j! d% [; }$ ~
/*
- r  Y$ j3 l" `5 d4 i& F2 t    驱动写1 \+ h* j$ \; v' S6 j% X1 c* @  c
*/7 M) p' l9 A: n# ?: a' _  l$ D8 P
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
0 T3 S% b# p! L" D$ ]7 K/*
. q& k; p' c1 b/ g! k! H    驱动控制- b; h0 e& y$ f8 G* r) e
*/9 a& n8 f3 p8 }
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:* t; _1 @1 M0 y' a
#ifndef _COLA_DEVICE_H_  R! L8 s" y" `8 h" m
#define _COLA_DEVICE_H_
2 R) r, j$ a/ S8 ~0 F1 k( menum LED_state
1 M* a; Q$ \8 e  j& S2 y{
/ k& a1 J0 h/ A2 x- N. p  K    LED_OFF,, i. w# m7 q  r1 x5 ~, `
    LED_ON,) K- \6 F- C5 U7 \- m
    LED_TOGGLE,8 c" E+ r7 z  Q
};; ~- o/ h( \" f9 u" M
typedef struct cola_device  cola_device_t;" m* R: F/ r4 o; x/ ~- b
struct cola_device_ops
( ~/ J" r& z6 `4 e/ G6 Q- d{. D1 `2 R" w6 v! z) ?% W5 |2 L
    int(*init)(cola_device_t*dev);- t" k+ h7 w6 i2 h- K$ s9 b
    int(*open)(cola_device_t*dev,int oflag);
3 x. ?# x! c# F/ {) }9 a' W- w    int(*close)(cola_device_t*dev);! n3 ?: X9 t' u9 d: t& t- n; r. r
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);. |' e7 w, v- s' I  d
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
5 C/ k) E: W& s* q+ }; j    int(*control)(cola_device_t*dev,int cmd,void*args);9 }* {" I; G' h5 R: b4 x( e5 B
};9 m( r6 g. N9 K# t& L+ `2 V0 O
struct cola_device+ f2 f% t5 m5 t: ~
{. f1 O0 U( f" l4 a* A, Y/ V, U/ s
    const char* name;
4 e# i  Y1 \3 W% X1 [# `    struct cola_device_ops *dops;
# _, ?( u) V  {; h4 d    struct cola_device *next;
+ n$ R  r* ]4 @: S, d4 i- W};
0 w9 e  u* _. ^  U$ _/*- l  r2 W- c' {( x; H2 ~9 e
    驱动注册9 A! i. H  P. d9 p1 B; A6 ?- O$ ~
*/' \9 M# o7 @& E: _
int cola_device_register(cola_device_t *dev);
% |  s( g4 o4 W; E/ g- Z9 z" M$ C/*
' ^) Q' n5 Q" u- u6 C5 o, x    驱动查找5 Z& @3 f  v& A, L# O; P. z
*/" e" e8 _0 y5 T1 a4 l2 ^
cola_device_t *cola_device_find(const char *name);
9 y" w& h$ o6 Y, L/*
: s8 H2 R* U4 |# q+ L- N2 \. D- c    驱动读! Q% V2 ~' n$ H. `. p
*/
* O; b! i) m8 O  b# f" g* o% Yint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
8 n! v% p3 n$ X6 y5 I7 E/*
- w8 W* C0 h; g' m8 j8 b, Y    驱动写
2 ?8 p8 _8 r9 X; T  {2 e! s5 X, D2 A*/- U/ q  _0 I: O
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);  X2 w4 ]) v7 l
/*
/ K/ ^# ]; o6 r0 e( Y5 [6 ^    驱动控制& e# i: u0 x) o  I5 \
*/
3 O& m( t( }' j- R9 Mint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);6 f  C$ F3 U3 e
#endif 源文件cola_device.c:& i. Z( H# v8 X
#include "cola_device.h"  L( \" o1 [: r4 w
#include
" u  {4 L9 k8 L" Y6 {: j#include
! l# H3 [# `. z. estruct cola_device *device_list = NULL;
3 S6 Q4 f9 v( q6 {4 m/ h9 I2 M/*
0 h2 q# E( t4 u: ~$ }$ ?  }: Z) l    查找任务是否存在
( _9 [* K2 @1 B8 z) g8 |2 o' @*/& ?& |6 `3 c! t, \) R: U
static bool cola_device_is_exists( cola_device_t *dev )
; S' A: Z3 s- @# @{: D; k. n+ W- @
    cola_device_t* cur = device_list;
! s& c4 |. m0 q7 A    while( cur !=NULL)- {5 t: a% y; j6 S' K
    {
' {7 ]3 G3 z0 _        if(strcmp(cur->name,dev->name)==0)
6 H- o' [4 I0 H8 G) x  d0 n7 b( E1 f        {
; P( R6 ?7 _  s5 U9 n- @' M4 q            return true;
" N5 z, A; y2 L) U0 O+ k        }/ R5 w" a( G8 E1 [( t: v0 m0 x
        cur = cur->next;
* g  M0 I. R1 I6 z+ D- D: J    }
* ^; f' j7 e, x5 @  d    return false;+ ]  B7 L8 t$ x* d4 n" I
}
: O  {9 Z0 B" g- ]" astatic int device_list_inster(cola_device_t *dev)
# L' \' E) v8 p8 w& N7 S' Z3 I. t{: d0 f8 U4 V8 \6 g" J
    cola_device_t *cur = device_list;9 y( C  x7 E! S- d- g( J+ P; S: S: c
    if(NULL== device_list)' O: `) B/ s2 ]
    {& W1 |4 y" m, W4 Z1 |  w. ^  C
        device_list = dev;& N+ Y' C& i' B8 O
        dev->next   = NULL;
8 q+ x* s0 G. R7 q& O    }
$ s+ O6 K1 ]7 D: \) g    else: p  p: A# {6 L: g
    {
# q% A  T6 \; D5 {( R        while(NULL!= cur->next)
; j9 K: M' U! A$ g, a5 W        {4 D' O0 ^7 |% ^1 ~+ |% _* p
            cur = cur->next;
" K& b* b; [7 `/ V! k" h: Q3 h        }5 Q# a) P" X. T, W* g' L  b) A
        cur->next = dev;4 w) b' S* u# o! ?
        dev->next = NULL;
0 D: \% S( ^8 D' _3 o1 L" K    }+ e+ |' i" K4 Y7 P
    return 1;
% C" U" G4 d" t5 @}: ]+ o1 q9 }2 Q/ y
/*
- T8 o: h" T- q) P: I! `    驱动注册: }9 S" l; s/ V+ m8 o
*/8 a( m& D$ I; i% E: w! l8 @
int cola_device_register(cola_device_t *dev)2 d6 V. H' ?4 Q1 d6 z9 Q
{% J5 }6 a! J6 y; C5 S- J
    if((NULL== dev)||(cola_device_is_exists(dev)))
& Y3 Y9 i, w8 x" D$ ~    {
2 C  ^" y) Z3 L7 F/ f6 E8 o5 l7 P        return 0;- O3 i$ O0 s; ?' L
    }$ A( I+ t7 l" E" F! ]4 `
    if((NULL== dev->name)||(NULL== dev->dops))
$ D8 _6 Z% w! s  h1 ?    {+ H; l0 F- d, ~4 t( a) `4 @
        return 0;
; @) K) Y- y! u2 o6 Z    }
/ J) ?8 d) R# H8 p    return device_list_inster(dev);
7 k+ i- p' a; ?+ N6 f; M& u1 p}
% H+ K' v) A% C' q/*
+ H  O' J- X0 ~/ ?4 N  }    驱动查找
4 d3 `) E6 w$ c*/
5 ^, n9 x2 I1 C8 c( S$ D, F8 ocola_device_t *cola_device_find(const char *name)
. l' E9 e8 q/ e{
6 l0 ?4 G0 ^; v* G/ ~/ V    cola_device_t* cur = device_list;2 H. t: P5 r0 _; \$ Z
    while( cur !=NULL)
% S9 z  K; w9 C9 m    {8 E& o, W. o- ]8 \/ U" U) W
        if(strcmp(cur->name,name)==0)5 ], Y8 g- \' s& f. p8 m6 r+ w
        {
0 O# T) f7 C0 |& o* X            return cur;
8 a$ p2 U/ S- X' }0 G! h3 ~. o        }
( L- R7 }8 }, t, n        cur = cur->next;
$ j* t- D2 \" e* n9 v    }
+ m' ^# x9 ^2 A# O) p) L, T0 \    return NULL;
0 o( f# x9 ]6 ~4 B) i}8 I$ X& C7 w1 }
/*1 s3 X2 S9 V' w( \7 ^
    驱动读, q4 T6 T. }( ]2 h" f
*/! `% Y& ?* B% O* V3 X7 l
int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
9 B9 m/ k3 L3 A! c. o( \7 V{0 S4 U! v- G) B( I, g
    if(dev)
% u2 M5 O0 f2 Y# M5 l. _    {
: p3 K' p0 H7 w        if(dev->dops->read)
( j4 j" ]& i8 s        {. p3 R* g$ v; [7 e$ Z! D3 o
            return dev->dops->read(dev, pos, buffer, size);
6 I& o8 D: @: b( k+ {% l        }* k4 B+ c3 n8 K* h* X* @7 g
    }
9 q# A  N7 V6 o8 s- J' X    return 0;; K9 U: S4 v9 T5 D/ u* {
}
& P/ [6 Y0 a: x1 _' U/*
9 H  F* y6 T. z: V$ \5 }8 `0 O5 c5 h    驱动写
% H' T% p4 L; y# a$ L*/
, p7 o' {) C4 c2 f% P* Q3 r+ Pint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size), \! q2 T. V8 x& A" P0 g
{
) g/ a* v, ~9 m. J8 o9 P    if(dev)7 }" t) P- H; y) c
    {) F8 G1 Z9 I6 i, ~: C6 B- s
        if(dev->dops->write)
2 O8 }4 P$ ^# ~. l% o% k        {
& ^+ X6 X5 T) V  C3 e5 ^            return dev->dops->write(dev, pos, buffer, size);6 N" t" D2 x9 {
        }8 o! ^# F) \8 k  G/ T1 F5 j
    }
1 _9 Y5 _3 J8 J; o" Q: u    return 0;
" h8 L( v# |' f}0 D5 `& n$ v/ f# ~6 Z( X
/*/ e. Z  E$ ?, l7 i. n
    驱动控制4 `. B( [/ i$ n6 e" Z9 J" D
*/2 U$ ^0 b5 c: m: \% }# |
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
9 R# h( ?4 G& G/ i) R{
2 j7 Q* ^. g, C1 B4 S, C; p. {- i    if(dev)+ R/ m. V. l. c' `6 X) e7 l
    {
& y, |- M2 L: g9 E! q8 I" r8 {        if(dev->dops->control)
3 J$ p* h6 E' q( V! }        {
; y, y: ^* s) Y: Y            return dev->dops->control(dev, cmd, arg);
/ Q( V2 C! L3 u        }: _0 M4 n. Z. a/ o
    }2 ^# m; S9 w, b7 j& L
    return 0;( O1 b% d! z/ i  D% B6 a8 i
}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。$ a/ Y: r2 r: M- t; M
#include "stm32f0xx.h"
8 _9 Y7 r  q& E3 v: t: Z* `/ R#include "led.h"
% k- r) R( A' e7 c#include "cola_device.h"
& W# e9 b' t4 k4 P6 ~$ P#define PORT_GREEN_LED                 GPIOC                  
* t) R! T. V( v* @#define PIN_GREENLED                   GPIO_Pin_13              
5 s0 |7 ]( v4 ~# A3 g2 R/* LED亮、灭、变化 */3 G9 n9 C, x4 H9 x6 I
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
" {' s% t& H/ J#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)% g  u2 P% H8 b' o  v' y4 |
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
2 K" d5 ?* Y7 s7 U2 rstatic cola_device_t led_dev;1 t* F4 z% O1 y. l
static void led_gpio_init(void)- G* R: K$ @5 c& E! u
{4 T, f( A2 p; g4 G" f7 O6 `# z
    GPIO_InitTypeDef GPIO_InitStructure;7 j) b  N: Q4 V/ Z$ [6 n
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);5 t' t2 X+ f2 w0 }. l' v7 n! c
    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
4 O7 E0 l" ?; e) N  r  P4 m    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ h+ b  X! e: D. M( l4 W! g1 R    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
! c" k, X- |% q0 i* y+ A( F# h% E    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;9 X7 K6 w! h0 L' F
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
' V  Y; z2 f+ w* }8 t/ k0 ~    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);% k/ j! B" e1 q8 W4 x
    LED_GREEN_OFF;
( @5 j5 c9 R! K) b3 J}
9 N+ m- J9 c# g+ n; V3 s: M3 C
! x6 O0 G2 X- z% f; Tstatic int led_ctrl(cola_device_t *dev, int cmd, void *args)2 r" k% H# \& T7 }( z1 I. E8 X- o
{4 O; ~* u4 V: V% U" ]0 D
    if(LED_TOGGLE == cmd)
. z- y9 r: H" d) u! D    {3 H7 Q/ z, [' \" Q& [
        LED_GREEN_TOGGLE;
: W7 \: w& g! K- ^6 K    }+ @8 `7 ?2 \' S( y3 s  f
    else/ W& d/ G9 Q9 f8 V1 x- v& D
    {5 Y- M% M8 l  S+ B1 w
    }3 @8 ~+ L2 s5 l
    return 1;! r7 O' m/ u7 Z
}
. B6 U8 s2 W; Z1 G5 xstatic struct cola_device_ops ops =
* f/ ~; M$ Q' y{
6 P* f% Z4 h' j0 ^$ s4 a3 \. f .control = led_ctrl,3 a2 ?# Q- X0 H- r" G
};
* ~+ `5 g. ^, m$ h$ M3 E& |% svoid led_register(void)+ @, `- S4 O+ e6 W/ a
{' e$ ]& {* w2 e$ U/ J6 H" D
    led_gpio_init();
6 r! G5 Y3 e% `1 y: {) Z; a    led_dev.dops =&ops;+ q" N* ~- S* ^( V2 i# f" Y
    led_dev.name ="led";
. y% h% B# I' U8 [( i    cola_device_register(&led_dev);
- z& ^6 @! p6 d1 z}应用层app代码:
# R0 F+ n, e; F0 w2 V#include
. K+ S  O6 m* d' Q+ I! j0 M#include "app.h"
1 f6 A- i. w& ^; u# w; K#include "config.h"( n, k3 k8 G( _: ?
#include "cola_device.h"
" Z1 L; W/ `( _: V7 a#include "cola_os.h"' Y. P. c* X: [/ `4 ?) S
static task_t timer_500ms;
- [; e" o/ H* `* N& sstatic cola_device_t*app_led_dev;9 g  E" y( B9 T# `# M
//led每500ms状态改变一次$ u8 @: r" `# o8 P
static void timer_500ms_cb(uint32_t event)
4 d# G* o1 ]: C{
, D5 J/ |: H* D# |  h. b* N1 k7 \    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);( y8 }7 c. a" |, \1 G# \- r( \* g* t
}3 _. G2 e8 T! r  V* v; w$ f5 }, @0 Y6 b: [
void app_init(void); n) F  N$ v' i0 J! P, ?, F
{
# x( R8 ^5 F: Q0 {& j  d    app_led_dev = cola_device_find("led");
2 w+ F6 {( ?2 P8 }& u    assert(app_led_dev);- J0 C/ T9 u1 c4 J& a6 p  Q9 _
    cola_timer_create(&timer_500ms,timer_500ms_cb);
$ J) h8 W" l# v: @    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);) v# s* p8 t, a2 a% U& L
}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。
6 Y2 G# C; R8 o& {四、代码下载链接https://gitee.com/schuck/cola_os
8 o7 ~3 W$ E$ O/ m/ K
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722
# }- g- H. r6 P0 Z-END-
3 Z/ z) f7 b1 ^* G往期推荐:点击图片即可跳转阅读
% y4 P# Z  c! m$ F                                                        ( I5 Y: D; E; H6 m
                                                                7 ~) H/ g, w* u0 |$ U
                                                                        " _1 v9 r( D! K6 A2 i. Z
                                                                                0 k5 P6 p/ M7 N% A/ T2 z

z5ikmk4xvwb6405408307.jpg

z5ikmk4xvwb6405408307.jpg
" l  v8 {) A/ O9 P5 u
                                                                                2 s$ w: y& R+ x* c0 e3 j$ V
                                                                                        嵌入式 C 语言的自我修养
  [4 u) a( n8 L5 u  @7 E9 A                                                        # o5 C8 W: U' K9 O  t1 {: r
                                                               
' U3 c" X; u( f( }8 X7 U3 U                                                                       
. l+ [2 ^2 o9 {  `7 A4 O, w                                                                                & _( r. U2 p! D- V

tydsioisxlh6405408407.jpg

tydsioisxlh6405408407.jpg

/ ]& {7 V' t; e# s                                                                               
; M5 _. y+ G$ s" K! p9 C                                                                                        被 char 类型的变量坑惨了!: S4 [1 L( `9 Z
                                                                0 T. G( N3 k* j
                                                                       
8 o% O% j$ Y; p3 i! D                                                                               
9 J& U3 P' A2 z8 n1 |& w3 ~* \

kgln3r4ra3w6405408507.jpg

kgln3r4ra3w6405408507.jpg

6 I7 c, |; T) q1 I                                                                               
2 ?1 D$ ]4 I# v* k4 ]/ _# v3 w* X                                                                                        嵌入式 C 语言知识点,动态变长数组9 _8 O4 U: {: w7 z- d8 R7 j' g9 F
                                                                               
8 T0 J1 A* C; m. q) l; ?                                                                       
; W4 g5 F' K" |& R# l4 |                                                               
$ T6 X! j8 ?2 P' O: h                                                        我是老温,一名热爱学习的嵌入式工程师
: B* }8 O: Y2 v$ l; ]. G& ?" a6 G关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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