電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 42|回復(fù): 0
收起左側(cè)

如何實現(xiàn)嵌入式軟硬件分層處理接口?

[復(fù)制鏈接]

455

主題

455

帖子

849

積分

二級會員

Rank: 2

積分
849
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-8-12 17:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師4 Z9 f4 Q1 Q, ?; h, E+ ~, |* J
關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應(yīng)用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。
' @! \$ F; i' D& q7 r# J使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅(qū)動層。
# t( S0 D/ y$ G# }. X
4 H2 g8 O' w! p! h: l/ J* w二、實現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動鏈表上,在驅(qū)動層實現(xiàn)device的open、read、write等操作。當(dāng)然這樣做也有弊端,就是驅(qū)動find的時候需要遍歷一遍驅(qū)動鏈表,這樣會增加代碼運行時間。
3 E$ N$ q) F' [三、代碼實現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
' S2 K: Z1 q5 q0 [7 n# I頭文件接口:" T' a+ G1 O$ L! M
本次只實現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實現(xiàn):; U8 z5 ~) Z  t3 c* E
/*' p8 A1 s5 M9 @' V" Y. _
    驅(qū)動注冊( g/ c* e6 k3 [& S
*/
3 _2 |2 |2 ^1 L  h% \( x! n! ]' Kint cola_device_register(cola_device_t *dev);+ p/ H$ y2 [4 J0 D
/*& ^# M+ M; o6 `0 l/ t
    驅(qū)動查找9 L, _4 {3 f  D% n' u9 g
*/) b: r6 n1 B7 I4 g$ J
cola_device_t *cola_device_find(const char *name);
3 `5 X5 N! T) y5 ?+ D% I9 J/*
) j9 H  P) G4 q3 g5 t2 G( o5 `    驅(qū)動讀
$ l  X/ }: U" ~) b$ C1 B7 C*/
# r5 A2 @; t; o# tint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);
8 M+ j' b7 T9 Z3 X/*6 M. h0 H# l; f& S# x
    驅(qū)動寫
4 `0 ^: H( P/ r( {1 L*/. W" E" C2 f( k) T2 j- b6 t- z' E
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);9 G5 B" n& Q  W9 A: d
/*
" g, U) {8 B8 r/ C. y  g! t4 G9 V    驅(qū)動控制
% }+ d( A3 n3 J. c7 h+ N* o1 L$ D3 V*/
3 _2 L% B& w5 m: x) Qint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);;頭文件cola_device.h:
$ Q7 ]! @% ~" K! k#ifndef _COLA_DEVICE_H_8 X8 q9 R) O8 Q; R0 E
#define _COLA_DEVICE_H_
* F/ l. H3 @/ \0 h6 ?" H- Henum LED_state: s* n+ E  r2 L) ^
{
! W3 k1 t5 B, k! X# F7 }* K    LED_OFF,1 L2 ]9 X8 ?7 n) z9 |0 M/ W# |1 t
    LED_ON,2 T$ C. o' y! i6 e# m
    LED_TOGGLE,
5 l( v" o0 s1 [/ q};8 |7 A( F7 ?$ }0 e" R* m' H
typedef struct cola_device  cola_device_t;
$ T; h* I* ]) j( jstruct cola_device_ops
5 W+ O3 k; m3 g0 b5 b0 i{
- y9 Y3 ?/ _& y    int(*init)(cola_device_t*dev);9 k- X1 g  _4 Q; I( u3 p/ Y
    int(*open)(cola_device_t*dev,int oflag);
, b; O! t# \) h8 ~$ {% f    int(*close)(cola_device_t*dev);0 j) b" w0 M* [. O
    int(*read)(cola_device_t*dev,int pos,void*buffer,int size);  {" c0 s9 d. n% C
    int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);5 t! p8 x; }0 [* X* p8 ~4 L2 n- U
    int(*control)(cola_device_t*dev,int cmd,void*args);
$ `" H1 k1 Q8 x+ c' y& z" N};  B2 K6 `7 `" d5 j6 W3 \
struct cola_device* ^' _- k. Q0 Q$ m- a) k3 V
{) |2 @" T4 s8 p: s& R; m$ \# V2 p
    const char* name;
