|
我是老溫,一名熱愛學習的嵌入式工程師9 w3 L' t: g' \. y/ j0 |
關注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網絡上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現應用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴格來時屬于硬件層的,如果軟件層出現這些文件會顯得很亂。7 V9 A* Z- W- g) D
使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現代碼中都會有device的源文件,沒錯,這就是驅動層。
+ v4 U; j) P2 Y
dd5lwp0asc16405226036.png (5.23 KB, 下載次數: 0)
下載附件
保存到相冊
dd5lwp0asc16405226036.png
2024-8-21 13:01 上傳
2 e% t8 q+ E# V' M6 ]# |1 B
二、實現原理原理就是將硬件操作的接口全都放到驅動鏈表上,在驅動層實現device的open、read、write等操作。當然這樣做也有弊端,就是驅動find的時候需要遍歷一遍驅動鏈表,這樣會增加代碼運行時間。
8 b$ y' j& u+ u三、代碼實現國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
- `" U, }& ~8 j% k4 v8 P頭文件接口:
4 M; q/ s8 ~& L" G0 n本次只實現如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應用層中只調用如下接口可實現:, ?1 n: x0 T0 |+ e" K
/*
, I% P) O* }: M0 ^/ n( e$ [ 驅動注冊& f+ D5 q5 Q: y% E" {2 A* l8 X- q
*/
7 i5 a7 |6 M+ {( `% tint cola_device_register(cola_device_t *dev);
/ }% j: p, Y9 }- r2 D/*+ @- p) R! t R4 a
驅動查找2 W, u* o+ Z; S, l% U
*/; h& |, v& P0 s3 |) V# s1 P& K5 Y
cola_device_t *cola_device_find(const char *name);
/ T' l: d* d6 l4 b" b8 b; s/*
' s- [6 V8 t- R 驅動讀
H4 c% C( T* o$ E. F3 m9 d" A' K*/
* Y$ n4 @. ?* l6 r4 L& cint cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);
8 R ~4 ?& ?' P/*7 o' @9 ]( O W6 d( [
驅動寫
8 R: G' s- Y4 o T( t) j' W*// Z' p0 I G3 K: t( | e; Q
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
6 x7 H4 L: R1 w7 @% j/*' x' c+ N; o8 \6 l* C
驅動控制
2 k# r! {" q. O5 Y0 q! s3 i*/
" s8 u/ _* ~- T; Kint cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);;頭文件cola_device.h:4 T3 r) Y9 F* P! ^% }7 ?3 L
#ifndef _COLA_DEVICE_H_# z& K& m4 F4 L- s
#define _COLA_DEVICE_H_
" i A+ U& B( venum LED_state
2 S0 L) l$ F& [/ h! z+ Q{: L }7 d# X. ~0 `
LED_OFF,; ~/ O0 D: `2 f- S
LED_ON,) J6 u; { U G0 `# S8 e" Z" U$ M
LED_TOGGLE,2 H, q# g9 E. E( @5 a; k2 |5 t
};, R) `7 j0 R/ ^) j3 F( \
typedef struct cola_device cola_device_t;
' t& V5 t, C3 A' Y- \2 g( `9 }struct cola_device_ops* F6 Z/ U, c( ^
{
8 F/ P& g2 s2 k% V3 S$ O" b int(*init)(cola_device_t*dev);
/ J4 `/ F8 n! B" I2 n1 P int(*open)(cola_device_t*dev,int oflag);
) w; t$ n) B- h t, M1 B int(*close)(cola_device_t*dev);
3 k2 E% J4 N# `/ l+ z/ | int(*read)(cola_device_t*dev,int pos,void*buffer,int size);' {1 [; u7 b- B" H$ G' C
int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);8 E4 U% c& ?$ B8 g+ e7 R. L
int(*control)(cola_device_t*dev,int cmd,void*args);
/ K0 o. F; W' }};2 H. j$ C* D% Y
struct cola_device
( u2 N: }4 n r{
C3 _4 P" P4 m( K, Y9 n const char* name;; j S- c2 P# y$ y9 H5 p5 R: P7 y
struct cola_device_ops *dops;# `. l) q% B' X5 m7 s" Q
struct cola_device *next;
# B% U' e9 L- b. \$ O8 Q; S: I};
& X/ F, D" S9 \/ l) ?# \* e/*2 x( E1 K! o" U8 _- `$ c4 @0 H
驅動注冊
! l# I* q1 @$ H# w) W* D*/
1 _% q, t7 \5 }, Z, b0 cint cola_device_register(cola_device_t *dev);! ]6 z# |) e9 h$ E8 G2 K9 l+ j
/*+ {2 d5 K$ L6 Z: w$ F
驅動查找6 ]. P9 ?9 x5 w! w% r9 J9 \
*/ {; {- r+ r. u, H# B1 T) `
cola_device_t *cola_device_find(const char *name);! C# R" l& o" @, v4 _
/*
4 P$ B& @8 B' ^6 @( r 驅動讀
1 y7 X! `" p1 |% M0 w5 W*/
% d( }' L% Y$ N: P; K! E( Iint cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);' [$ Y1 r" T5 V# K. G
/*/ S8 `4 J2 q% b- s' @$ @* ?
驅動寫* n9 ^4 P4 |" _5 @
*/% I) y- t: {9 {: p) w. m
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
6 W- z6 A y4 G3 t4 O8 k/ [& p/*
4 u# R D2 [; t8 ]) j 驅動控制& U" d* K+ m1 y) F; ^5 i
*/( O1 X9 H0 G" ? Z1 f9 T3 z1 }
int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);
' P, R4 D; c2 g: N" U/ U) N#endif 源文件cola_device.c:
! K$ \8 ~5 E6 n* T#include "cola_device.h"; y \4 T1 r L" | x) w
#include # R3 C; C. B1 C/ U7 M. h# v0 m
#include ) J7 k& k% }) \1 P9 v& `
struct cola_device *device_list = NULL;# E. o, Q7 v+ I8 w% `) F; C
/*( c9 E) Y1 Z+ x% e
查找任務是否存在; P4 I* H3 Q# \) ^# M( I
*/
8 K( J- _" u% \" \! R( ~3 zstatic bool cola_device_is_exists( cola_device_t *dev )
! d/ H$ V/ J% p1 a{
0 s. O" D) V, |; \/ A* T( w: a cola_device_t* cur = device_list; i Y" s8 _0 G9 T0 f1 R
while( cur !=NULL)" N4 n2 r5 U# @! w6 U: n
{ N7 E. P4 R, ]. R: m1 s, J5 f3 ~
if(strcmp(cur->name,dev->name)==0)7 l3 X* u% x: Q" _' y9 j
{
E5 P' D/ B7 ^5 N1 C return true;3 J, S. [2 f6 s, }- C2 B; \
}
) w) Z3 g/ i6 x cur = cur->next;
. S( W( [3 c! R( E: i/ ]4 h }
3 ]& x; r! ^! i, |& ~ L* M0 L) t return false;
6 d C7 f3 r* E6 s& _} S; C# U+ e7 H2 r; l% N
static int device_list_inster(cola_device_t *dev)
. \8 z E7 I4 n+ j9 T; Z7 O{
% K4 F+ `% e; Z cola_device_t *cur = device_list;1 _/ K- k9 y' c* |8 Z. y# _
if(NULL== device_list)
( j% F, s+ j L' Z {
6 a V. U. M3 X& O0 w device_list = dev;
6 f* M9 F( Y- ]6 ?0 i, c, s; { dev->next = NULL;
& {( M% A2 E9 }* T) F }
) j; y" X/ I a0 L else
7 l* c& G) A# }' W {
" f; V+ c) I! [' z5 V/ h; x6 F1 L while(NULL!= cur->next), p7 d) ~) e3 l" X- m7 N, G
{7 t) j* K$ L, q, A/ t
cur = cur->next;: W4 V# n+ p }& N4 ?1 x# o# u
}
2 E3 o6 u1 E7 { cur->next = dev;6 r- A; M1 S6 s r4 _9 ^' w
dev->next = NULL;8 U$ Q C- c2 J Y/ d# j9 u) T4 A* ~
}. b- X Q" {* [9 x3 m8 i" k
return 1;' ?' ]0 [* E9 T5 ^: d
}
+ L0 J6 Z0 b$ O4 b# O/*
3 S& k" g% I7 w" B# S* i% v 驅動注冊' D1 j5 s( T* x" v0 z- I* k" A, N
*/0 D( N3 k V/ t1 i
int cola_device_register(cola_device_t *dev)
% t& s6 S5 Z8 c: A{
# e+ t# {, h# |( ~) C if((NULL== dev)||(cola_device_is_exists(dev)))
( b% E. U8 Z. ?- H5 ^ {
6 K9 n) `4 N9 Z$ W return 0; q5 A! q0 w' B7 B* `/ j! y
}( d8 `6 Z9 z& C4 O0 a
if((NULL== dev->name)||(NULL== dev->dops))
: h5 k/ H! c2 x- D+ X {! s" x3 n8 K8 h+ M2 |
return 0;
$ O# h, a9 A. a7 N: J1 I }# C: S+ H8 z! d% M; t; o: ~ O
return device_list_inster(dev);* Z3 ]$ ], y2 s$ i% V, s- d7 C
}
( l. H8 R. E. ~. X" |& L0 U/*) j7 Z& H% Y( Q/ T9 N7 U
驅動查找
0 S& g' {# m4 l. M! l*/5 V9 O) i2 b1 |1 E! [
cola_device_t *cola_device_find(const char *name)8 ]. `5 P8 o. J7 b9 W/ |
{" w3 R* b+ i/ R. k
cola_device_t* cur = device_list;
( c b' f1 y3 P& A- L5 k/ m! L while( cur !=NULL)
- h' [. i# j1 H2 H& r {3 V) l7 v; f- W& y& m
if(strcmp(cur->name,name)==0)
$ n. T w' h5 }5 G5 ]5 Q( d {
! @4 L. `" v( H0 q& W/ q. [ return cur;
' i- a- u' @& s. z }2 A5 b% j( }! q8 s7 r7 {9 b$ L6 S+ b
cur = cur->next;* k. ^& F! Y& g3 N
}
0 v. N/ U+ U3 r/ { return NULL;- @ {6 Q }: U1 N" R1 V) l
}
% G. L9 }: h- d2 N6 O& X9 u/*' V! T& A$ a5 M% n& R) B5 r5 O C
驅動讀
2 g0 w: {) B: Q7 O: ?# ?( R: Q*/( I. P2 ` n6 |( f
int cola_device_read(cola_device_t *dev, int pos, void *buffer, int size)! u* `2 A4 C' g: I! j( } C
{; X/ t D% o9 H9 n/ `, U0 X; c
if(dev)
" f# l, [1 ~+ a: S7 e, u {
1 E9 T6 X6 r \" s0 q! ^ Z* s if(dev->dops->read)/ y; {" `$ J1 V8 ^' R1 b
{
% p! n0 P* g7 \* {9 l+ p2 q' d) I4 W! | return dev->dops->read(dev, pos, buffer, size);
8 n# m. {; c8 Q( { }& Z+ _3 n# C; q7 o8 {7 b
}* h- U6 J# Q j- b7 y: J
return 0;; Y( h" b5 g. X, Z$ f) M% }2 o6 U
}
0 L. b5 t# Z7 q$ R4 k/*
# q. ]) [$ D0 l+ n5 m8 p4 F: V 驅動寫
0 p, s J S; y2 J. m*/
?" _1 H# c$ e5 x0 `int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)( P* S+ d) `$ L' o. } I$ I- ?
{4 t" a. Y) c3 A# J7 g; A8 v7 o7 }
if(dev)5 e3 {. b$ L# c, @* _
{$ g# Y. V+ C8 F0 Q$ m& c
if(dev->dops->write)# B; X* ]. J; ]6 {! P, a
{7 W3 i0 D) s* [0 b0 o K
return dev->dops->write(dev, pos, buffer, size);7 y/ v; s/ \0 h( _) {/ e% d
}
/ }* U, z) J; @1 K }
9 }1 J( J- k/ N return 0;0 w4 d+ B7 }; `& W, n4 M0 O9 h9 y
}
: D$ j5 e( c ^3 k" l4 {; O/*& D& [3 B$ n/ d% N
驅動控制
9 P) P3 ^& q$ a* [- ]*/
7 n: O' T# i9 K1 E5 L U7 S: k' ^int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg)
/ _( {2 o& N d$ C/ H{
% l; B/ W4 A7 U: }/ P if(dev)
* Y3 }3 P' p8 n; G {
/ k0 s, B: ~1 a1 e+ ~, J# U4 p# U; l/ b; t if(dev->dops->control)
3 P0 F4 f. Y" i" z! K {
! B/ I' I9 ?7 w: u+ D2 O9 u return dev->dops->control(dev, cmd, arg);
! h+ X& `$ q, F }
9 m5 V2 |' j! h( D }
! Z* s5 I' M$ U" D; H; } return 0;/ c+ k! z, ]& ~" M- o/ V1 ?
}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調用。9 i& Q1 J% q% C# n1 a- R
#include "stm32f0xx.h"2 |: x( @+ a' U
#include "led.h"
# F" ^( d& `9 j2 a9 } ?5 u s h#include "cola_device.h"
/ W9 [5 j( B. M& F4 M% N3 t% }3 P#define PORT_GREEN_LED GPIOC
- a5 e9 G+ b7 \3 K. D4 h; |#define PIN_GREENLED GPIO_Pin_13
. L0 R5 E K' }" S- K( x N/* LED亮、滅、變化 */& _$ H% q& {* E3 T1 {2 T% D2 Q
#define LED_GREEN_OFF (PORT_GREEN_LED->BSRR = PIN_GREENLED)
7 Y5 @: ^" i2 s/ {2 A#define LED_GREEN_ON (PORT_GREEN_LED->BRR = PIN_GREENLED)
: H' ^5 }3 s/ ^4 @! [#define LED_GREEN_TOGGLE (PORT_GREEN_LED->ODR ^= PIN_GREENLED)( O+ z% i; Q8 L# T
static cola_device_t led_dev;- w# C2 ]- R1 D6 O7 i$ I
static void led_gpio_init(void)
' N9 m3 f y5 K, ^{$ D2 n2 M9 y; b5 H; N" |
GPIO_InitTypeDef GPIO_InitStructure;
- f0 X- U$ J) B9 n4 x& Q. t RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
5 F: m- @) i" _ GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
5 a! n7 t) s% O6 \8 r4 c GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;$ R4 r* Y' l) c3 t9 D
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
3 z0 E# |9 `- i c5 a GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
' P9 i# r# s8 d GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
: Y. ^! e5 ^0 k/ ?& U GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
; b% y# k- G, E& |+ a' k7 X6 ` LED_GREEN_OFF;5 I2 E* J1 C0 z o1 u7 |, ~% z
}
5 n, M, z# w0 D0 O9 t1 G9 g( y3 h2 Y. d' L
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
8 Q, [9 `/ u1 g3 U+ M" T; p* a{ ~, R5 K( G4 ]6 h0 R, X# _
if(LED_TOGGLE == cmd)
) r" C+ ~# ] O7 h: _2 m; a* l. M {0 v; r* k2 g5 H% v2 |, e" W7 K1 \, ^
LED_GREEN_TOGGLE;
5 l L# _* L) O. V. n4 P. Z7 j }: |4 Y# _. y' O0 P+ j, i
else
. |* `; | |3 v6 h {
. P$ ^5 ^1 C7 y$ C2 L0 p# F/ C }
5 ?% {7 i/ k4 l% L- X! ] return 1;' m$ ~. \- Q1 G
}$ a6 @! w4 v6 T1 T' @0 u7 [& A
static struct cola_device_ops ops =! z" [; _( B! Y" C& p2 Z
{
% v. O: I& S& g .control = led_ctrl,: [ ?; Z9 [1 g# J
};5 E( i/ @5 P/ s. l) d1 A5 S5 x
void led_register(void), k, d5 h9 F; f: K( ]" F' G
{
" A0 y* Z$ G; u, ~% r/ B1 [ led_gpio_init();5 o9 J% v1 C9 {6 l5 A4 h' x7 \
led_dev.dops =&ops;5 q3 e9 o, p2 \+ |9 `
led_dev.name ="led";
( O) d1 l& {5 S1 X+ i2 ], o cola_device_register(&led_dev);
6 Q' z; M% W* T( x5 _: `1 k}應用層app代碼:& H* s, A( N! [; n/ [
#include $ }# a' m4 I4 ^& J: v
#include "app.h"
7 @5 p a7 A7 y#include "config.h"
* X# Z" r: J( p, H, }1 C/ @#include "cola_device.h"
2 D7 C" h. x, L R/ j9 S& r#include "cola_os.h"
' Z# L; \! p; S& R5 C: C5 Z9 Rstatic task_t timer_500ms;& O1 o7 m7 V2 h8 M, e& E* P
static cola_device_t*app_led_dev;
/ k1 f( r" p8 R' f//led每500ms狀態(tài)改變一次! O( `5 n4 Y$ v) M0 X. o) R
static void timer_500ms_cb(uint32_t event)
5 f; O$ [- p0 ]{' r- h5 |) ?6 h& u! x
cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
$ _: Q2 ?% N6 u, a: d k}
% W7 M( B0 a2 F' O. [# z$ x$ E: L5 G; Jvoid app_init(void)8 k0 z' i0 D2 n# f2 |
{
/ R- x- `" c0 P4 B4 L* D: I9 \ app_led_dev = cola_device_find("led");* P: K; [9 }% _+ u0 D( \+ b
assert(app_led_dev);
2 _5 c3 X" d# X( s1 t/ M cola_timer_create(&timer_500ms,timer_500ms_cb);' }( p3 f4 Y$ V
cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
3 Q8 t; s( Y' c}這樣app.c文件中就不需要調用led.h頭文件了,rtt就是這樣實現的。
# C3 ^: C/ ?5 `/ i/ F% o- D四、代碼下載鏈接https://gitee.com/schuck/cola_os+ Z$ D8 [9 u6 g F/ r0 B" ^$ o
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
5 e6 N. x8 K( @% C( |/ [-END-
4 Z: G4 l! x7 o0 {1 x往期推薦:點擊圖片即可跳轉閱讀
1 _# r$ l v/ j/ u N; O 3 N( ~, z( y7 K2 V' Y/ C( k/ Y
( T/ d1 Q) _( f: e5 u
2 {: ?2 u9 U+ Z9 n 8 ?, @) Q* H2 o" v
fs2m2h1lmop6405226136.jpg (59.84 KB, 下載次數: 0)
下載附件
保存到相冊
fs2m2h1lmop6405226136.jpg
2024-8-21 13:01 上傳
7 g* ^; j, @6 C/ f" F
w+ T1 V' H: c* a+ m
嵌入式 C 語言的自我修養(yǎng)
1 s# z* C* a% b' F% @ d0 u 9 o) R9 d$ T7 N0 ~; ]/ }
) ?& U( T7 w3 e, R9 t
: t* I8 O/ d% a$ T+ g
3 Q0 G8 i& E3 |6 w3 [
eugn1hgtrcu6405226236.jpg (115.65 KB, 下載次數: 0)
下載附件
保存到相冊
eugn1hgtrcu6405226236.jpg
2024-8-21 13:01 上傳
0 e* ~" N+ Y; `$ U
2 X/ |, j. C! q9 x: N
被 char 類型的變量坑慘了!
" T7 H" [- {; J1 H8 U 1 T& B6 h; ]5 E% K
* h8 u) G6 _7 M% R- w- } 4 @1 x5 o& @. j3 y- g' u2 V
u3ekctdsamz6405226336.jpg (80.73 KB, 下載次數: 0)
下載附件
保存到相冊
u3ekctdsamz6405226336.jpg
2024-8-21 13:01 上傳
e s0 m: g6 a
; [; @7 R1 Q5 e9 {8 {0 f( a 嵌入式 C 語言知識點,動態(tài)變長數組* V4 M9 |7 D9 Q
3 b% D" C. l$ z( u' g9 { 6 M, g" L) Y! I1 R4 z
`! Y! D! I8 x6 ?) b 我是老溫,一名熱愛學習的嵌入式工程師
) S, Q% c3 T5 P2 l* J關注我,一起變得更加優(yōu)秀! |
|