您好, 登录| 注册|
论坛导航
您好, 登录| 注册|
子站:
论坛首页    单片机MCU/嵌入式
  •  发帖
  • 收藏

【Rt-thread学习记】:设备层框架设计之故事续集。。。
阅读: 2365 |  回复: 25 楼层直达

2019/08/20 09:03:41
1
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

QQ截图20160321155901 内容精选】管理员精心选择的优质内容 快来讨论吧


筒子们,我胡汉三又回来啦,帖子停更了一段时间,主要是忙忙忙。。。忙着搬砖(悲催的是却不挣钱。。。),好不容易装了几车砖,地主总算暂时的放过我了,可以歇口气了,帖子更了一半被打断的感觉,好像梦见女神,历经千辛万苦要打kiss了,闹钟响了,但是梦想终归还是要有的,不知道还有没有看官老爷还在,管不了那么多了,我要关了闹钟,继续去追我的女神了。。。

接下来,还是改一下帖子的风格,技术的细节太多,痛苦总是太多,忘了女神的美,还是听我慢慢的讲故事吧。

话说在遥远的远古时代,有两个的程序猿小A和小B,接下来我们称他为猿小A 和 猿小B吧。。。故事即将开始。。。

标签 STM32 MCU ARM C语言
2019/08/20 09:41:48
2
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

故事开篇:

              这里是一个远古荒凉的小岛,但是电子产业却异常的火热,人们除了辛苦的劳作,最大的乐趣就是拥有各种各种电子设备,这里就要杜撰一下了,猿小A和猿小B原本来自一个宗派,电子研发门,这是个非常高端的机构,但是每年培养出的人才却是比较少,而来到这个小岛上攻城狮就只有他们俩了。

                  平淡的生活就这样开始了,隔壁老张打渔归来,大中午的发现空调低压压力老是在报警,重启了十几次也不行,这么热的天谁愿意来给修空调啊,但是没空调那是要熟的节奏,于是老张来喊猿小A ,小A 帮我改改程序,把那该死的压力报警去掉,我要热死了,于是小A默默的收拾了一下电脑,工具就随老张出门了,小B却在一旁摇摇头。。。

            话说,小A和小B来这个小岛已经好多年了,小A为人老实,想法也少的出奇,可以说是有求必应,小B却截然不同,这么多年邻里百家的各种需求和问题,让小B觉得搬砖生涯苦不堪言,他总是在不断的思考一个问题,程序的世界是不是真的应该是这样呢。。。




        

          


            

2019/08/20 09:45:15
3
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

幺蛾子比较多的猿小B找到小A 问:干了这么多年程序猿,你觉得程序的世界应该是怎样的。

      

  A:在宗门里,宗主和我讲:

             程序的世界就是一条一条的语句,一条接着一条的执行,而我们的意义就在于,把人们的需求变成各种各种的顺序表,当他们有需要的时候,我们就得给他们去改一下这个顺序表。


2019/08/20 09:49:39
4
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

B问:可是你有没有想过,我们每天辛劳的搬砖,改着各种各样的需求,反而人们的需求越来越多,我们要改的东西也越来越多,我们就俩人,铁打的也扛不住这么下去,能不能把他们的需求汇总一下,把里面共同的部分提取出来,变化的部分单独编写,这样虽然需求多了,但是万变不离其宗 ,我们的工作可就简单了。

           A问:可是那该怎么做呢,我只会搬砖啊。。。

           B陷入了沉思。。。

           有一天下着大雨,小B兴高采烈的跑到小A家里来讲,他想到解决一类需求的法子,例如今天想要加个U盘,明天想换个便宜的flash,我们干脆做个框架出来,把每一类设备相同的部分抽象出来,不同的部分作为真正需求去更改,这不就行了。

          一幅图片在小B的脑海里缓缓展开。。。

2019/08/20 10:13:28
5
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

       小B异常兴奋的把脑子里的画面用笔画了出来,拿给小A看。

        小A却一脸懵逼的看了半天道:大哥,我这智商有限,不要总拿这些PPT来忽悠我好不好,真的看不懂。

       小B也很无奈,心里想,要不是这个岛上只有你还能看懂点东西,我才不会找你一起分享我的想法呢,无奈归无奈,小B开始尝试用小A能够理解的话来给他解释,道: 首先,你讲的都没有错,程序就是一条一条执行的语句,但是我相信对于函数应用也很熟练了,通过函数封装语句的方式,是不是比汇编的时代好过多了。。。

        小A点点头。。。

        小B继续讲到:其实你潜意识里面理解了封装最大的意义,却没有意识到,那现在我给你画的图,就是函数————函数之间的封装,哪怕用函数直接调用的方式,要驱动一个设备正常工作,相应要记住或者编写的函数也是非常多吧?

        小A继续点点头。。。

        那我现在告诉你,我定义六个函数,你只需要记住会用,那么通过他们你就能找到一想要的任何一个底层函数。。。类似这样子。。。

