Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
【STM32】每天了解RTT多一点(1)——rt_device_find函数浅析
发布于 2018-01-11 12:08:52 浏览:6358
订阅该版
* 本帖最后由 黄侃 于 2018-5-9 20:15 编辑 * rt_device_find函数再RTT系统中,用于查找当前设备是否在系统设备注册表里,如果是返回设备指针,否则返回NULL。这个函数可能是我们打开RTT设备驱动层大门第一个面对的重要函数了。函数本身语句不多但是可以看到RTT设备驱动层的设计思路和框架。 首先函数参数是一个字符串,即设备的名称,例如“UART1”之类,这个参数是查找对象,即在当前系统的设备列表里查找是否注册了某个设备,如果是,则函数返回设备对象的指针,也可以称之为设备描述句柄。如果没有查找到,则返回NULL RTT的设备列表,不是一个简单的数组或者链表,使用一个for循环查询就得到结果。 首先,RTT里有一个全局大数组,定义方式为: ```struct rt_object_information rt_object_container[RT_Object_Class_Unknown] ``` 这个数组可以称为object容器,设备列表,是这个容器里的一个成员。 ![ob容器.jpg](/uploads/201801/11/114150c6421vv1qoz1z2qq.jpg) 容器中一共有多少个成员,取决于RT_Object_Class_Unknown的值,这个值在rtdef.h里通过一个枚举变量来确定。 ```enum rt_object_class_type { RT_Object_Class_Thread = 0, /**< The object is a thread. */ #ifdef RT_USING_SEMAPHORE RT_Object_Class_Semaphore, /**< The object is a semaphore. */ #endif #ifdef RT_USING_MUTEX RT_Object_Class_Mutex, /**< The object is a mutex. */ #endif #ifdef RT_USING_EVENT RT_Object_Class_Event, /**< The object is a event. */ #endif #ifdef RT_USING_MAILBOX RT_Object_Class_MailBox, /**< The object is a mail box. */ #endif #ifdef RT_USING_MESSAGEQUEUE RT_Object_Class_MessageQueue, /**< The object is a message queue. */ #endif #ifdef RT_USING_MEMHEAP RT_Object_Class_MemHeap, /**< The object is a memory heap */ #endif #ifdef RT_USING_MEMPOOL RT_Object_Class_MemPool, /**< The object is a memory pool. */ #endif #ifdef RT_USING_DEVICE RT_Object_Class_Device, /**< The object is a device */ #endif RT_Object_Class_Timer, /**< The object is a timer. */ #ifdef RT_USING_MODULE RT_Object_Class_Module, /**< The object is a module. */ #endif RT_Object_Class_Unknown, /**< The object is unknown. */ RT_Object_Class_Static = 0x80 /**< The object is a static object. */ };``` 可以看到RT_Object_Class_Unknown顺序排到倒数第二个去了。加入我们将来需要扩展这个object容器,则可以把新增的对象列表放在这个枚举列表里,并且放在RT_Object_Class_Unknown之前。不过需要注意容器中的列表数量可能不能超过0x80,因为我也不知道RT_Object_Class_Static的作用,可能后面会慢慢遇到。 因此RTT查找设备首先就是在Object容器里找到设备列表指针,然后再进行查找。由于Object采用的数组方式,因此查找非常简单: ```information = &rt_object_container[RT_Object_Class_Device];``` 简直瞬间定位。 设备列表的指针找到了,但是我们打开information一看,啥也没有: ```struct rt_object_information *information; struct rt_object_information { enum rt_object_class_type type; rt_list_t object_list; rt_size_t object_size; };``` 仅仅有一个类型用于区别object类型,和一个链表指针。我们并没有看到每个设备的实体在哪里。如果采用比较容易理解做法,建立一个数据链表,链表成员为每一个设备对象即可。 这么做的目的在于,刚才我们看到在Object容器中,有很多个列表的存在,例如设备列表,信号列表,事件列表等等,如果对每个列表都建立一个链表,会出现由于数据类型不同而导致大量冗余代码。 举个例子: 如果我们的程序要将一组int变量和一组char变量组织成链表。那么对于int链表的表示方式为: ```struct list_int { int data_t; struct list_int *next; } ```char的表示方式为 ```struct list_char { char data_t; struct list_char *next; }``` 那么每个list的操作,比如创建,删除,插入函数,都得写2个,分别针对于int和char。因为C语言不能根据输入参数的类型实现不同的调用。 为了避免这种情况,可以采用如下方式来完成泛型,首先定义一个链表结构: ```struct list { struct list *next; }``` 然后在数据对象中包含这个链表对象struct ob_int ```{ list node; int data_t; }``` 然后编写创建,删除,插入函数,这些方法函数是针对struct list的而个跟data_t的类型无关,然后每个Node都相当于是ob_int对象的首地址,通过node地址就得到了ob_int的地址。 RTT采用类似的做法,只不过使用的是双向侵入式链表 ```int data_t; list node; }``` 使用了一个经典宏,通过node地址,能够得到ob_int的地址。 ```#define rt_list_entry(node, type, member) \ ((ob_int*)((char *)(node) - (unsigned long)(&((type *)0)->member)))``` 根据member(在结构体中的成员),结构体类型type,node(链表成员节点地址)计算出数据对象的地址。 带入参数则为: ```((type *)((char *)(node) - (unsigned long)(&((ob_int*)0)->node)))``` (&((ob_int*)0)->node)得到了node在ob_int结构体中的偏移量,地址0仅仅取址而不赋值是不报错的,通过unsigned long转换成32位地址的值,在使用node的地址减去这个偏移量的值,这里(char*)是必须的,避免成为偏移量*sizeof(node),最后转换为ob_int类型得到地址值。 那么到现在我们就明白了,RTT的设备在一个双向循环链表里是如何查找检索的了。
查看更多
2
个回答
默认排序
按发布时间排序
moss
2018-01-11
这家伙很懒,什么也没写!
学习学习 就是能不能改一下排版
andychen
2018-01-12
这家伙很懒,什么也没写!
Good,楼主继续连载
撰写答案
登录
注册新账号
关注者
1
被浏览
6.4k
关于作者
黄侃
这家伙很懒,什么也没写!
提问
17
回答
37
被采纳
0
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
rt-thread使用cherryusb实现虚拟串口
2
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
3
《原子操作:程序世界里的“最小魔法单位”解析》
4
《C++设计模式:重塑游戏角色系统类结构的秘籍》
5
rt-thread官方usb驱动之虚拟串口
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
6
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部