Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
block
设备驱动
RT Thread 块设备注册
发布于 2025-06-23 13:49:45 浏览:59
订阅该版
[tocm] # RT Thread 块设备注册 关于块设备的注册时方法和注意事项,分析多个实例说明块设备注册的必要信息 [RT-Thread--emmc 块设备对接及文件系统挂载_rtthread emmc-CSDN博客](https://blog.csdn.net/tyustli/article/details/123686580?spm=1001.2014.3001.5506) [文章详情](https://blog.csdn.net/u010261063/article/details/148843801?sharetype=blogdetail&sharerId=148843801&sharerefer=PC&sharesource=u010261063&spm=1011.2480.3001.8118) ## 块设备信息结构体 该结构体 [rt_device_blk_geometry](javascript:void(0)) 的定义如下: ``` cstruct rt_device_blk_geometry { rt_uint64_t sector_count; /**< count of sectors */ rt_uint32_t bytes_per_sector; /**< number of bytes per sector */ rt_uint32_t block_size; /**< number of bytes to erase one block */ }; ``` ### 成员详解 #### [sector_count](javascript:void(0)) - **类型**: `rt_uint64_t` - **描述**: 表示块设备中的**扇区总数**。 - **作用**: 文件系统需要知道总的扇区数量来分配空间和管理存储内容。例如,如果一个 SD 卡有 1024 个扇区,这个值就会是 1024。 - 应用场景 : - 文件系统初始化时使用此字段计算总容量。 - 存储设备的分区管理依赖此字段。 #### [bytes_per_sector](javascript:void(0)) - **类型**: `rt_uint32_t` - **描述**: 表示每个**扇区的字节数**。 - **作用**: 块设备的基本读写单位通常是扇区,这个字段告诉系统每次读写操作的最小数据量。常见的扇区大小是 512 字节。 - 应用场景 : - 数据读写操作必须按扇区对齐。 - 文件系统的缓存机制依赖此字段进行缓冲区大小的分配。 #### [block_size](javascript:void(0)) - **类型**: `rt_uint32_t` - **描述**: 表示擦除一个**块所需的字节数**。 - **作用**: 在支持擦除操作的存储设备(如 NAND Flash)中,数据是以块为单位进行擦除的。这个字段提供了每次擦除操作的最小数据量。 - 应用场景 : - NAND Flash 驱动开发中需要正确设置此字段。 - 文件系统在进行垃圾回收或磨损均衡时会使用此字段。 ## 注册一个块设备   ### sd card的注册实例 ## 使用sfud norflash系列注册块设备 > rt-thread\components\drivers\spi\spi_flash_sfud.c  控制函数 1. 获取块设备信息 2. 实现擦除功能  ## 分析fal抽象层注册的块设备 今天看见了fal注册了一个块设备,由此联想可得出,**dfs文件系统可以挂载在fal注册的块设备之上** ### 1.块设备注册 ```c #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops blk_dev_ops = { RT_NULL, RT_NULL, RT_NULL, blk_dev_read, blk_dev_write, blk_dev_control }; #endif /** * create RT-Thread block device by specified partition * * @param parition_name partition name * * @return != NULL: created block device * NULL: created failed */ struct rt_device *fal_blk_device_create(const char *parition_name) { struct fal_blk_device *blk_dev; const struct fal_partition *fal_part = fal_partition_find(parition_name); const struct fal_flash_dev *fal_flash = NULL; if (!fal_part) { log_e("Error: the partition name (%s) is not found.", parition_name); return NULL; } if ((fal_flash = fal_flash_device_find(fal_part->flash_name)) == NULL) { log_e("Error: the flash device name (%s) is not found.", fal_part->flash_name); return NULL; } blk_dev = (struct fal_blk_device*) rt_malloc(sizeof(struct fal_blk_device)); if (blk_dev) { blk_dev->fal_part = fal_part;//分区句柄 blk_dev->geometry.bytes_per_sector = fal_flash->blk_size;//块大小 blk_dev->geometry.block_size = fal_flash->blk_size;//块数量 blk_dev->geometry.sector_count = fal_part->len / fal_flash->blk_size;//扇区数量 /* register device */ blk_dev->parent.type = RT_Device_Class_Block; #ifdef RT_USING_DEVICE_OPS blk_dev->parent.ops = &blk_dev_ops; #else blk_dev->parent.init = NULL; blk_dev->parent.open = NULL; blk_dev->parent.close = NULL; blk_dev->parent.read = blk_dev_read;//读 blk_dev->parent.write = blk_dev_write;//写 blk_dev->parent.control = blk_dev_control;//控制 #endif /* no private */ blk_dev->parent.user_data = RT_NULL; log_i("The FAL block device (%s) created successfully", fal_part->name); rt_device_register(RT_DEVICE(blk_dev), fal_part->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); } else { log_e("Error: no memory for create FAL block device"); } return RT_DEVICE(blk_dev); } ``` ### 2.fal的读取函数 直接使用fal提供的api `fal_partition_read`实现读 ```c static rt_ssize_t blk_dev_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { int ret = 0; struct fal_blk_device *part = (struct fal_blk_device*) dev; assert(part != RT_NULL); //读取数据 ret = fal_partition_read(part->fal_part, pos * part->geometry.block_size, buffer, size * part->geometry.block_size); if (ret != (int)(size * part->geometry.block_size)) { ret = 0; } else { ret = size; } return ret; } ``` ### 3.fal写 这里的是**先擦除后写**入 ```c /** * @brief 块设备写入 * 1. 擦除 * 2.写数据 * @param dev * @param pos * @param buffer * @param size * @return rt_ssize_t */ static rt_ssize_t blk_dev_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { int ret = 0; struct fal_blk_device *part; rt_off_t phy_pos; rt_size_t phy_size; part = (struct fal_blk_device*) dev; assert(part != RT_NULL); /* change the block device's logic address to physical address */ phy_pos = pos * part->geometry.bytes_per_sector; phy_size = size * part->geometry.bytes_per_sector; //擦除 ret = fal_partition_erase(part->fal_part, phy_pos, phy_size); if (ret == (int) phy_size) { //写 ret = fal_partition_write(part->fal_part, phy_pos, buffer, phy_size); } if (ret != (int) phy_size) { ret = 0; } else { ret = size; } return ret; } ``` ### 4.控制函数 主要功能 1. 获取设备信息 2. 擦除 ```c /* RT-Thread device interface */ #if RTTHREAD_VERSION >= 30000 static rt_err_t blk_dev_control(rt_device_t dev, int cmd, void *args) #else static rt_err_t blk_dev_control(rt_device_t dev, rt_uint8_t cmd, void *args) #endif { struct fal_blk_device *part = (struct fal_blk_device*) dev; assert(part != RT_NULL); if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)//获取设备信息 { struct rt_device_blk_geometry *geometry; geometry = (struct rt_device_blk_geometry *) args; if (geometry == RT_NULL) { return -RT_ERROR; } memcpy(geometry, &part->geometry, sizeof(struct rt_device_blk_geometry)); } else if (cmd == RT_DEVICE_CTRL_BLK_ERASE)//擦除 { rt_uint32_t *addrs = (rt_uint32_t *) args, start_addr = addrs[0], end_addr = addrs[1], phy_start_addr; rt_size_t phy_size; if (addrs == RT_NULL || start_addr > end_addr) { return -RT_ERROR; } if (end_addr == start_addr) { end_addr++; } phy_start_addr = start_addr * part->geometry.bytes_per_sector; phy_size = (end_addr - start_addr) * part->geometry.bytes_per_sector; if (fal_partition_erase(part->fal_part, phy_start_addr, phy_size) < 0) { return -RT_ERROR; } } return RT_EOK; } ```
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
chejia12
这家伙很懒,什么也没写!
文章
15
回答
1
被采纳
0
关注TA
发私信
相关文章
1
nfs挂载不成功,但是SPI flash块设备已经在了.F407探索者
2
使用sdio 接口实现 sd block 的 erase write read
3
让成员函数能作为rt_device中的回调函数
4
关于设备配置时延时的处理
5
rt_device_set_rx_indicate设置的回调如何传递参数?
6
关于 输入捕获 驱动的
7
关于设备驱动的迷茫与疑惑
8
关于rtthread中各种驱动的问题
9
drv_hwtimer 和hwtimer关系是啥?
10
RTT有没有接口文档,可以用于写一些自己创建的设备的这些文档?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
6
五分钟玩转RT-Thread新社区
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
Bootloader
AT
Hardfault
CAN总线
ART-Pi
FinSH
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
FAL
RTC
rt-smart
I2C_IIC
UART
cubemx
BSP
ESP8266
PWM
ota在线升级
WIZnet_W5500
packages_软件包
flash
freemodbus
GD32
潘多拉开发板_Pandora
ADC
编译报错
keil_MDK
定时器
flashDB
rt_mq_消息队列_msg_queue
ulog
socket
msh
中断
Debug
SFUD
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
RTT_逍遥
5
个答案
2
次被采纳
加缪
11
个答案
1
次被采纳
三世执戟
6
个答案
1
次被采纳
用户名由3_15位
5
个答案
1
次被采纳
本月文章贡献
chejia12
9
篇文章
4
次点赞
纯白酱
2
篇文章
4
次点赞
Hlafklio
2
篇文章
1
次点赞
530china
1
篇文章
7
次点赞
rv666
1
篇文章
7
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部