2019/08/20 10:22:45
6
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

       小A一脸懵逼的问道:通过6个函数就能找得到任何一种设备的真正的驱动函数,这个怎么可能呢?

       小B开始了自己的演讲:通过6个函数找到任何一种设备的驱动程序并不难,可以通过参数的方式实现嘛,小笨蛋,难得是要把驱动程序全部都分类分名字管理起来,同时给你的6个函数提供接口,这就需要引入设备驱动框架的伟大概念了,通过注册的方式将驱动程序加入到驱动框架中,然后通过设备驱动框架的接口进行设备的操作,懂了吧?

      小A还是依旧一脸懵逼。。。

      小B讲:你先不用理解,只要会用就可以了,后面以你的智商绝对可以看懂我的伟大理念,放心吧。

       小A点点头:好吧,那要怎样做呢,你还是给我举个例子吧,半个篇幅都是PPT,以后看着这些图,我也搬不了砖啊。。。

      小B满脑子黑线,还真要送佛送到西啊 。。。

2019/08/20 15:00:40
7
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

         猿小B祭出珍藏多年的开发板,对小A讲,接下来让我带你嗨翻全场。

         小A:都这么牛叉了 你能不能不玩这么easy的开发板。。。,要不还是讲PPT吧。。。

        猿小B:请忽略这些不重要的细节。。。让我带你遨游RT-thread,设备层。。。哈哈哈,小A记住了,Linux的核心是shell,RTT的核心是finsh,原理上两者是一个玩意儿,他不win老大,图形化的输出,所以你要学会和他沟通的语言,凭你的天赋 自学就OK了 。。。

       




2019/08/20 15:03:03
8
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

接下来需要检查一下工程连接仿真是否正常,确保板子能找到仿真器(不然怎么玩):


2019/08/20 15:06:09
9
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

在工程中,我们采用uart1作为finsh连接的端口,这里需要检查一下开发板是否能正常通过串口连接到电脑终端,以及正确的配置CRT参数:

2019/08/20 15:19:45
10
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长
确保串口配置没有问题的情况下,打开串口连接,并通过jlink烧录RTT源码,等待RTT启动:

2019/08/20 15:34:17
11
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

     猿小A:这玩意儿搞起来是不是有些费劲啊,一顿操作猛如虎,一看空荡有如二百五,你整个空main来忽悠我。。。。


    猿小B:我还没操作完你就打断我。。。。RTT有个很好玩的地方,程序可以不放在main中一样可以执行:

来我给你刷新下三观。。。

    猿小A:。。。

    猿小B:核心在这里,这个函数并没有被放入main,但一样可以执行。。。两个字,安排。。。




2019/08/20 15:42:02
12
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小B:这里无法给你延时视频,其实通过按键,改变了LED的输出,同时通过finsh终端输出相应的信息,到目前为止其实有一点很神奇,我基本上没有写任何代码,就完成了一个简单功能的实现,真正应用时,只需要讲案例改为线程的方式就可以正常运行了。

猿小A:amazing。。。

2019/08/20 15:56:15
13
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小A :可是到目前为止都没见你进行过任何软件的配置,明显是拿一个现成的工程的演示。

猿小B: 这都被你发现了,哈哈,接下来看一下如何配置改功能的,这里只讲和例子相关的pin的配置,系统的配置自学哈。

猿小A:。。。

这里主要用到工具ENV进行工程的裁剪,GIT远程代码更新下载,RTT有很多第三方源码是被托管在服务器上的。

先看一下ENV的menuconfig功能:


2019/08/20 16:33:54
14
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小A : 接下来请开始你的SHOW TIME...

猿小B : 。。。好吧。。。

首选要选择芯片的型号,这个是必须要配置的,likethis:

默认GPIO功能是开启的:

打开软件包,加载相应的sample软件包:

2019/08/21 08:19:58
15
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小B:万事俱备,只差scons 生成并变异整个工程,这里可以选择MDK或者IAR看使用习惯了。

猿小A: 从头到尾你讲了一个demo,居然要如此复杂。。。

猿小B:虽然讲的是demo,但是后面开发项目你需要用相同的步骤流程,不要老想着demo。。。

