电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

572

主题

572

帖子

4361

积分

四级会员

Rank: 4

积分
4361
发表于 2024-8-12 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师4 n' o7 \0 `6 v; k  \4 T5 k: z5 F
关注我,一起变得更加优秀!一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会有stm32f10x.h或者stm32f10x_gpio.h,这些文件严格来时属于硬件层的,如果软件层出现这些文件会显得很乱。
, e. _+ Z% [$ w, t# C- V使用过Linux的童鞋们肯定知道linux系统无法直接操作硬件层,打开linux或者rt_thread代码会发现代码中都会有device的源文件,没错,这就是驱动层。
6 ^9 B# G$ ]6 n/ i

sis112cs4gh64026495427.png

sis112cs4gh64026495427.png

" ^% W0 o4 r/ w/ I. L; p二、实现原理原理就是将硬件操作的接口全都放到驱动链表上,在驱动层实现device的open、read、write等操作。当然这样做也有弊端,就是驱动find的时候需要遍历一遍驱动链表,这样会增加代码运行时间。
2 l, W" d+ [" z: A( M1 G! L三、代码实现国际惯例,写代码先写头文件。rt_thread中使用的是双向链表,为了简单在这我只用单向链表。有兴趣的可以自行研究rt_thread
2 W( t4 C8 M: [, c8 w3 Y' e头文件接口:1 u& |' h( B; h( t
本次只实现如下接口,device_open 和device_close等剩下的接口可以自行研究。这样就可以在应用层中只调用如下接口可实现:
  f* I" B7 m5 Q0 j/*/ M; H8 o4 X9 f5 w* I- k
    驱动注册
% K& ?9 `0 @4 F' C*/( ?0 J7 F2 F# `/ T9 w9 F
int cola_device_register(cola_device_t *dev);7 l4 C3 }, D, K4 H# o
/*
0 Q" s- R3 c" A    驱动查找0 ]( ]3 g" i, I5 @) c$ H: B
*/9 ^3 W7 }4 A  H2 D7 U" W
cola_device_t *cola_device_find(const char *name);7 D; U0 c  q5 y
/*
% S0 p. {! c3 N# \, v8 M    驱动读, Z) g( z* j! G) b! H
*/
  E& }% t- p, ~+ W1 nint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);3 B7 K: v  c) Z/ I' f0 h$ q
/*
4 H- E: _# |) f3 S$ h$ o1 j    驱动写. c6 T& B. B. S2 y% {
*/
) G5 q0 h  N3 d# e( xint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);4 g" _; [+ S% F! P( R
/*( L; A7 O: ^, E  b2 H  T- ]' g
    驱动控制$ X% ~3 s+ }0 _3 |0 ?3 \
*/
! x5 k7 k+ K- `# Uint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;头文件cola_device.h:
, Y5 R. T5 L2 {$ U* q& W9 X0 G#ifndef _COLA_DEVICE_H_' a. {9 M" t& N
#define _COLA_DEVICE_H_
8 t2 C  h) _5 `  kenum LED_state2 t* _4 A5 T, [; v. N8 V" G6 k
{2 t: H& N5 {0 G6 ~. I/ x0 [+ B
    LED_OFF,
4 C4 S3 k' D9 Z- Y6 y1 Q* C& X    LED_ON,
" v4 c' q1 l% T/ `    LED_TOGGLE,& S/ J) K' S/ i5 W4 M! c+ P  j
};/ a1 G& W4 }$ a& `) b- i0 z
typedef struct cola_device  cola_device_t;
" i+ q/ g" p) S- a& g) G6 wstruct cola_device_ops, l/ {! y8 y, L8 W
{
' x2 j  a4 e- s, D3 @0 u8 H    int(*init)(cola_device_t*dev);
7 B5 d: v  X' H7 y& v; ?    int(*open)(cola_device_t*dev,int oflag);* T# E" T0 x/ C4 R$ b
    int(*close)(cola_device_t*dev);
  Z. y/ }! j& m# `! i9 p    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
) J* [: A- x0 d. t4 J    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
& N% V0 v- d: A; A2 P    int(*control)(cola_device_t*dev,int cmd,void*args);* ?- @4 u/ M: |
};( P: ?* K& k. Y1 r0 l6 A  Q1 y
struct cola_device
/ g0 u8 v3 e0 [, i/ k8 \{0 V! j$ k' C! i7 Q7 r
    const char* name;+ a1 Y. X8 a9 z8 C7 U* u
    struct cola_device_ops *dops;4 [5 i' x7 ]. Z8 U; p- ]- Y- B' ]# N1 G7 i
    struct cola_device *next;  t4 U# r  R+ k9 U" n- D0 n
};
( W; F; e2 u# r$ t/*  L/ g$ z' H: Q/ ^
    驱动注册
: i0 h1 Q; L% |*/
- }; t" @- G7 o& K: |int cola_device_register(cola_device_t *dev);) a7 W9 r8 T4 u8 d
/*, }. ~' u2 u; y1 m
    驱动查找9 [& Y+ ~+ _" U& Y  Q( c. I2 W
*/  U. t& |1 L& d+ C! T
cola_device_t *cola_device_find(const char *name);
* r( I. A' ^% Y. L  ]6 \2 b1 n/*
* Q" t; q8 ~: e' `8 M    驱动读
8 e& e0 V, E% r' e5 J& }*/
0 J3 K5 Y& N3 a- p" |6 X+ e4 Cint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
; x% ?2 I4 x, j7 A8 T$ v( x1 d/*
" k6 |0 p8 B4 j1 g7 F; [' b2 q    驱动写6 H; H" _6 R0 Q2 Q* T
*/2 F. b' x6 Y/ W) e1 q. ~5 N! ^# v3 Y
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
* s2 n1 N- D/ ^& Y+ o/*% F6 M' c  y3 E1 D7 |( n8 M
    驱动控制
/ c3 Z2 W/ C; v! x9 s) j( W. u& g*/
) r$ I9 y) s4 _0 n; o+ S  e7 Sint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);; U  J, L  {/ x
#endif 源文件cola_device.c:
! P; b2 S% ?3 o) ^3 V$ l#include "cola_device.h"2 j/ N8 }4 y8 N% t* o$ i, r) A
#include
) ?( |9 ^  l1 X4 b9 ?5 b* n#include 6 _$ }6 n8 t4 |' P8 r3 _
struct cola_device *device_list = NULL;" a5 {( g* D' x# H" E
/** q; a8 t0 \' x1 Z/ `+ O; @) O
    查找任务是否存在
! p$ {' a, R( ^- S*/1 k2 J$ C  W8 R: _
static bool cola_device_is_exists( cola_device_t *dev )  z$ @6 Q/ ?2 c" ]
{. }) b5 x5 {( D7 j- o7 }
    cola_device_t* cur = device_list;
0 F* ^; Z5 g- |    while( cur !=NULL)
' F" a1 n7 |, j$ C: ?    {7 k9 N' s1 d2 N) s. n, K! d
        if(strcmp(cur->name,dev->name)==0)8 J2 k- G: c; {+ A4 P
        {
9 I% L4 z* [) @2 u, i* |- H6 `- G            return true;2 d6 K7 t; S( i/ M
        }
- O# c: m; l+ j7 s; a        cur = cur->next;
* Q7 L$ |% P& B    }
  J$ Z9 e# ]) E  F$ ?- |+ Y    return false;
% d% A( D) w  W3 U' s  n}! w1 Q# C  k, E; l: W
static int device_list_inster(cola_device_t *dev)
" i, r# f1 |# O# l$ B{) f/ T( D' }6 ]+ }
    cola_device_t *cur = device_list;) \8 c$ H: _$ x; n( j" n. z
    if(NULL== device_list)
) D, ~  r4 p- {0 ?. ^9 Y2 ^    {
& ]+ u# |+ d$ f7 u; @        device_list = dev;
1 c9 ?  r" B& g& h3 r0 o) H( k        dev->next   = NULL;
0 U3 g5 k. a# _9 z- H    }
/ l! e9 `4 k& D" p    else( f' K' o! q+ P
    {
$ z) \) S) J3 R. w        while(NULL!= cur->next), x$ j3 y* x/ e+ [, a
        {
7 w1 S* R# J' F            cur = cur->next;4 _# o" @% J. P1 z3 h$ B
        }& k% I5 l( Z" V9 M, M- r
        cur->next = dev;
6 \7 K6 h' c8 o) Z        dev->next = NULL;: F+ e3 a: K4 w9 C9 m2 l
    }
) F7 p* W1 }( `3 T' p4 G0 s    return 1;
- g4 u/ p; D' k! C8 l}
, o7 K" F/ d, C& R; M/*! R3 X; z) O" J+ Q1 p* B! @' l/ i
    驱动注册  A1 C* d2 j( |: b, s& O* P& W
*/
8 {( T* ]; a! Qint cola_device_register(cola_device_t *dev)
' @7 ?0 I4 ~, ^{  w; ~4 n, N! Y! n
    if((NULL== dev)||(cola_device_is_exists(dev)))7 e3 Q" x; w: F% X
    {4 _& x+ V7 s/ [5 p% m: ?2 O# }
        return 0;& z& n2 K6 _; s3 c2 z3 Y
    }
. T9 }' j4 j: u* ^    if((NULL== dev->name)||(NULL== dev->dops))% p- m: c) f; x! v6 }  b6 B
    {
! Y6 D7 [; T% v: Q& y0 h        return 0;* V: j7 a4 l9 z* q+ P( F- {
    }& M3 p1 N, i; w, ^1 N2 C
    return device_list_inster(dev);
- B" x- ^/ J5 C6 y5 o}
8 F! Y% S$ W# X$ A' c! S1 q/*
7 G( r! f8 \. D3 d    驱动查找/ y. D+ L: N$ B% @2 b0 V
*/
, R: h, s! `( U$ ^cola_device_t *cola_device_find(const char *name)# }9 V) {: v5 U
{
; n3 i+ Y- g$ m" ^; d    cola_device_t* cur = device_list;/ ~7 z( t1 I+ A  F4 F; [$ J. @
    while( cur !=NULL)
* ~/ T; U) n( ]* L$ w( f8 v* j    {
" ^  M; }6 {! `' c$ E+ G        if(strcmp(cur->name,name)==0)
, u& c4 `) [7 z+ V) V! [        {* S; h5 L/ I* G' J
            return cur;! @# r) x* Z7 S" T+ V
        }
, D1 s* V$ H5 D1 A+ g# ~        cur = cur->next;. m5 s2 Q) Q5 t" ^0 \9 y  L$ N
    }) ]; @3 _- W. U+ S  ?/ n( y) h$ B
    return NULL;1 }2 d+ {$ a$ ]: J: A+ O  o
}3 T; `9 z. Q. m$ j
/*8 C, A/ W+ u' \8 o2 c8 e2 r
    驱动读- ~' J; N* D1 p, Z/ @; H+ B( g# c0 ^
*/
" s; V! o' f' O8 P1 mint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)# \$ {, X/ V# Y7 v! f
{3 c7 |# W. S; M% H' h, y6 Y+ Q$ P
    if(dev)& ?) `6 q- m; _* S  G
    {7 w# d- @$ t7 I. c1 g. H7 `
        if(dev->dops->read)
" o: ?  ^8 L7 p+ R& }! V. y2 j        {
; o+ Z# C3 E' }            return dev->dops->read(dev, pos, buffer, size);
1 s3 h# U% K/ q$ n$ v        }
& [% M8 L- O" R) [    }
- @. F) s6 i! m0 R! w) A    return 0;
, ^; A, }2 U8 F0 k}  P  M7 y" u+ X. V
/*# R8 ~" @: ?+ H9 @- e
    驱动写
# l; v( \: _- x) u5 G8 L*/
' K6 D; g- n8 s, f3 p0 h5 Mint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
' f0 q) c, i2 @8 s$ b3 E3 [* y{
) ?1 w  e( T1 _4 ?! K( P& Y! ^    if(dev)
% w+ a% x& j8 H    {
' W9 i. `( J1 y) r        if(dev->dops->write)# ^1 G" H. m( l8 R$ Z
        {
2 `. c2 D6 m" ?9 }& Z, G            return dev->dops->write(dev, pos, buffer, size);
' k  s: B6 R+ U4 j4 ?        }
& r( |. [$ Y9 A4 T5 a: y2 Q  v    }
8 G3 X! [( P7 b8 A, E8 c    return 0;; m* [: h( b- e' w) D5 ^! D
}, g* s+ g! ]" R  v
/*3 [& r% A% Z0 i! y, G
    驱动控制
% t4 D% N  ~/ J# U9 E+ b*/. D5 ^3 I: t6 ]% G' D# F$ j
int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
5 [; x# B: {4 w7 E& c6 T: X- w{7 _0 x6 @* X% a* Q, J+ o( @
    if(dev)
( }. x' p9 Z7 g: `4 |$ N3 _0 {  q    {
, F$ q* K* t& }        if(dev->dops->control)" O! x; V6 O' n$ O; |
        {( N7 a' s$ H$ |) h) _4 A1 T
            return dev->dops->control(dev, cmd, arg);1 r9 l7 [5 U' v) U( t8 o" O) O
        }
4 {3 x; M( A. C5 L1 R$ M    }6 J7 F* D1 [5 `# [0 ]/ V
    return 0;- H3 U/ o. b( B. [5 @3 v& Z
}硬件注册方式:以LED为例,初始化接口void led_register(void),需要在初始化中调用。
$ F  w& ]! ?5 i% w+ B  Q; F, l' g#include "stm32f0xx.h"" t: v. v& J) J; s
#include "led.h"  O% O( [! D) F4 e& Y/ ^, R% k
#include "cola_device.h"
3 m& k# W; d' T6 @! g9 {% @- t#define PORT_GREEN_LED                 GPIOC                  
2 Y: h8 t: V6 a, M* z; C#define PIN_GREENLED                   GPIO_Pin_13              ( W7 }4 [2 }, @
/* LED亮、灭、变化 */! o: |1 Z6 Y! C6 h
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
# ?9 p  r9 H# {7 Y0 K7 k#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)
. X8 o8 M9 C. g; N' Y#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
4 D: Z! m) f* H0 B+ g( Istatic cola_device_t led_dev;+ ~! o8 X3 U" h1 u9 \
static void led_gpio_init(void)
' h2 V2 R2 y8 {6 y; ~8 `+ O{
/ M8 v' r, M( ?) v1 _    GPIO_InitTypeDef GPIO_InitStructure;
) d* Q1 B2 T- Y. `) S' l    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
3 a0 I' O% C) B7 w8 a/ v: |    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;# U0 K( Z# B( H$ L7 e) I( |
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;4 p* f  \' a6 L* b5 |
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 n# d" l* K4 Y5 ]* K7 u& n
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
0 H( N0 |' i. O& e5 F$ @$ D8 J    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;$ n; N1 k+ g0 y
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
* I3 l: H0 D0 [; c4 g" {    LED_GREEN_OFF;
+ P' v0 _: A6 t( N' O6 s$ B}
( Z! g- z8 C# j! z2 v% `$ R3 y1 Z; N6 X; t- E
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
/ Q! u9 Z! Z& @7 O! q0 R{& B$ H' t' w- U. i
    if(LED_TOGGLE == cmd)& Y0 w; e& X1 l, H
    {, d  D" L1 }$ _9 W) r  L) s. }2 l
        LED_GREEN_TOGGLE;# r1 m( S0 s/ N' q( D6 g" I
    }
$ n6 e6 V5 c/ X% Z  @    else8 X" k5 X6 Y; Q8 f1 [% L! L: }7 ~
    {
2 t" U, x7 s  O' D, D' R    }
1 C1 m. O3 G! s4 j, \5 d! x    return 1;
1 N- j9 O1 q1 D2 P}
0 t% d8 v' U) Y: S- R" Y% x0 xstatic struct cola_device_ops ops =
" i$ N, r7 N, V9 H& _' J/ l  e{3 L2 R' M. ^# C$ k$ h8 T  `0 [
.control = led_ctrl,
" w6 K+ F' t$ {};
( k5 @! G; L& D$ @, s! d$ fvoid led_register(void)8 n" T' g9 Q1 ]
{' N" `0 l1 Y, g& K
    led_gpio_init();2 m& w2 Y( `& O0 V+ w6 I$ I
    led_dev.dops =&ops;
, k9 Z; b- \6 l: }0 u8 v6 {    led_dev.name ="led";
6 k) M, ], m$ o/ h# N9 ]" p    cola_device_register(&led_dev);) w/ y0 `8 F! t1 I1 p
}应用层app代码:
8 P2 n; W& ~3 x' ?( i#include
1 W' R" p: `- ?#include "app.h"
/ D( @; C% X0 t#include "config.h"
, ^9 \# b8 V: J; ~; m5 ]: U#include "cola_device.h"! O9 n% k# K, I0 @
#include "cola_os.h"
  y% t7 j/ L  ~% e7 I) S5 estatic task_t timer_500ms;
9 H  q4 _' @" p9 @6 B/ e' c+ ]static cola_device_t*app_led_dev;
) U( G3 X4 l* _# }! n( q//led每500ms状态改变一次8 `# H# s8 S& [. w( C6 X. ]
static void timer_500ms_cb(uint32_t event)) [) b' r3 z7 o! Y
{. A- T2 N' Q+ d5 f' Q0 ?. l
    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
- {3 Y4 ~6 k# @+ e3 N* Q}! C' M8 q/ g3 x
void app_init(void)
4 c8 A9 a& d9 [5 v4 U{
- F% a! s. Q/ N5 H7 p( O( I) j    app_led_dev = cola_device_find("led");$ c9 z4 }% p# P! H& K. U; x  a
    assert(app_led_dev);0 n5 f$ G! I3 }$ J# a
    cola_timer_create(&timer_500ms,timer_500ms_cb);/ ], e' @% A) i" m
    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
3 V6 i) U( B$ d8 ~3 P}这样app.c文件中就不需要调用led.h头文件了,rtt就是这样实现的。. E7 n: x0 k2 _9 i7 o" k7 U
四、代码下载链接https://gitee.com/schuck/cola_os! O  R0 _9 p1 o  D4 C
原文链接:https://blog.csdn.net/ziqi5543/article/details/101512722. y7 V( k3 h0 N5 ~7 o4 D
-END-
  A5 Z& c. X8 H/ K# w1 s往期推荐:点击图片即可跳转阅读
3 `4 ]& @. R% \) I" s                                                        / C. a# z/ \8 [5 R
                                                                " f6 }9 p& f! }. A! Z7 ^7 h5 W5 q, U( a
                                                                       
' l2 _' B! K: L5 S0 Y1 k                                                                               
$ j  B% L! i: @( r6 d! E8 e9 a

qffajmyjrru64026495527.jpg

qffajmyjrru64026495527.jpg

9 @0 Z/ e2 R& U+ `. A6 G                                                                               
2 N+ c' `  @& p7 f4 H' i/ N# C                                                                                        嵌入式 C 语言的自我修养( u. R" c. B5 i  E0 G. M( t/ x
                                                       
# J9 v0 W; J# l- C. _; [4 X" r                                                               
2 B/ E, |  P+ U% u% f                                                                        " A# J0 d! U7 ^8 [( y& R0 N3 l! P2 I7 _( q
                                                                                5 Z  y% F& x$ n! _- h# S

dfe224e5wga64026495627.jpg

dfe224e5wga64026495627.jpg

6 m/ T, t, {0 C7 T2 U                                                                                # N  Q6 v' r3 y4 _
                                                                                        被 char 类型的变量坑惨了!
2 o, u/ K/ y/ C5 C6 W1 E) L2 L                                                                / {: Y1 J3 j3 E* u5 H; {
                                                                       
: l" R8 Y5 Y) t- O/ p6 `                                                                                * a$ r, s$ Y' K* A4 {, E& T

b3qpejpoxth64026495727.jpg

b3qpejpoxth64026495727.jpg
2 D3 ^  j+ R! r. v8 P1 k4 X8 v
                                                                               
% u$ w+ W4 K0 f                                                                                        嵌入式 C 语言知识点,动态变长数组
, {. m- G  ]1 a; x8 I                                                                               
7 |5 S0 @$ u9 \" ?                                                                        ; L, @0 i0 d/ o  `: ?- L" W/ C
                                                                $ C1 V2 B4 _8 r8 }7 b8 a- J
                                                        我是老温,一名热爱学习的嵌入式工程师
2 d$ _+ Z( U2 Q6 b; b关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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