' X+ m$ m( C- m4 f- \% l    struct cola_device_ops *dops;/ z$ x8 T; l. s' ~5 `/ K5 ~) h
    struct cola_device *next;
, |8 {' W+ i1 [* _};
! `$ G) A8 E/ C9 }: U0 g/*4 e1 g4 D2 H; W% A. e, ]
    驅(qū)動注冊
9 n6 w1 d; u. A& l*/
! F3 d0 j) F/ ~0 z& X, @4 ]int cola_device_register(cola_device_t *dev);1 j3 ^9 `- J+ |, D
/*
7 O! l6 R6 m" i' _: R/ o    驅(qū)動查找
5 w0 E* M( P" ^! i* ~( p*/
- E1 V! c' E4 h5 d' H( c4 w$ Icola_device_t *cola_device_find(const char *name);
" ~: ?8 z% {7 M/*$ Q7 F" f- X% d5 e
    驅(qū)動讀# T5 `0 K& M0 l$ |' c" {' g
*/
) Y* U* e8 r) ?" k3 W/ }int cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size);! T) i0 Y  k0 v
/*5 r3 A) o% v! v; C' Y
    驅(qū)動寫
% d, c; n) @. t*/
! j  v& k" W! `9 F& @" _, A; Rint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);6 D& O' S' a+ c5 v$ U( O, Y
/*
9 h2 y) E8 v* x; J: Q" b    驅(qū)動控制
$ n+ s' G7 c0 Q+ C- t* W* C7 |0 f" W7 M*/
: i9 ^9 E  x$ \int cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg);! J. }% Y7 K. J- v
#endif 源文件cola_device.c:
8 i' J- Q1 K8 p( u9 m( L#include "cola_device.h"
" I1 D7 `; s0 h$ d* A#include 5 i4 f) z( ~. e9 |2 p  K) R
#include
$ s- U" U- [6 D+ i1 Z' Mstruct cola_device *device_list = NULL;3 z% f  _" i% {
/*
5 l! f- _" u5 E3 ]) w* p) ]    查找任務(wù)是否存在* d! j# O2 o0 p- g% {! a
*/! o& @$ H7 Z% @4 k: d/ Y! Z6 |; o
static bool cola_device_is_exists( cola_device_t *dev )1 b9 a) W5 M$ g5 @$ [
{
) w" X6 b! n/ S  S! E6 `    cola_device_t* cur = device_list;8 k3 y) H% F1 T# y; F. b9 ^
    while( cur !=NULL)6 o0 G6 i0 n; V/ I2 T7 j/ H( q
    {( G1 E- A% p3 e2 q
        if(strcmp(cur->name,dev->name)==0)2 R+ r7 R, X* e9 H5 }9 P
        {) F4 n6 _! O% A7 {9 R+ b/ M- M$ g
            return true;& V$ T' I4 x8 q/ D) v8 {! N
        }2 h9 Z( K$ R* h, x, h3 n
        cur = cur->next;+ c( j, X3 D6 y2 j0 Q- E
    }. T/ a5 {" Q: v3 s" k
    return false;
/ a( e0 P3 |, o  {% c}
% d0 Q5 d! y" f1 R# E4 u9 gstatic int device_list_inster(cola_device_t *dev)/ \: v) N* l2 J  C6 a0 k
{
5 T- j+ Y# t) b2 Q; a$ S9 z# V    cola_device_t *cur = device_list;
6 B7 a4 ]# o, |7 j: h    if(NULL== device_list)# B0 X- `) |6 z5 I2 p' v9 b  h
    {
. T+ k4 p0 P4 i7 O* M        device_list = dev;
4 e6 t' E5 V5 K        dev->next   = NULL;
, R( J  D( v5 H7 m8 O1 X    }
4 [7 a0 Y. \/ k    else/ A3 ^! _4 c& ^1 ]2 x
    {$ l7 S! N; u0 o8 a
        while(NULL!= cur->next)7 B: S1 N/ N7 y( M
        {
2 G- J0 g5 C. e) c% j/ p            cur = cur->next;; K, J' X# e( c1 p
        }- K; Y' n1 q& i
        cur->next = dev;
, `/ W* [8 Y! t- e+ _        dev->next = NULL;' U9 z# j/ D, e3 n
    }8 P9 E0 J1 q3 B1 p, A' ^
    return 1;5 t5 o  W8 k1 a! j; {# [
}* I) j. q0 K" Q4 x" F8 M, X
/*0 \  ]  [2 e8 r+ x$ u
    驅(qū)動注冊
/ K! f3 o6 k+ z1 s2 b% C+ a*/8 ]5 x; Y  N$ g3 q: E6 g( J
int cola_device_register(cola_device_t *dev)2 s, U, `1 S) \. e
{
+ b* m" C8 Z: Q0 w    if((NULL== dev)||(cola_device_is_exists(dev)))
# O! y, T3 @* ?+ J5 \5 T$ q    {
! R3 [1 R6 z% W9 n2 C& h        return 0;
% N# P2 v/ v" O% |    }
: e( ^- a( C3 k, L( M$ }    if((NULL== dev->name)||(NULL== dev->dops))4 t9 Q; U1 V, x
    {( _' M/ d: L* m6 k; [2 X
        return 0;+ S5 A& b, V, G
    }$ G3 r$ h1 H/ d" R% C
    return device_list_inster(dev);
' D4 e3 _0 P$ s& I' ?) b) p}
0 M4 X4 j- y. H/ N4 D  A# v% p% v7 z/*
2 M, m- W1 x% m% H1 E, F    驅(qū)動查找$ H! n( u9 I/ b
*/& f/ @5 M8 f  m1 l4 Z& x3 G
cola_device_t *cola_device_find(const char *name)
" w9 _8 A( T: X  q{' x& h4 ^! d) G  H  [
    cola_device_t* cur = device_list;
) n4 ~7 A% x0 Q: B# z) n* }9 t; L    while( cur !=NULL)3 q3 B5 R9 M( J2 }* |# ~# s
    {+ Y# D0 l8 {5 v1 S! a. j# y- t
        if(strcmp(cur->name,name)==0)( l, R5 D; P0 I1 M& \# z% v
        {) ]2 L5 W/ _/ g' }2 Q
            return cur;
; S9 ]5 W' |. o! }        }
' o- y% j: c+ b1 N        cur = cur->next;% N0 W$ k; E" b$ }/ W/ h0 M$ Q
    }! U6 V* `$ c1 F; Y1 r9 i& @
    return NULL;  z1 D0 E, M. \- N; c
}. {/ X; A: l! E& r! C
/*) j) `' B0 D* k* U" h& A, q# q
    驅(qū)動讀# ~" Y' {- l6 J
*/
2 R8 ~  N4 L7 T" T( Iint cola_device_read(cola_device_t *dev,  int pos, void *buffer, int size)
* U. W; h/ i" _% k, s. G{
$ A$ }6 Q1 I/ u; P    if(dev)
7 [% G- `8 q0 z8 K% @" a" g3 @' |9 B3 J    {
' s5 z/ I0 Z, U( g9 S- x' [) s        if(dev->dops->read)
# |& h: S3 N# p        {5 l* A; D* p0 F$ e  I
            return dev->dops->read(dev, pos, buffer, size);! K/ @' ^$ j( R9 V" p+ c
        }
- v' D) K# q) q! t8 b/ t    }6 X& f1 {5 x9 j4 g) L' S
    return 0;
; X; Z' G' \9 c. V}2 A% |/ I, ]; _# |7 d% ]7 y. I
/*. D7 t- X- F7 z* I% I' z$ P8 O
    驅(qū)動寫
: F# s0 s! q: O. y8 U*/
( R/ }# u5 _- B# ]8 c  s: Hint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)
* e6 n' H4 @/ N5 Y9 w* k+ i{
( C1 Z; m- P  z2 a0 o/ P( N$ O    if(dev)2 J4 i2 q6 s( I0 e1 @; _  P8 G
    {
$ _. C. I* t% E2 C: v        if(dev->dops->write)
* l. I9 E$ q# ?2 g2 v- D) p        {7 f' r3 u0 \9 B( h! t
            return dev->dops->write(dev, pos, buffer, size);
8 Z/ w+ C; C/ J' K- c2 n        }) b' ~$ p* V# R" w6 x5 O/ x" @
    }
( D2 P/ J$ N! q( E    return 0;
- J5 j1 e- o! t" z  H2 t}7 w. ~& U8 b6 n. i/ _
/*2 V) k3 `7 W: e. V# d
    驅(qū)動控制( B$ O# L& V" A- v" q5 w" ?
*/
0 }5 |4 b1 [2 G" S% Y6 `9 r  e8 Hint cola_device_ctrl(cola_device_t *dev,  int cmd, void *arg)
- L/ ]% z5 O/ b{
% N5 ~) W  |% |) V    if(dev)% |$ |; g+ f+ H  S' s1 N) @- l  {
    {: I, q! J- `2 L/ `) l
        if(dev->dops->control); R+ L- |! j, I+ R- Y! _
        {
1 u6 C# E1 L# I( L9 Q* Q            return dev->dops->control(dev, cmd, arg);
0 _6 |  y: m2 V! w        }
) N4 C- l' k: H7 U& d7 K    }
0 o9 o! a) J6 @3 _( B) G    return 0;2 P* M- L0 b/ u
}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。0 q& M6 q4 v$ w8 \! F7 k5 s
#include "stm32f0xx.h"
  m. Z( R4 B' s0 L; p. ^/ k#include "led.h"
" _: v5 A. \' l$ D& M/ I#include "cola_device.h"
7 ^- |  |4 z2 K8 Z5 a. c#define PORT_GREEN_LED                 GPIOC                  
9 a6 j1 G: c+ o8 w6 s0 Q/ j#define PIN_GREENLED                   GPIO_Pin_13              ' E4 P1 F1 E& W4 ~2 D$ n2 k
/* LED亮、滅、變化 */  G- W5 K$ p4 y  {" n
#define LED_GREEN_OFF                  (PORT_GREEN_LED->BSRR = PIN_GREENLED)
& Y% p; F- M- @. f, n#define LED_GREEN_ON                   (PORT_GREEN_LED->BRR  = PIN_GREENLED)8 E( w" E2 P9 x) W; i& @" _
#define LED_GREEN_TOGGLE               (PORT_GREEN_LED->ODR ^= PIN_GREENLED)7 q' i; p0 z% j4 {
static cola_device_t led_dev;
* E/ j3 o$ ?3 T) S- o6 \4 Fstatic void led_gpio_init(void)
3 ?8 Z$ H8 g. o. t- n{; o4 `& z/ y) j. x# k" J! U
    GPIO_InitTypeDef GPIO_InitStructure;
, P; p5 A+ D0 R. `$ v    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
! g% ^  M( n. m+ K* l" Z- W4 {    GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;6 {* d9 ^' x9 A8 ?" [, y
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;2 M( E3 _9 Y* w7 U
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;5 n$ ?( }# X) j5 V9 s
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;& o8 S. t! a  w' v% t9 J
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;, U1 |. L7 I$ o
    GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);" _, e! [4 |+ l& Y0 L
    LED_GREEN_OFF;( @2 ?! ?, j- q) m
}
" V9 L. Q- U& H0 J3 n( e& H+ R4 C4 |6 |0 C& ?9 U& W- Y# u
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
8 t2 O1 K2 @+ ~& k- h9 r{% [- K( V7 u+ K+ B
    if(LED_TOGGLE == cmd)
- i5 T0 ]' \' K( ~' s1 R    {
4 Z7 l& f$ ^" U4 @7 O        LED_GREEN_TOGGLE;
6 j+ j! S' H0 @1 i/ g$ Q    }
# H4 B  W" l, \" j$ v; A7 d) B! `    else2 p, _, |+ l. U$ x: e
    {# R1 H8 w1 H- X1 n, ~' w1 i
    }
, M, i% G; V( w6 F# W: P    return 1;5 m/ g$ W# y  }0 ?. O% h
}
4 Q2 r% y/ v, q3 O+ Wstatic struct cola_device_ops ops =: |' y2 b( @) S( ^6 t
{& Q. q2 p7 J3 o# j) o6 D
.control = led_ctrl,) a; |% C" E6 R0 M0 j
};
* @+ q. n/ r0 o5 a: D; e$ kvoid led_register(void)
1 r* r- z7 C, Y! O6 [) X% x9 b3 u{) D2 B  h" i& i0 G- S$ N
    led_gpio_init();" D' I! C5 ^3 z. q
    led_dev.dops =&ops;) v8 B6 L9 n- a0 u0 D
    led_dev.name ="led";
& N' H2 d  b( C* j( R$ r( e5 c    cola_device_register(&led_dev);
$ h2 u8 ]6 |9 f6 j" R8 g}應(yīng)用層app代碼:
% ]( \, |: t. X% }9 s) v% n2 T#include
/ b) Z. S' O' M" s- q) @#include "app.h"! w$ i+ g' `: n5 H" `6 G6 [
#include "config.h". ~/ R% K# c' o( M/ Y8 P% k
#include "cola_device.h"6 U) K6 J: |9 K+ b
#include "cola_os.h"
: f: L3 @5 u4 g- d/ R% G3 vstatic task_t timer_500ms;# C$ |! e( ?, }& m/ c
static cola_device_t*app_led_dev;
) v1 D* s; @8 e8 a//led每500ms狀態(tài)改變一次( g2 _6 C8 j, Q5 S( [5 n2 O! `* `5 t
static void timer_500ms_cb(uint32_t event)
: x! y( C' d4 s- v" B# }{
& S( c8 T$ w* w: R    cola_device_ctrl(app_led_dev,LED_TOGGLE,0);: |8 T: W1 o: n- O! K
}: I6 @! w: G9 m% o+ F
void app_init(void)
* ^8 }  X8 k! j& T: z; @) E{& e4 X/ ^% K' D9 }! z
    app_led_dev = cola_device_find("led");$ D8 |7 B' w) \) W9 M
    assert(app_led_dev);  @' K% E8 i* v2 ~4 O% W0 r
    cola_timer_create(&timer_500ms,timer_500ms_cb);
! b5 [9 Z7 V0 N* R2 C; Y; r    cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
. H; @) n% y$ H1 S+ W. G/ |  H: [}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實現(xiàn)的。
' z7 @6 D" P" I3 x1 n+ j四、代碼下載鏈接https://gitee.com/schuck/cola_os
- D/ h8 E  t0 D/ u7 k; l# z
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
, @, @& B+ z2 |+ f! |-END-
. V2 S1 @: z9 B  W  `2 h4 _9 B往期推薦:點擊圖片即可跳轉(zhuǎn)閱讀7 G6 d5 [) G+ `
                                                        ( O+ a8 C6 Y5 Y' B) x3 B) s
                                                               
5 X. `- c/ g" d' i2 _                                                                        . ?. j& C# a* K9 y
                                                                                : r/ D" f  J+ B' R

/ d- \2 b: }; l: P3 @9 e                                                                               
2 T7 |7 L- i& k! t4 [1 l                                                                                        嵌入式 C 語言的自我修養(yǎng)
5 b: a  s8 }* ~- U1 I: ]! G  k                                                       
( R) g  I# L9 a                                                                . T( R1 s- R/ w. E9 c7 c
                                                                       
4 o5 N* i4 a9 T  t* I                                                                                0 _0 I8 S, x% m9 Q) Z, j% e

  i- _  A: L# p  L# q& f! t! C                                                                                : Q- f/ ?' W  I1 M9 m% N
                                                                                        被 char 類型的變量坑慘了!  I! p+ l/ M( x7 A" H: m# ~0 o4 U
                                                                ; a4 g- i( t. O6 m
                                                                       
6 i# _2 N! R( b: l, I+ x/ e  S9 Q                                                                                * u+ ?* v6 K! `3 Q% e
0 E# F2 U7 G( C7 N
                                                                                . F* ?- l3 I  ^; X
                                                                                        嵌入式 C 語言知識點,動態(tài)變長數(shù)組' t3 i& Z- r! B+ _1 Z, w
                                                                               
& X' w( `8 C7 b" o+ o$ A8 H                                                                       
4 h9 N' I8 I9 n$ y& M                                                               
& `, g9 v* s* R- g$ r- N                                                        我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師/ Q1 j0 q( k0 b
關(guān)注我,一起變得更加優(yōu)秀!
回復(fù)

使用道具 舉報

發(fā)表回復(fù)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表