2019/08/21 09:10:16
16
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

            猿小B:接下来启动最核心的部分,设备驱动框架分析,先从第一个部分开始,那就是pin设备,MCU都有的设备,STM32俗称GPIO,全称就不展开了,这里记住IO设备管理器给APP层提供的6个接口驱动函数:

            rt_pin_mode()        //设置引脚模式

            rt_pin_write()         //设置引脚电平

            rt_pin_read()          //读取引脚电平

            rt_pin_attach_irq()  //绑定引脚中断回调函数

            rt_pin_irq_enable()  //使能引脚中断

            rt_pin_detach_irq() //脱离引脚中断回调函数

引脚在使用的时候 ,需要提供引脚编号,RTT有个很逆天的地方,内部做了一个引脚号编码表,就是将你能看到的MCU腿的硬件编号对应到了相应的引脚上,例如原来你写程序时用到2号脚,但是真正对2号的初始化,时根据GPIO的定义来,例如PA2,但现在不用了,输入引脚编号,码表会自动找到对应的引脚。你需要知道的就是硬件的引脚编号:


猿小B:括号内的42就是我们需要的,不用再关注那是PA9还是XXX...

猿小A : 这个我喜欢。。。


2019/08/21 09:26:11
17
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

        猿小B:接下来我们来看一下这六个接口的内部实现,首先先看一下他在哪个文件中定义,这对理解设备管理框架的层的概念很有帮助。。。

                  

这里的重点是 _hw_pin.ops,而这个对象的赋值居然在register中,这就引出了 设备驱动程序到设备管理框架的注册机制了。

        

                   

2019/08/21 09:46:28
18
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

        猿小A : 有一点明朗了,也就是说APP通过设备驱动框架使用之前,必须先将设备驱动注册到设备驱动框架之中吧?那在哪里register的呢?

        猿小B : 你上道挺快嘛?看来功底不差,你所说的都是对的,接下来我们来看下,这个register函数在哪里调用,这里面有一个最大的关键点,后面再说。。。

        猿小A : 又卖关子。。。

        真正的register来自于这里:

2019/08/21 09:55:50
19
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小A : 有点明白了,也就是register在真正的设备驱动程序中进行了注册,将设备驱动程序与设备管理框架真正的联系了起来,从应用开发的角度整个过程分为三层:   APP层:main.c

         设备驱动管理框架层:/DeviceDrivers/pin.c

         设备驱动层:/Drivers/drv_gpio.c

整体的构造还是蛮新奇的。。。

猿小B :不错嘛,省的我多费口舌了,你居然全看明白了,那么我要说的是,真正从我们攻城狮开发的角度上,设备管理层,设备驱动层都是现成的不需要我们进行开发,最关键的是register行为是程序自动加载的不需要我们手动注册,从头到尾对设备的操作只需要关注那六个接口函数就OK了,是不是很神奇,哈哈。。。

猿小A : 你指的是这里吧,INIT_BOARD_EXPORT(rt_hw_pin_init);

猿小B 目瞪口呆:这你也懂。。。。

猿小A : 我就这句看不懂,想必你说的不需要手动注册的实现在这里,我猜。。。

猿小B ,吐血。。。

2019/08/21 10:15:37
20
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小B : 你不要把重点放在实现的原理上, 而是要把精力放在应用上,这才是攻城狮的核心。。。

猿小A : 说实话这种应用方式太简单了,基本看一遍再照葫芦画个瓢就会了,总得给自己找点事情做,不然怎么听你长篇阔论的。

猿小B : 。。。算了不和你一般见识了,既然是设备应用的主题,还是回到主题上把那六个API仔细讲解下,就收尾吧。

1.设置引脚模式: void rt_pin_mode(rt_base_t pin,rt_base_t mode);

参数:                                                    描述:

pin                                                          引脚编号

mode                                                      引脚工作模式

#define PIN_MODE_OUTPUT          0X00        /*输出*/

#define PIN_MODE_INPUT             0X01        /*输入*/

#define PIN_MODE_PULLUP           0X02        /*上拉输入*/

#define PIN_MODE_PULLDOWN      0X03        /*下拉输入*/

#define PIN_MODE_OUTPU_OD      0X04        /*开漏输出*/

2.设置引脚电平: void rt_pin_write(rt_base_t pin,rt_base_t value);

参数:                                                      描述:

pin                                                            引脚编号

value                                                         电平逻辑值,可取2种宏定义值之一;PIN_LOW低电平,PIN_HIGH高电平;

