|
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
. Q: @5 Q H. P" ^關(guān)注我,一起變得更加優(yōu)秀!一、前言以STM32為例,打開網(wǎng)絡(luò)上下載的例程或者是購買開發(fā)板自帶的例程,都會發(fā)現(xiàn)應(yīng)用層中會有stm32f10x.h或者stm32f10x_gpio.h,這些文件嚴(yán)格來時屬于硬件層的,如果軟件層出現(xiàn)這些文件會顯得很亂。4 Q# F& J# h5 m
使用過Linux的童鞋們肯定知道linux系統(tǒng)無法直接操作硬件層,打開linux或者rt_thread代碼會發(fā)現(xiàn)代碼中都會有device的源文件,沒錯,這就是驅(qū)動層。
1 P; Y. O( n' I. x
kgq5x1duezb6402851105.png (5.23 KB, 下載次數(shù): 0)
下載附件
保存到相冊
kgq5x1duezb6402851105.png
2024-8-20 12:05 上傳
2 }" V6 G4 Y* h+ L
二、實現(xiàn)原理原理就是將硬件操作的接口全都放到驅(qū)動鏈表上,在驅(qū)動層實現(xiàn)device的open、read、write等操作。當(dāng)然這樣做也有弊端,就是驅(qū)動find的時候需要遍歷一遍驅(qū)動鏈表,這樣會增加代碼運行時間。( Y" |3 d! `" y: V/ _2 s3 f ]
三、代碼實現(xiàn)國際慣例,寫代碼先寫頭文件。rt_thread中使用的是雙向鏈表,為了簡單在這我只用單向鏈表。有興趣的可以自行研究rt_thread. w- M& [6 S3 a/ Y! S1 i
頭文件接口:
+ a- r3 m1 B5 i2 I7 L ]" s8 |" b本次只實現(xiàn)如下接口,device_open 和device_close等剩下的接口可以自行研究。這樣就可以在應(yīng)用層中只調(diào)用如下接口可實現(xiàn):( Y+ V- i) }- ?6 a. D% f
/*
& Q: o3 a+ u. D( J- x" @3 G. K6 K 驅(qū)動注冊
7 o$ }' ?0 W5 V5 |+ Z*/# Y5 k4 }$ v6 U) L8 y1 o' j! W( _
int cola_device_register(cola_device_t *dev);3 Z7 y5 B! g+ o0 R
/*
' M1 s2 q3 t: X/ C 驅(qū)動查找
( Z, A" e! O$ D! h*/0 F" Q) {" E' \
cola_device_t *cola_device_find(const char *name);
: R6 m- B p( }. e: H/ C- V1 N/*
" _9 {2 t3 _- V) \4 ` f 驅(qū)動讀4 E% S0 M' M( M# O; N q* |2 q
*/3 W/ I: R9 F! l( e5 Q& }/ J% Z% o
int cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);
( @9 x/ n( w0 y$ O- M) i/*2 a# @5 d/ r! _
驅(qū)動寫
0 A/ j. `( j3 r*/1 m( V: ~: H0 W) ]( M
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);
2 j9 o" P* m1 v: @* g/*
" m1 d! g2 X: ~2 K/ z5 j% _ 驅(qū)動控制9 g- N8 p& O/ C$ V$ k. Z
*/7 w4 K- [4 S' g" y I
int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);;頭文件cola_device.h:
# g8 [* _" O7 f6 m#ifndef _COLA_DEVICE_H_$ ?* |( _3 B7 b' L
#define _COLA_DEVICE_H_
9 {5 Z* r/ k) B W7 G4 ^enum LED_state
; |3 {# W4 p Z1 u{" r5 C% N. q( w3 e8 J( E& f, ?
LED_OFF,; J7 n( |) |' T
LED_ON,) i4 t. t+ n' H, N6 {
LED_TOGGLE,
/ R- u6 v: M y2 y};2 v1 Y4 P6 f5 A. X0 G8 |
typedef struct cola_device cola_device_t;) O9 z8 n- e1 g
struct cola_device_ops) R2 @. d3 X/ M8 o3 r, V+ N3 n
{
) V" u( t9 Y. F5 W: S) k+ v2 ^! V int(*init)(cola_device_t*dev);2 y4 ]9 @* U1 `; ^; T) a. I `! ~
int(*open)(cola_device_t*dev,int oflag);
; e% w+ A% y0 y% `6 ^2 D int(*close)(cola_device_t*dev);
3 R1 L$ U; Y4 N0 H v int(*read)(cola_device_t*dev,int pos,void*buffer,int size);
) K6 i6 R' T" q* W2 B& o5 P4 w int(*write)(cola_device_t*dev,int pos,constvoid*buffer,int size);
1 d% {$ q- |6 R int(*control)(cola_device_t*dev,int cmd,void*args);( z" H& Z, g' o6 R6 g* r( ]! Z
};
/ ]6 L6 I3 c5 e& J' Nstruct cola_device+ F v$ w, b+ f/ j
{; T- P* q. }( P1 @4 H/ Y4 ~. [! o
const char* name;& n* D) [, ^! o* B* Z
struct cola_device_ops *dops;
: A1 B9 |. d/ H k6 O- r* Y struct cola_device *next;
! ^( j2 _+ ~7 X( g$ c};1 A/ U; A' N( t3 M" s
/*4 ~: c+ n! C. E2 F! j5 s; o
驅(qū)動注冊2 G9 h9 a& L6 J
*/
+ `/ \9 x, C, vint cola_device_register(cola_device_t *dev);
5 C( ], A- Q/ t; `5 y/*. i) s6 Q6 j, j% Y6 o, [
驅(qū)動查找
( U+ T) o b( E5 w$ i8 k! f1 }*/ Y) G- n# ?! m" w2 P
cola_device_t *cola_device_find(const char *name);
8 O, W, A5 W! k/*& E* Z5 j9 W+ h
驅(qū)動讀
( Y; q& L4 Y# z3 y$ [& n- G6 m*/
% B1 v# v6 p5 i/ c6 `! Kint cola_device_read(cola_device_t *dev, int pos, void *buffer, int size);
: } G0 c9 {# g% F/*( H& e" a9 e! g! J( d: C! V
驅(qū)動寫
7 h# |: d- p [ k/ D( |*/
. n# h4 B1 | K1 G" \int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size);/ v9 P/ d& P/ x
/*
2 b# s; H' C( B8 W: P 驅(qū)動控制
; J [! ?' q i*/% R3 G2 u( B5 U( x7 ]; S6 `& h2 u2 z
int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg);
% E5 E- U4 U6 }- ]#endif 源文件cola_device.c:7 l9 c M* W+ T5 r5 D
#include "cola_device.h"/ l* s# |5 P# q7 J& o0 ]
#include / w2 v3 n9 q! s2 m' q
#include ! p" E7 x& ^1 x! E
struct cola_device *device_list = NULL;
0 x" W+ D; |! t, W/ r! S/*
1 t! q, F6 l }8 o9 N 查找任務(wù)是否存在
, _/ R6 ]( u0 {4 R*/
( _, B+ d, E" rstatic bool cola_device_is_exists( cola_device_t *dev )3 k* ?& H- C* y. u0 [8 B
{. v9 k: w6 \, \8 x" ]8 i4 p, i
cola_device_t* cur = device_list;+ E2 q; R6 m f4 R8 p/ U
while( cur !=NULL)
. O" h, M5 \5 [8 Z {* D9 |! w4 d2 y" b% i% v0 \" j
if(strcmp(cur->name,dev->name)==0)8 H1 t6 [* y: O3 x, [. ]2 R( X
{
/ F; |' r. ]4 a5 U! Z return true;% a, j& ~4 y) q0 Q, U2 I+ _
}
# g1 r0 J- H5 ] m* M cur = cur->next;) X3 ]0 g w0 `
}# `: l- ^9 ~5 O( }# c1 \
return false;
1 s% j& g. U3 X4 k8 u}
; G3 s; m! p) |2 u2 P: {static int device_list_inster(cola_device_t *dev). ]+ f4 y( g# w- S! Y$ M
{
1 M) W$ S/ t6 ]* [) V* m4 Z/ T cola_device_t *cur = device_list;& G7 p- z7 w% {. _# S* z T& r
if(NULL== device_list)
2 j7 x+ g% M) g {
! b3 I' _7 q% [0 ` C7 K" z5 B device_list = dev;0 c3 B9 E. ^" ]# k- t
dev->next = NULL;
5 ?7 K' T) T5 Z* r' U' n& W) j0 \ [4 H }
6 y. _9 E. M" q( X9 X; j6 x4 N) t; T else
3 _) Z1 h- E9 U0 I" E3 f, F {1 T& @, J0 i: P5 S: L
while(NULL!= cur->next)
% x1 C/ n" N2 `0 @; g+ I( ] {
1 `) h$ {+ L. ?1 t U: } cur = cur->next;
- m0 k: H5 h ~ }3 R: Z+ F A: R& m) }
cur->next = dev;
0 k" d% r8 e8 _! t0 b dev->next = NULL;8 G6 }7 ]$ k' b6 b- p0 y- z2 b
}
) ^4 h3 ^6 M+ Q- M return 1;8 D: |) S% ?0 u8 n
}: k t% |) F$ p: w
/*
/ S$ m. S n0 ^9 _" N# ^4 w& \ 驅(qū)動注冊5 R# |. D$ G! ~/ G4 w0 O! q
*/" M0 a3 O& ?- N7 q
int cola_device_register(cola_device_t *dev)
/ K% ]1 e) g; p/ u{
5 _+ O. R5 _8 Z2 H+ _- y+ h: b. b if((NULL== dev)||(cola_device_is_exists(dev)))
8 y+ x4 K& E' R6 i9 V \$ n6 ^) T {6 o* R! s% a. A O
return 0;7 l2 J9 `/ [1 n( ~5 l P/ W9 @- F
}
( v ^' B+ Y9 `9 s7 y/ n9 E+ h0 x* P if((NULL== dev->name)||(NULL== dev->dops))+ P. x; M$ x8 ~6 H* b2 i3 G# }
{
* e/ G3 g: g7 a9 L( V return 0;/ p+ W8 i2 o- I2 Q, U H
}
& N/ M0 f+ ^6 h2 W* s" o return device_list_inster(dev);
5 r! W9 g; @# B6 K( t; I}
% C) Z* M% |, B6 E9 F/*' ~5 P: C( Z1 W P6 J% T
驅(qū)動查找
+ q0 ?6 o. f9 I P* S*/
+ S: h+ p8 }: k0 B* ncola_device_t *cola_device_find(const char *name)
5 T/ C2 Z8 n4 ^( }& U/ P{
& x- a/ ]) `- i3 E0 u* @ cola_device_t* cur = device_list;- n2 v0 J5 n% v5 Y) A
while( cur !=NULL)
' o. n. H& p0 |- \" h# Z {
! R8 g( F9 x r. K8 H8 f* Z' \ if(strcmp(cur->name,name)==0)
. Q% F. s0 x7 I {
7 t$ D W: j' O: F A) p return cur;9 z# o+ ~- G% N' s- @1 C
}
8 ^4 Q5 [0 T) A cur = cur->next;
" A4 q* d6 Q6 S: [ }
" a; S* c9 f/ G$ j* m$ S return NULL;
" \; C+ J& M; k}8 y5 A+ B: a& L# C) g+ q
/*
9 p; D' Z9 H4 |% X5 Y1 x4 K 驅(qū)動讀* ]( z% u& J8 {; f0 T' ?
*/
( B n) v4 X. p+ v: t) dint cola_device_read(cola_device_t *dev, int pos, void *buffer, int size)
9 |( N# P: ]* H0 I{5 I! Z( f% z) a, o. t' C' @
if(dev)! ~6 L: x( ^ H. I; ~& V; V
{
/ t/ J- d$ k) ^5 V if(dev->dops->read)
m' c5 O0 n0 U1 E {
4 G1 }- ^& L. O1 g9 E! d. e' j return dev->dops->read(dev, pos, buffer, size);: r! N9 T. ~2 ^6 a$ q) T
}' o/ s. L+ J6 i
}
9 ]1 S0 ^" M8 m, B6 U return 0;
# S( s! w' o* v1 i}
* G& ~# f, I% x2 d3 W& m/*
' |, i7 \3 n C, D 驅(qū)動寫. i# a! L2 u4 u) K$ u5 s) ~
*/$ B7 M8 F1 a$ l! J3 y
int cola_device_write(cola_device_t *dev, int pos, const void *buffer, int size)- i. f. e5 H: ?# l3 F
{ |( g) D8 ~) [4 E3 o0 X
if(dev)- w6 I& q, e7 v
{* H8 T2 n8 f1 Z
if(dev->dops->write)
) G, H, Q3 i% P' z {
0 C1 z7 ~7 p( f( k return dev->dops->write(dev, pos, buffer, size);* f* Y; T- S: N& S2 X& `8 ~
}
& t) y3 J: L+ X( I- g }
! @) o) q& Q& e6 q# H# t return 0;' I# `; W4 D/ {- U
}( q7 |2 F8 ]& D. b, i( s6 w
/** b' S& ` B* b3 h' v
驅(qū)動控制- j5 ~6 k: u. I7 {2 g' {3 d
*/9 l4 p$ m3 b# ]. v4 U/ \: o0 u. @
int cola_device_ctrl(cola_device_t *dev, int cmd, void *arg)3 \* m$ [2 @: i; g& T- S, P
{5 \7 P! j, B1 V
if(dev)- `/ w8 E) L- M T/ U1 E" l" Z0 d
{" q$ Q3 h5 F0 [6 b: ~- O0 e& g
if(dev->dops->control)4 x, S, s7 D9 o4 l5 l! Q" L: H
{% h! r6 P( Z5 [- o G; h
return dev->dops->control(dev, cmd, arg);
1 h; R" ]3 D9 Z }
" |* z3 d; }7 P& O: M }
: ]1 C6 @5 i5 [6 y" C8 v return 0;; p- }+ B0 {/ E( s( ^& w9 e, G
}硬件注冊方式:以LED為例,初始化接口void led_register(void),需要在初始化中調(diào)用。
: k- }# s, ~3 _9 d#include "stm32f0xx.h"8 ~* q/ a6 R3 d: [5 n+ |
#include "led.h"# u3 E* q( T' [7 P+ @; H
#include "cola_device.h"
# `6 l( L5 h4 s$ G) {#define PORT_GREEN_LED GPIOC
4 Q s6 O- B6 }" _#define PIN_GREENLED GPIO_Pin_13
1 p* _4 ]: D u- D( B4 c/* LED亮、滅、變化 */5 M" a$ b3 [ p& ^
#define LED_GREEN_OFF (PORT_GREEN_LED->BSRR = PIN_GREENLED), ?' A) l6 \0 j8 A0 e
#define LED_GREEN_ON (PORT_GREEN_LED->BRR = PIN_GREENLED)
3 Y! ^( ?7 a7 \% k9 [#define LED_GREEN_TOGGLE (PORT_GREEN_LED->ODR ^= PIN_GREENLED)
# ]* f+ x- Y+ U; cstatic cola_device_t led_dev;
( ^7 F" N2 ^7 e! W( J$ S5 Ostatic void led_gpio_init(void)1 y% D& C9 K( R) f) d Q2 a
{
+ s1 z, I/ y$ ?1 w. w$ P" { GPIO_InitTypeDef GPIO_InitStructure;& o- c7 [" q1 b- J
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);. M0 a: H. O. C
GPIO_InitStructure.GPIO_Pin = PIN_GREENLED;
+ J$ z: f: U* x' I* Y8 c& ] GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ l! L2 O* s9 v4 T! E a/ d) I GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;+ V3 W, U* S" S& m) b
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
! m C9 q [# N! R6 { GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;4 z" f7 P$ a6 ^" y: y8 ~
GPIO_Init(PORT_GREEN_LED,&GPIO_InitStructure);5 K3 A, e6 r ]7 F9 f: z( ?
LED_GREEN_OFF;
; f" a" ] X9 ^ v7 E' ~& D}8 I. x$ c) d* ], H' o
5 j/ h! o# n) u' y
static int led_ctrl(cola_device_t *dev, int cmd, void *args)4 Y/ K4 p! {1 W- p) v/ G
{# x; [) u; t `1 k& i4 Y
if(LED_TOGGLE == cmd)' _9 Z' b$ F- O4 M* {" Q
{
$ |; U" ~6 s* S LED_GREEN_TOGGLE;$ w2 f, u; i+ i& v
}
' a0 h% j$ g' {$ w1 D else+ r2 d5 ]& W8 c2 O' f" B% |
{
) H2 O! f j) ?( a) }' a8 L }
4 \9 n0 c; Y0 G3 D- l% a return 1;
3 }7 q1 A2 ? w2 A' ?}5 S: z7 M( K1 a. \1 V
static struct cola_device_ops ops =
" k: a; ]* l' W1 B" H) E{- H: e3 s6 T( d1 X. U/ H
.control = led_ctrl,
0 Y0 M! V) j" {, D5 f. o0 Y};
6 V/ O8 d! u! G9 Evoid led_register(void)
) y5 \8 T0 l5 M( ]4 b2 t8 G& H2 N{
, p: D/ b5 N& Z- c0 t) X led_gpio_init();
6 G( |* |5 F0 m% e3 K8 Z led_dev.dops =&ops;6 ? s8 m& G' i" y
led_dev.name ="led";
- i8 C( U" d6 ]' ? f/ j- h @ cola_device_register(&led_dev);7 |- w3 d( ]5 T1 ~
}應(yīng)用層app代碼:: h' e# {" Y4 Y% }- W* [
#include
0 @; C6 }. [/ N- b5 Z: ]#include "app.h"8 F6 T& B/ {3 q) m) t! [, n
#include "config.h"; X9 F+ [ ^# |$ `: X) x- a
#include "cola_device.h"7 ^7 }, Y% k8 v+ {( ]' r& D* W
#include "cola_os.h"2 P+ s' w2 v) ?+ V
static task_t timer_500ms;/ h9 O( ?+ f8 X, F: I( x- n
static cola_device_t*app_led_dev;
/ b' g) S% d5 h! D//led每500ms狀態(tài)改變一次# |* v. ~' \6 k) `
static void timer_500ms_cb(uint32_t event) ~, @, h d/ S( e
{
% C# G) m" }2 M: E4 a% R cola_device_ctrl(app_led_dev,LED_TOGGLE,0);
+ k4 p I$ n& b, E* U @+ ~% e/ p}
4 E; H& e1 l2 v1 [void app_init(void)- J8 [3 G& z+ _8 b% O
{
! O8 t' u) `+ h4 R3 P! ` I' D app_led_dev = cola_device_find("led");: U6 g+ M/ y" K9 n
assert(app_led_dev);
6 V. O6 s H) F0 b; |' O7 n cola_timer_create(&timer_500ms,timer_500ms_cb);+ O* t7 V+ j! K' }
cola_timer_start(&timer_500ms,TIMER_ALWAYS,500);- W! A1 i: @4 z( y0 |2 \; p( U# v/ |
}這樣app.c文件中就不需要調(diào)用led.h頭文件了,rtt就是這樣實現(xiàn)的。
2 E; ^4 s w# ?6 M四、代碼下載鏈接https://gitee.com/schuck/cola_os5 i- n* t4 K" d4 C: m/ o
原文鏈接:https://blog.csdn.net/ziqi5543/article/details/101512722
& T, K% T2 W9 I$ g( `) X' W-END-
. A% Y% l( n& Q# T+ ~往期推薦:點擊圖片即可跳轉(zhuǎn)閱讀5 {# D0 X2 O! j' Q+ {2 c0 F
+ ]' r8 C+ \; r" N; h/ B7 M - m( u6 ^( f: K7 \
- [& }4 b6 \& J' _ 6 y/ |4 U; {9 S3 i" m- z
b0beaurbwco6402851205.jpg (59.84 KB, 下載次數(shù): 0)
下載附件
保存到相冊
b0beaurbwco6402851205.jpg
2024-8-20 12:05 上傳
! P9 o i* I' u& Q9 m: q3 I' P
9 I0 {. M) S; V' }1 x 嵌入式 C 語言的自我修養(yǎng)
& B0 e# o' j- S+ S) \- g4 ?, O5 ` 9 ^+ i# U, i$ B
: Q# n' d* w( M3 `2 R 3 h" ^6 y9 n5 ?6 X6 V4 P
+ o9 T* X, {3 O* b& w) _; y
yh50034yjyz6402851305.jpg (115.65 KB, 下載次數(shù): 0)
下載附件
保存到相冊
yh50034yjyz6402851305.jpg
2024-8-20 12:05 上傳
+ e2 M9 Z, W( M) J
2 K+ Y1 W& N% j' n5 P9 Q+ H/ \) Y4 S 被 char 類型的變量坑慘了!; r5 t. G5 _" o$ O9 s8 y/ Z7 x
% H! J5 ]6 }1 ~8 I- z! i5 K
; f1 a4 e) @8 A3 K, @% U% X: h
w( a0 C# m9 o# W
wjvt2xsxnar6402851405.jpg (80.73 KB, 下載次數(shù): 0)
下載附件
保存到相冊
wjvt2xsxnar6402851405.jpg
2024-8-20 12:05 上傳
a$ n& K$ J# m% I
5 d; }" e4 I* ?' M( T
嵌入式 C 語言知識點,動態(tài)變長數(shù)組
' t0 h. m" ~6 L 5 C) w3 L# J+ z7 m0 g+ X9 N1 O6 g
) z& P& x" v+ t
/ }/ x% S. f; ~" Z 我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
4 W0 m* X( s; b( q' x& O關(guān)注我,一起變得更加優(yōu)秀! |
|