Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
[讨论] Device的新设计
发布于 2011-01-13 18:27:14 浏览:9597
订阅该版
当前的RT-Thread Device应该说设计得并不十分完美,有些东西交错复杂,也容易导致一个驱动设备节点内存占用过大 ``` struct rt_object parent; /**< inherit from rt_object */ enum rt_device_class_type type; /**< device */ rt_uint16_t flag, open_flag; /**< device flag and device open flag */ /* device call back */ rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size); rt_err_t (*tx_complete)(rt_device_t dev, void* buffer); /* common device interface */ rt_err_t (*init) (rt_device_t dev); rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag); rt_err_t (*close) (rt_device_t dev); rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size); rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size); rt_err_t (*control)(rt_device_t dev, rt_uint8_t cmd, void *args); #ifdef RT_USING_DEVICE_SUSPEND rt_err_t (*suspend) (rt_device_t dev); rt_err_t (*resumed) (rt_device_t dev); #endif void* user_data; /**< device private */ ``` 1. 结构体中包含了大量的指针函数。由于一个设备驱动就是一个内核对象,而内核对象只能是动态的(必须能够被修改),它将直接变成一个个内存区域,进而消耗了"大量"的内存。 2. 对于从设备支持非常弱,基本上是采用一个个从设备就是一个内核对象的方式,内存浪费也非常严重。 3. 并不见得太适合于对象化编程(因为对象类不得不从rt_device类上继承,然后相应的内核对象类内存占用进一步增加)。
查看更多
15
个回答
默认排序
按发布时间排序
bernard
2011-01-13
这家伙很懒,什么也没写!
新设计主要还是围绕着如何更精简,更可维护化着手(但也有可能导致一些代码阅读上的变扭,这个尽量依赖于面向对象化的编程模式消除掉) ``` /* 新的结构定义 */ struct rt_device { struct rt_object parent; rt_uint8_t type; rt_uint8_t flags; rt_uint16_t item_count; const void* items; const struct rt_device_ops *vops; const void* user_data; }; ``` 新的设计中,包括: 1. 把原来的堆积式的函数指针变成函数指针结构,使得可以把一个设备驱动的函数操作集变成了常量,直接放置于flash中。 2. 添加items域,以指向从设备分片,即从设备与主设备共享大多数的数据域,仅在一些小的细节上有出入,并且也可逐步转换成静态的常量数据不再占用多余的内存。
3.
4. 更加不同类别的设备驱动,定义一些公共的方法,使得以后编写驱动时仅需要实现更小的方法集合。
bernard
2011-01-13
这家伙很懒,什么也没写!
缺点:将造成现有所有设备驱动的更改! 优点:内存占用会更小,对象化程度也会更高。
totest
2011-01-13
这家伙很懒,什么也没写!
好,支持bernard,能比之前的模式省内存当然是最好的了。
aozima
2011-01-13
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
留名再细看,一块硬盘是一个主设备.N个分区是N个附属的从设备,这样做应该更方便?
mbbill
2011-01-14
这家伙很懒,什么也没写!
这么看的话每个对象能节省下来几十个字节的内存。不过改动工作量很大,或许可以再仔细想一些革命性的改进再动手
bernard
2011-01-14
这家伙很懒,什么也没写!
>这么看的话每个对象能节省下来几十个字节的内存。不过改动工作量很大,或许可以再仔细想一些革命性的改进再动手 --- 是的,发这个帖子的意义也正在于此,大家多讨论讨论。 我觉得比较有意义的是,可以写一些公共的类,例如stream_device,这个针对于简单的串口,当要实现具体的串口设备时,仅给出读和写基本上就可以了,而不需要类似现在要实现全部的标准5个接口。
lgnq
2011-01-14
这家伙很懒,什么也没写!
很期待 不知道这次关于device的新设计,在rtconfig.h中是否还会有RT_USING_DEVICE的配置
bernard
2011-01-14
这家伙很懒,什么也没写!
暂时先保留吧,并把原来RT_USING_DEVICE缺少的宏也添加上。 不过如果系统中没有那个面向极限型的活跃分支,支持这个意义也不是太大。
bernard
2011-03-29
这家伙很懒,什么也没写!
大家多讨论讨论,特别是现在已经采用RT-Thread写过设备驱动的。如果需要修改,那么早改的麻烦比晚改的麻烦小很多。
onelife
2011-03-31
这家伙很懒,什么也没写!
>新设计主要还是围绕着如何更精简,更可维护化着手(但也有可能导致一些代码阅读上的变扭,这个尽量依赖于面向对象化的编程模式消除掉) > > > >``` > >/* 新的结构定义 */ >struct rt_device >{ > struct rt_object parent; > > rt_uint8_t type; > rt_uint8_t flags; > > rt_uint16_t item_count; > const void* items; > > const struct rt_device_ops *vops; > const void* user_data; >}; > >``` > > > >新的设计中,包括: >1. 把原来的堆积式的函数指针变成函数指针结构,使得可以把一个设备驱动的函数操作集变成了常量,直接放置于flash中。 >2. 添加items域,以指向从设备分片,即从设备与主设备共享大多数的数据域,仅在一些小的细节上有出入,并且也可逐步转换成静态的常量数据不再占用多余的内存。
>3.
>4. 更加不同类别的设备驱动,定义一些公共的方法,使得以后编写驱动时仅需要实现更小的方法集合。 --- 俺很赞成这样的修改。俺以为对于嵌入式系统,尤其是 RTOS ,节省内存是宗旨、是要贯彻在每一段代码里的。即使要和运行速度进行权衡,节省内存也常常胜出。 若是以节省内存为目的,俺觉得常量应集合在结构体中存储于 Flash ,程序在内存中使用指针来存取。然后还应尽量减少指针的数量。 俺尝试调整了一下楼主的代码,以抛砖引玉。请批评指正。 ``` struct rt_device { struct rt_object parent; rt_uint8_t type; rt_uint8_t flags; rt_uint16_t item_count; /* 缩编指针 */ const struct rt_device_block *block; }; /* 常量集合 */ struct rt_device_block { const void *items; const struct rt_device_ops *vops; const void *user_data; }; /* 使用此结构可减少现有代码的改动 例如: test.close(dev) 需改为 test.block->vops->close(dev) */ struct rt_device_ops { /* device call back */ rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size); rt_err_t (*tx_complete)(rt_device_t dev, void* buffer); /* common device interface */ rt_err_t (*init) (rt_device_t dev); rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag); rt_err_t (*close) (rt_device_t dev); rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size); rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size); rt_err_t (*control)(rt_device_t dev, rt_uint8_t cmd, void *args); #ifdef RT_USING_DEVICE_SUSPEND rt_err_t (*suspend) (rt_device_t dev); rt_err_t (*resumed) (rt_device_t dev); #endif /* 自定义函数(集合) */ void *rt_user_ops; }; ``` 另外一种方法,可使 device 的操作函数更具弹性。 ``` struct rt_device { struct rt_object parent; rt_uint8_t type; rt_uint8_t flags; rt_uint16_t item_count; /* 缩编指针 */ const struct rt_device_block *block; }; /* 常量集合 */ struct rt_device_block { const void *items; /* 操作函数表 */ const void *vops; const void *user_data; }; /* 类型定义,以 close 为例 */ typedef rt_err_t (*vops_close)(rt_device_t dev); /* 偏移量定义,以 close 为例 */ #define vops_index_close (4) /* 例子 */ rt_err_t test_indicate(rt_device_t dev, rt_size_t size) { } rt_err_t test_tx_complete(rt_device_t dev, void* buffer) { } rt_err_t test_init(rt_device_t dev) { } rt_err_t test_open(rt_device_t dev, rt_uint16_t oflag) { } rt_err_t test_close(rt_device_t dev) { } rt_size_t test_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { } rt_size_t test_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { } rt_err_t test_control(rt_device_t dev, rt_uint8_t cmd, void *args) { } rt_err_t test_suspend(rt_device_t dev) { } rt_err_t test_resumed (rt_device_t dev) { } rt_err_t test_user1 (rt_device_t dev) { } rt_err_t test_user2 (rt_device_t dev) { } /* 操作函数表实现 */ void *vops[] = { test_indicate, test_tx_complete, test_init, test_open, test_close, test_read, test_write, test_control, test_user1, test_user2 RT_NULL /* 结束标志 */ }; /* 常量集合实例 */ const struct rt_device_block test_block3 = { RT_NULL, &vops, RT_NULL }; /* device 实例 */ struct rt_device test3 = { 0, 0, 0, &test_block3 }; /* 使用函数, 同样可减少现有代码的改动 */ ((vops_close)(((void**)(test3.block->vops))[vops_index_close]))(dev); ``` 其他: item_count 是否可作为 reference counter?初始为1;为0时,kernel 可释放该 device object 所占用的内存。
撰写答案
登录
注册新账号
关注者
0
被浏览
9.6k
关于作者
bernard
这家伙很懒,什么也没写!
提问
414
回答
5941
被采纳
76
关注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
freemodbus主机在freertos的适配,参考rtthread例程
2
开源共生 商业共赢 | RT-Thread 2024开发者大会议程正式发布!
3
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
4
RT-Thread EtherKit开源以太网硬件正式发布
5
还在担心bsp不好维护吗?快使用yml管理主线bsp
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部