3.读取引脚电平:int rt_pin_read(rt_base_t pin);

参数:                                                       描述:

pin                                                             引脚编号

返回                                                            ------------

PIN_LOW                                                    低电平

PIN_HIGH                                                    高电平

还有仨放到下一个帖子,有时候长了也容易发布了,那就杯具了。。。

2019/08/21 10:36:35
21
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小B:继续讲完剩下的三个API

4.绑定引脚中断回调函数:rt_err_t rt_pin_attach_irq(rt_int32_t pin,rt_uint32_t mode,

                                                                            void(*hdr)(void*args),void *args);

参数:                                                 描述

pin                                                      引脚编号

mode                                                  中断触发模式

hdr                                                     中断回调函数,用户需要自行定义这个函数

args                                                     中断回调函数的参数,不需要时设置为RT_NULL

返回                                                    ——————————

RT_EOK                                               绑定成功

错误码                                                  绑定失败

——————————————————————————

mode选择:

#define PIN_IRQ_MODE_RISING                0X00/*上升沿触发*/

#define PIN_IRQ_MODE_FALLING              0X01/*下降沿触发*/

#define PIN_IRQ_MODE_RISING_FALLING   0X02/*上下边沿触发*/

#define PIN_IRQ_MODE_HIGH_LEVEL         0X03/*高电平触发*/

#define PIN_IRQ_MODE_LOW_LEVEL         0X04/*低电平触发*/

5.引脚终端使能:rt_err_t rt_pin_irq_enable(rt_base_t pin,rt_uint32_t enabled);

参数:                                                  描述:

pin                                                        引脚编号

enabled                                                 状态,PIN_IRQ_ENABLE(开启) ,PIN_IRQ_ENABLE(关闭)

返回                                                     ——————————————————————

RT_EOK                                                使能成功

错误码                                                  使能失败

6.脱离引脚中断回调函数: rt_err_t rt_pin_detach_irq(rt_int32_t pin);

参数:                                                    描述:

pin                                                          引脚编号

返回                                                        ——————————————

RT_EOK                                                  脱离成功

错误码                                                    脱离失败

猿小B:到这里API介绍全部完毕,完全手打我再加深一下印象,这里有一点要注意,在RTT中程序的执行只有两种上下文环境,一种是中断,一种是线程,这里并没有出现任何线程相关的内容,所以中断回调函数应该是在中断上下文中,喜欢delay的筒子们注意了。

猿小A:我说你一张图能搞定的非要手打不嫌累呢。。。不过关于上下文环境是个值得深思的问题。

猿小B:。。。

2019/08/21 10:45:19
22
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长

猿小B:到这里基本我想表达的都讲完了,怎么样,你有没有什么想法,小A同学。

猿小A : 首先同学的称呼是不对的,叫A总好了,你的想法和整个构架说实话还是很给我震撼的,尤其是在多对多映射的方式,通过底层注册的方式去实现,我还是蛮惊喜的,又学到了一些知识,后面我可以采用这种方式自己开发一下驱动程序。这种开发方式还是蛮新颖的,我觉得后面我考虑试一下。

猿小B : 让你理解应用,你却去搞原理,这种项目可是付费的,我费尽千心万苦研究的,你一句话看懂了就学会了,要赔钱。。。

猿小A : 好啦,不要这么小气,中午请你吃个鸡腿好了。。。

猿小B : emmm。。。这还差不多,哈哈,这篇就到这里吧,下一篇看看讲讲的别外设,不要再透过应用,研究原理了,这么下去我讲的都试着心惊胆战的。。。还没做好的蛋糕,你却拿去开店了,多伤人。。。

猿小A : 我。。。我尽量。。嘿嘿。。。sayonara。。。

2019/08/21 11:04:09
23
kfjy2
电源币:309 | 积分:0 主题帖:1 | 回复帖:52
LV4
连长
强势占楼
2019/08/21 11:06:46
24
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长
欢迎欢迎。。。
2019/08/21 14:22:15
25
jlh213
电源币:3674 | 积分:21 主题帖:7 | 回复帖:201
LV5
营长
尽管你写的不错,可是我依旧一脸懵B~~不过,顶你!
2019/08/21 15:40:31
26
s453208[版主]
电源币:540 | 积分:104 主题帖:48 | 回复帖:161
LV7
旅长
摸摸大
客服热线
服务时间:周一至周五9:00-18:00
微信关注
免费技术研讨会
获取一手干货分享

互联网违法不良信息举报

Reporting Internet Illegal and Bad Information
editor@netbroad.com
400-003-2006