|
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師, F( M8 F+ V. t6 K
關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應(yīng)用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。
; F* q2 _* M/ @: b* g2 {: L1 u使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅(qū)動層。
. N9 [% s! M% P' a. l( A
echvysqqdf16408848026.png (5.23 KB, 下載次數(shù): 1)
下載附件
保存到相冊
echvysqqdf16408848026.png
2024-8-29 12:14 上傳
8 c3 Z9 d- ~9 j- M n二、實(shí)現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動鏈表上,在驅(qū)動層實(shí)現(xiàn)device的open、read、write等操作。當(dāng)然這樣做也有弊端,就是驅(qū)動find的時候需要遍歷一遍驅(qū)動鏈表,這樣會增加代碼運(yùn)行時間。. h9 h. ]& g$ x3 b; [) c
三、代碼實(shí)現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread
1 J0 {' t {$ i3 b2 b頭文件接口:
9 P1 W, m m8 ~. g$ I$ \" j本次只實(shí)現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實(shí)現(xiàn):4 s! R+ D# T2 X& e x) Y
/*
4 L- `; {* }3 f/ E 驅(qū)動注冊
7 K' q d8 | F*/2 z. \4 s, E! M) W% _
int cola_device_register(cola_device_t *dev);
" A% z- \, R: ?/*
! E, o: j/ M: K9 _, F; n* x 驅(qū)動查找( O' I5 I$ A0 q) {$ R; W) u* q Y
*/
5 }6 s& _6 ^6 B8 V, P4 D/ Zcola_device_t *cola_device_find(const char *name);
1 Z" g! S' a8 W/*
$ o+ L( {/ z4 @9 x 驅(qū)動讀
" _* D# z" l3 X: o# j+ G, p*/
+ j1 D8 J4 ?9 ?) vint cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);8 D m0 X4 [1 R' d# o
/*
; L4 _% r$ D* U8 Q: p 驅(qū)動寫4 D2 S$ o& z! @% h8 C+ s8 U. W
*/
" H, q0 e/ @+ j+ z7 ^- Rint cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size); C& q x" S0 Y; s0 C4 H+ N5 k
/*
6 Q$ ?6 H2 k ?) D( G. u 驅(qū)動控制, G3 Y" I+ D' i6 r
*/
2 \% i8 t2 A8 \9 t) O _' C7 u. iint cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);;頭文件cola_device.h:
5 G4 T6 l( C: w" |0 Q) H$ Q#ifndef _COLA_DEVICE_H_
! q4 O$ B8 U$ a, k#define _COLA_DEVICE_H_ j8 s* j# N0 G( ^) b
enum LED_state
" Y: d( u' S5 ?6 u2 W{6 H1 D( g) R2 m
LED_OFF,
, ]) z4 H& K! z4 J LED_ON,
$ t( R+ ? B# T9 f' g6 k! h W- H J LED_TOGGLE,
$ |1 M5 j! H; E};4 e, m' }* d8 \) T k U/ C
typedef struct cola_device cola_device_t;
+ c/ S& k3 |* V, N; Gstruct cola_device_ops
/ v; {; k2 M1 y{
9 X: m9 Z0 [. L$ J4 ?0 M2 x int(*init)(cola_device_t*dev);
5 V- H% e n, z2 ? J int(*open)(cola_device_t*dev,int oflag);
' y& E" P7 t2 o* S int(*close)(cola_device_t*dev);* w* W& {6 A3 e0 s8 D5 D& l5 C
int(*read)(cola_device_t*dev,int pos,void*buffer,int size);; X. X3 g! k7 L( x% C' v9 p
int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size); J! ?0 } Z& T, m# x, D8 e* z
int(*control)(cola_device_t*dev,int cmd,void*args);) A2 U1 t+ d v
};
+ \: }( A/ Y9 u+ rstruct cola_device
1 R. F" X, }7 @5 R{; K# R& f2 C' H% n9 V) P4 V
const char* name; i+ `7 b, y8 ~: A5 v7 z1 E) \
struct cola_device_ops *dops;. n( Y$ V. A& X4 S; q' L# { r
struct cola_device *next;: h* ]( ~. x5 h" O) o: j
};
/ w% ?, @9 c$ n3 [- j/*
" \& J5 B& y; ^- {- b0 y4 q$ h 驅(qū)動注冊
, Q. K# ]: i3 q7 S5 T*/+ o8 O# \9 q. r% j& o z6 e
int cola_device_register(cola_device_t *dev);- z6 C: s+ y7 j& u" { j& G
/*4 n% ?9 `; G% G
驅(qū)動查找
5 R8 c/ n- q) n, N% t3 l: ~) P*/
5 N2 p. d, @4 u f& R1 kcola_device_t *cola_device_find(const char *name);
* w/ m+ M- t" o- K# B( I/*; Y7 L: ^2 E8 s$ ]7 V( z3 @. x2 @
驅(qū)動讀
- U0 w9 e# G1 t7 E3 t* n' a F# X*/
8 s7 O; o7 g5 d1 Zint cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);2 j T! M; Z" y
/*4 w/ _" T4 r7 P4 T, X! _% W
驅(qū)動寫4 x* e- q2 b3 o4 [& k
*/- p- Q4 ~7 ~# L! a
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);, J# c; F. F% Z1 C# Y% w% Y) i
/*
$ \& d+ v. ?0 G/ G" Q 驅(qū)動控制: t+ }, }" E+ s
*/
" y+ z' i |- @. J( Lint cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);
5 {' T; M3 E$ K! [4 {* e2 A#endif 源文件cola_device.c:
7 D r; l, c B0 x7 S#include "cola_device.h"
2 l, d7 Q9 ?) B& J; j#include
7 q0 S4 w# k1 N" h3 z#include : K0 x9 x; T8 a3 i p: W, k
struct cola_device *device_list = NULL;7 `* P5 _7 n3 i0 J% m4 M( I. g
/*& U. U' G( r! w- C' I) {& h
查找任務(wù)是否存在
) ]; O& W4 p- s0 Q1 W8 r*/" E: b* B5 H, x8 C/ h' w
static bool cola_device_is_exists( cola_device_t *dev ): {) \( H1 Q# T+ c. n( w D! t9 e
{" Q4 O; K% A$ ~* d/ `# u
cola_device_t* cur = device_list;
) h# Y6 M" O' y* _7 F4 L6 H) U while( cur !=NULL)# W% c F( o4 [- A: u6 _
{
- P8 r6 t0 ]9 j) x s, B+ e* c if(strcmp(cur->name,dev->name)==0)& N- Q' X+ W, t
{
( i% I* d1 J. `3 y0 v4 I4 R return true;2 w% `4 w! d/ L6 {: V1 i
}$ d d2 ~ J1 l \# L
cur = cur->next;
' o& A" l) g& T3 |! f: m } P0 e" E7 G7 t
return false;
: N9 M3 \/ e( O6 d}
% V x8 u8 E2 U; D, l0 Nstatic int device_list_inster(cola_device_t *dev)
8 W4 ?: P9 d( h0 f$ z7 \{
% \+ ^9 x$ M: z( ? cola_device_t *cur = device_list;0 {( ~2 i( y* }7 R
if(NULL== device_list)7 @$ r- s: f. G! I8 A
{
" N# }6 E8 R3 n O. @. R- x$ T device_list = dev;5 Q6 d) z7 k" \9 ^9 a. q% v
dev->next = NULL;
; Z& J3 R( B) B* A: ?( n5 z }0 v$ z, J! n) C/ `8 n
else9 H7 W$ e# K* |8 p9 A0 Q3 _
{
- L% r5 M0 O1 N9 p8 Z6 v while(NULL!= cur->next). d9 ]. p5 ]# i" s1 [
{1 _4 {" }* e- E- K. ~6 b9 a
cur = cur->next;
5 w% |3 T! ^" c/ P1 G: Z }; X/ h9 h4 j; c- j, J0 c8 }
cur->next = dev;( f+ Q' ~+ [2 L: k: |4 g+ C
dev->next = NULL;
d: k, F% e/ S' a }
1 @9 j/ V* ?/ V) C i1 J return 1;( ]" W9 G# J" }; {1 I$ j
}
. Q& @ q# a4 h- _. J/*. s1 P% l) j) u8 u O
驅(qū)動注冊4 ^$ v N- X6 k; t5 I, [" Z
*/
, s5 L' b7 C" B. z. X2 Uint cola_device_register(cola_device_t *dev)
$ X- ?" ~# \0 C4 l{$ F# n8 W1 `6 V3 g* K: c6 E W
if((NULL== dev)||(cola_device_is_exists(dev)))4 T9 z+ P1 {$ R/ r( f0 Q$ t
{/ d. G" a+ G; n' d. O
return 0;0 |& d% Q8 U. d( [, k! @
}
9 ~4 Z& ?$ D: R, ]( y if((NULL== dev->name)||(NULL== dev->dops))
" I9 ^% S! D' v$ V2 \. Z9 d {
0 q* ^ I5 Y$ Q return 0;
& j# G) M9 L0 H' k( S }
, X( V1 R$ U+ N4 N7 [ return device_list_inster(dev);
/ j0 j( ~, g( x8 g3 i q}/ P( h* B7 R3 G2 R0 y" u
/*6 ^% U) F5 h6 d: U2 d
驅(qū)動查找
) H {/ [' [/ A9 D- ~3 o*/
, U" K3 { O/ i4 `% P' ?) Ocola_device_t *cola_device_find(const char *name)7 |! a4 N" k% A& K
{% w2 N0 V/ B) |' D& d4 a
cola_device_t* cur = device_list;
" j H3 F# q5 v3 o ~ while( cur !=NULL)
4 r2 \1 Q- q% n$ n {
$ ]* r& A$ P3 ]( l& s! v7 u% s# s if(strcmp(cur->name,name)==0)2 ^5 y+ v8 j; u9 Z* g" v2 z2 h5 k
{
, M! f: v. R, d3 M3 `, a8 ~ return cur;
% s2 v2 `1 P B0 E* h; q }" D0 `! F+ N; o
cur = cur->next;
q6 Q; r! q) ^# {) A1 m. |# L }
* Q/ O1 e% `3 {3 | return NULL;
" c* \5 g6 n f6 Z}6 Z: j/ x3 O p
/* d( k4 s5 j2 O- q& p
驅(qū)動讀' g9 Z; i; q% \6 G
*/; i" D5 u j7 v
int cola_device_read(cola_device_t *dev, int pos, void *buffer, int size) X# m( I/ }5 h6 `" ^
{
2 K0 `0 A+ Y) z, A2 L! z if(dev)5 v+ c) s- x: I4 Q3 r
{
8 Q6 z* B- @, ~# y# A if(dev->dops->read)
. h7 U0 T, }+ c j( |* B g, I$ _ {
* n( @ R* B: J. R' B return dev->dops->read(dev, pos, buffer, size);
( `, B7 X# { T( F }* S# g6 u/ F, d/ a+ O
}
! i8 V$ x* y+ o return 0;
. f) A# a/ n5 S}/ q" v& L2 ^5 A ~% P8 v2 W! q
/*4 d- p, v8 ?9 \* `& `
驅(qū)動寫
3 g) l0 b6 M. _9 V; h- k, j1 c*/! L$ u4 o y( d8 A6 y
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)( {' d0 T- s: y: W
{
# ]: ~0 a' w7 M. L' h3 X if(dev)% i) @% S0 J8 j. w+ ]
{
' c$ s6 R* |& f) ?9 f( \ B if(dev->dops->write)
* C8 D: w) ]. ` {% s- b6 B7 M1 M/ A( [" M6 a- {
return dev->dops->write(dev, pos, buffer, size);- `. H6 k2 o! F& j9 d
}
, ^4 R* E1 H; c5 z: o& _% x( p } t) n2 G3 [$ J7 c4 h: E% Y' r
return 0;
9 U: W3 v/ o6 S& M4 r}
8 V7 m+ n1 j* o9 w# f! e/*$ V4 D0 a; Z) H+ `1 \0 S) m
驅(qū)動控制; R& |; G1 f7 F' o, ?4 n/ H8 b* r1 V
*/
) C, M- c1 W5 w. q, N% Eint cola_device_ctrl(cola_device_t *dev, int cmd, void *arg)
/ O/ }* g, e% Q3 f! H{
4 C& k( c, ^! c# k8 z r if(dev)
0 J* z" G( F+ P( S6 e! C0 k# s {
/ h7 q$ U) p N, M# Z2 `: z7 r if(dev->dops->control), v. {4 y7 B/ |
{
% H4 F+ ^: Y& V+ O! m6 M return dev->dops->control(dev, cmd, arg);
' z( i0 ?! P# D6 g6 g }
# k3 T) c, \6 [4 ~ }
; I8 l: h% r9 H' g' ?3 H return 0;1 Y/ G/ y$ h: y+ W3 q- L$ i; y2 Y
}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。/ F0 ^& [6 a8 ]' `- I. F6 t
#include "stm32f0xx.h"3 k; g* }5 Y- e4 k* m, L
#include "led.h"
7 v2 z6 E5 `: X" k3 v#include "cola_device.h"0 x6 H3 ~! s( w+ }5 C0 X g; }5 x# m
#define PORT_GREEN_LED GPIOC 0 H' o& y6 e; V+ V0 r
#define PIN_GREENLED GPIO_Pin_13 2 _8 }0 K3 W0 A J1 F; G& t; G E
/* LED亮、滅、變化 */" f3 b& T- L+ s) q
#define LED_GREEN_OFF (PORT_GREEN_LED->BSRR = PIN_GREENLED)$ m2 h; u' m) N
#define LED_GREEN_ON (PORT_GREEN_LED->BRR = PIN_GREENLED)& M5 m; ^2 T* c5 \* P8 M. X
#define LED_GREEN_TOGGLE (PORT_GREEN_LED->ODR ^= PIN_GREENLED)" C0 ?5 O& {3 z2 ~
static cola_device_t led_dev;1 |+ L! B- W- a' f# Q, O
static void led_gpio_init(void)
4 J; I6 l4 O' H{
r/ L* H" _) B8 E' o' [' ^4 c GPIO_InitTypeDef GPIO_InitStructure;
4 `! R& W) t5 o# C1 q RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);& E! F) a4 L- R: F2 J, M
GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;2 X+ f* N1 k5 r) Y+ D
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
1 \( W3 q% S, T* F+ q8 N& w GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
* V/ p5 v1 [4 \2 z1 D GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; s, ?* m, X: \ g2 T8 r
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;* |: h `0 W+ X/ W+ T9 m; f
GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);
% M, K) K, V* v3 Y6 @ LED_GREEN_OFF;
4 \1 L. X2 B5 q& U+ c- f+ n% _}9 S6 e' K: J, O$ J+ c( b! A9 v
1 ~* V$ z7 T( f" w7 x+ x& N, H
static int led_ctrl(cola_device_t *dev, int cmd, void *args)
6 f1 Q N* h( s/ s{# V- w5 S+ Q9 }3 E8 n
if(LED_TOGGLE == cmd)
& {! i+ R% `7 y7 F- A6 S {
8 o& \$ `3 \/ q" U LED_GREEN_TOGGLE; B( P& V1 ]( E y [1 ~
}
' z' E) j+ I: \$ R else1 W0 m' {# k8 L" p' `
{
' T& W# J" g" o! @" S# d }# V4 I0 `, Z" c# u) O+ h
return 1;
: V" H$ @$ Z7 x}5 U$ n$ x5 H" r; ^- N) D; s
static struct cola_device_ops ops =
0 F! p. g/ j2 B. X{) I" p; Z' @1 U& f
.control = led_ctrl,( M3 a* @! }7 b$ {4 `7 S
};" K: `. v& ]! _% _3 a- Q
void led_register(void)
, l9 m9 R7 o6 Z' {2 c{1 D$ ~8 h( z+ x% D0 T7 K, r
led_gpio_init();. {+ y; a! J. a* |1 Q1 _; J
led_dev.dops =&ops;
& Y, i" W( _. A$ s9 J led_dev.name ="led";& W2 M! S& P2 q: f/ @/ E
cola_device_register(&led_dev);& X$ ]0 x1 E. g/ j. N6 B3 l9 r
}應(yīng)用層app代碼:: @9 [8 p0 Y' p- J1 g
#include
$ c3 [% Y" r; R- k" X#include "app.h"
$ D& i; a8 r8 p0 p* | o/ u#include "config.h" z( M3 i O6 ^& y& M# C; j
#include "cola_device.h"
6 j9 F2 {& k3 r _. F#include "cola_os.h"
$ @! ~4 ]9 W% W! f. Istatic task_t timer_500ms;( }3 |7 ~/ y$ I3 e6 }
static cola_device_t*app_led_dev;
' T' b1 U; u n5 E1 A//led每500ms狀態(tài)改變一次
/ L; M+ S0 k$ J5 J4 B2 x. xstatic void timer_500ms_cb(uint32_t event)
! S7 ~1 w8 i1 w5 C7 F( l{
. N" ?- G' l3 {8 Y: i cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
4 r% i! y" U! m8 m% G: G0 U}
; {7 Z, r& @0 O4 J a) [void app_init(void)
3 N& `; V, {+ q% C% Z{) c2 ~$ X+ ?1 ]3 l/ K, G' |
app_led_dev = cola_device_find("led");
/ R! A0 i! w, f2 ^ assert(app_led_dev);
9 x- q' i4 |5 K, c9 o6 C3 C cola_timer_create(&timer_500ms,timer_500ms_cb);2 z: H8 f" O7 g& H
cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);
! e! K# A& \& c. s6 n: J}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實(shí)現(xiàn)的。0 s5 L. ~1 g. W9 I. ^6 |; a& ]; N
四、代碼下載鏈接https://gitee.com/schuck/cola_os/ O/ K A& U! K: j0 M) }/ D+ n
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722* n- X' n/ A: c1 T% U$ M# Q
-END-! Y9 f" g" f' W
往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀
) D% h9 r4 S. |* h- x: r: }% |& z
, X8 o& n* N7 b7 Z7 C/ r1 e 3 d0 {4 ^. x2 t# I/ F5 V* F6 [" U
7 A, a# z% U- J7 r# a
, M& j3 O4 U. Z+ Y
gayih2vnbik6408848126.jpg (59.84 KB, 下載次數(shù): 1)
下載附件
保存到相冊
gayih2vnbik6408848126.jpg
2024-8-29 12:14 上傳
% S% |$ A* {# b# ^4 A7 O
2 d1 w9 j N3 M3 l/ r7 c5 J: s1 R 嵌入式 C 語言的自我修養(yǎng)+ }8 @# `) x& |- b9 r; }
, [1 [+ d% B) b( G8 \ m
, K' I' w( x4 h# X9 q9 ?
' A* T0 M3 ^ Z4 k$ |) H! d) g
' Y8 X. P9 `) q& O k! m
fybj3a4kykh6408848226.jpg (115.65 KB, 下載次數(shù): 0)
下載附件
保存到相冊
fybj3a4kykh6408848226.jpg
2024-8-29 12:14 上傳
2 J! v4 A8 f% Q0 z# m; ?
* |. v" R- t* E; v9 q: X, ~ 被 char 類型的變量坑慘了!8 Z8 L7 ], \1 D5 u
4 I% l' d" j" m, T9 _% V2 Y: w
+ z/ o, J8 r9 a; x7 h! G $ h8 i& _7 h. Y3 K- y& R6 A
b2kxjl1lw056408848326.jpg (80.73 KB, 下載次數(shù): 1)
下載附件
保存到相冊
b2kxjl1lw056408848326.jpg
2024-8-29 12:14 上傳
) K$ S% n0 ?* l" u: I. T8 h
; @4 z. a" t$ K# t8 _
嵌入式 C 語言知識點(diǎn),動態(tài)變長數(shù)組
. d) Y8 s5 g. o6 T) E% B) }3 n 2 W8 X4 X5 {" q2 I4 c. b1 i$ [
. H- L3 Y( l) u$ Q( l7 y: }; C & h8 c! a% {3 X$ b9 P. b
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師. b4 f) U! S( J: \' N0 w
關(guān)注我,一起變得更加優(yōu)秀! |
|