物联网系统RT-Thread学习---组件使用(二)

前文回顾

《物联网系统RT-Thread学习—开发环境搭建》
《物联网系统RT-Thread学习—内核学习》
《物联网系统RT-Thread学习—设备和驱动学习》
物联网系统RT-Thread学习—组件使用(一)

本集预告

学习RTT到现在,缺少一些实际用例,最近购买了flash芯片,来学习一下组件中的文件系统,为了学习,得下本钱啊。
在这里插入图片描述

开发过程

硬件连接

用到是标准SPI接口,所以一共SPI线4根,与开发板的SPI1接口相连
STM32F103C8T6的SPI1如下
在这里插入图片描述
flash芯片是W25Q64,8Mflash,接线如下
在这里插入图片描述
这4根线,很简单。
CS 《----》NSS
CLK《----》SCK
DI 《----》MOSI
DO 《----》MISO

电源2根,别接反了就行。
在这里插入图片描述

工程配置

开启SPI总线。
在这里插入图片描述
这里我们使用了SFUD,这个能够自动探测flash的参数。
在这里插入图片描述

然后配置开发板的SPI部分宏定义开启,这与前面的总线启用是配合关系,负责具体的接口选择
在这里插入图片描述
如果这里没开启,那就需要手动增加一些宏定义,但是每次配置就会清空,所以最好的办法,就是在这里开启。前面一章开启IIC的时候,这里就没有配置,还是太年轻啊。
在这里插入图片描述

开启虚拟文件系统及对elm格式支持
在这里插入图片描述
这里选择的是elm格式,系统能够支持如下几种格式,需要分别开启。根据需求选择,而我不一样,我只是学习一下没有见过的elm文件系统。
在这里插入图片描述
这个扇区大小就需要根据flash芯片来决定了

本章重点来咯!!!
在这里插入图片描述

W25Q64是华邦公司推出的大容量SPI FLASH产品,其容量为64Mb。该25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件。W25Q64将8M字节的容量分为128个块,每个块大小为64K字节,每个块又分为16个扇区,每个扇区4K个字节。W25Q64的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。所以,这需要给W25Q64开辟一个至少4K的缓存区,这样必须要求芯片有4K以上的SRAM才能有很好的操作。

我这个STM32103F20K的内存,用起来也很吃力,后面就马上遇到问题了。

代码实现

SPI设备注册

static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    rt_hw_spi_device_attach("spi1", "spi10", GPIOA, GPIO_PIN_4);
	rt_thread_delay(50);	

    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi10"))
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);

其中的PA4这个接口是片选引脚
这里就是告诉系统,我们有一个SPI设备接入了,片选IO为PA4。并且挂载为块设备。
在这里插入图片描述

块设备注册

然后需要将刚才的SPI设备,挂载到根目录

static int mnt_init(void)
{
	//dfs_mkfs("elm","W25Q64");//挂在前需格式化
    if(dfs_mount("W25Q64","/","elm",0,0)==0) //挂载文件系统,参数:块设备名称、挂载目录、文件系统类型、读写标志、私有数据0
    {
		rt_kprintf("挂载成功\n");
    }
    else
    {
		rt_kprintf("挂载失败\n");
    }
    return RT_EOK;
}
INIT_ENV_EXPORT(mnt_init);

如果需要格式化,前面调用

dfs_mkfs("elm","W25Q64");//挂在前需格式化

这个最好不要每次都调用,否则你还存啥啊
在这里插入图片描述

测试主函数

int main(void)
{
	int file;
    int size;
    struct statfs elm_stat;
    char str[] = "hello world";
	char buf[80];
	
	if(statfs("/", &elm_stat) == 0)
	{
		rt_kprintf("文件系统 block size: %d, total blocks: %d, free blocks: %d.\n", elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree);
	}
	if(mkdir("/testdir", 0x777) == 0)
	{
        rt_kprintf("创建目录'/testdir'成功\n");
	}
	else
	{
		rt_kprintf("创建目录'/testdir'失败\n");
	}
	
    /* 以创建和读写模式打开文件,如果该文件不存在则创建该文件*/
    file = open("/testdir/test.txt", O_WRONLY | O_CREAT);
    if (file >= 0)
    {
		rt_thread_mdelay(1000); 
        if(write(file, str, sizeof(str)) == sizeof(str))
    	{
			rt_kprintf("写文件成功\n");
    	}
		else
		{
			rt_kprintf("写文件失败\n");
		}
        close(file);   
    }
	else
	{
		rt_kprintf("写文件打开失败\n");
	}

    /* 以只读模式打开文件 */
    file = open("/testdir/test.txt", O_RDONLY);
	
    if (file >= 0)
    {
        size = read(file, buf, sizeof(buf));
        close(file);
        if(size == sizeof(str))
    	{
			rt_kprintf("读取内容成功(size: %d): %s \n", size, buf);
    	}
		else
		{
			rt_kprintf("读取内容失败(size: %d): %s \n", size, buf);
		}
    }
	else
	{
		rt_kprintf("读文件打开失败\n");
	}
    return RT_EOK;
}

功能就是挂载目录,测试创建目录,文件的写入和读出。
,基操勿六,基操勿六。
在这里插入图片描述

遇到问题

无法打开文件

调试结果发现
在这里插入图片描述
能创建路径,但是无法创建文件
在这里插入图片描述

通过调试发现,在函数int dfs_elm_open(struct dfs_fd *file)
中,分配内存出现了失败
在这里插入图片描述
这里的结构大小是4000多,这就和前面我们所说的
在这里插入图片描述
呼应起来了。
在这里插入图片描述
所以这里来看,使用这个文件系统,对内存要求还是挺大,反观创建路径的内存需求为500多个字节,这里还是能够满足的。
在这里插入图片描述
所以这里我们需要打开一个宏定义
在这里插入图片描述
一旦开启这个,FIL这个结构,就会缩小FF_MAX_SS个字节,即减少一个扇区的大小,4096字节,那么再分配内存,就不会失败了。
修改之后再次测试
在这里插入图片描述
OK。
在这里插入图片描述

注册函数

RTT提供了一些接口,用来在系统启动时候,注册一些设备,并且根据先后顺序,提供了不同的接口。

/* board init routines will be called in board_init() function */
#define INIT_BOARD_EXPORT(fn)           INIT_EXPORT(fn, "1")
/* pre/device/component/env/app init routines will be called in init_thread */
/* components pre-initialization (pure software initilization) */
#define INIT_PREV_EXPORT(fn)            INIT_EXPORT(fn, "2")
/* device initialization */
#define INIT_DEVICE_EXPORT(fn)          INIT_EXPORT(fn, "3")
/* components initialization (dfs, lwip, ...) */
#define INIT_COMPONENT_EXPORT(fn)       INIT_EXPORT(fn, "4")
/* environment initialization (mount disk, ...) */
#define INIT_ENV_EXPORT(fn)             INIT_EXPORT(fn, "5")
/* appliation initialization (rtgui application etc ...) */
#define INIT_APP_EXPORT(fn)             INIT_EXPORT(fn, "6")

我们前面用了

#define INIT_COMPONENT_EXPORT(fn)       INIT_EXPORT(fn, "4")
#define INIT_ENV_EXPORT(fn)				INIT_EXPORT(fn, "5")

分别用来初始化设备和执行挂载操作。并且保证了注册设备在前,挂载在后。

结束语

又到了一年一度的扫福活动了,每次到这时候,才意识到快过年了。今天看到这样一篇文章
《对话“流调中最辛苦的中国人”:来北京找儿子,凌晨打零工补贴家用》

我也不觉得自己可怜。我只是好好干活,我不偷不抢,靠自己的力气,靠自己的双手,挣点钱,挣了钱找孩子。就是为了生活,为了照顾这个家。
我找孩子,到现在花了好几万。打工都是打零工,赚了钱就找孩子,没钱了就打工。我努力,就是为了把孩子找回来。我辛苦一点,就算把命搭到里面,也要把孩子找回来。

致敬一位伟大的父亲。

RT-Thread诞生于2006年,是一款以开源、中立、社区化发展起来的物联网操作系统RT-Thread主要采用 C 语言编写,浅显易懂,且具有方便移植的特性(可快速移植到多种主流 MCU 及模组芯片上)。RT-Thread把面向对象的设计方法应用到实时系统设计中,使得代码风格优雅、架构清晰、系统模块化并且可裁剪性非常好。 RT-Thread有完整版和Nano版,对于资源受限的微控制器(MCU)系统,可通过简单易用的工具,裁剪出仅需要 3KB Flash、1.2KB RAM 内存资源的 NANO 内核版本;而相对资源丰富的物联网设备,可使用RT-Thread完整版,通过在线的软件包管理工具,配合系统配置工具实现直观快速的模块化裁剪,并且可以无缝地导入丰富的软件功能包,实现类似 Android 的图形界面及触摸滑动效果、智能语音交互效果等复杂功能。 RT-Thread架构 RT-Thread是一个集实时操作系统RTOS)内核、中间件组件物联网操作系统,架构如下: 内核层:RT-Thread内核,是 RT-Thread的核心部分,包括了内核系统中对象的实现,例如多线程及其调度、信号量、邮箱、消息队列、内存管理、定时器等;libcpu/BSP(芯片移植相关文件 / 板级支持包)与硬件密切相关,由外设驱动和 CPU 移植构成。 组件与服务层:组件是基于 RT-Thread内核之上的上层软件,例如虚拟文件系统、FinSH命令行界面、网络框架、设备框架等。采用模块化设计,做到组件内部高内聚,组件之间低耦合。 RT-Thread软件包:运行于 RT-Thread物联网操作系统平台上,面向不同应用领域的通用软件组件,由描述信息、源代码或库文件组成。RT-Thread提供了开放的软件包平台,这里存放了官方提供或开发者提供的软件包,该平台为开发者提供了众多可重用软件包的选择,这也是 RT-Thread生态的重要组成部分。软件包生态对于一个操作系统的选择至关重要,因为这些软件包具有很强的可重用性,模块化程度很高,极大的方便应用开发者在最短时间内,打造出自己想要的系统RT-Thread已经支持的软件包数量已经达到 180+。 RT-Thread的特点: 资源占用极低,超低功耗设计,最小内核(Nano版本)仅需1.2KB RAM,3KB Flash组件丰富,繁荣发展的软件包生态 。 简单易用 ,优雅的代码风格,易于阅读、掌握。 高度可伸缩,优质的可伸缩的软件架构,松耦合,模块化,易于裁剪和扩展。 强大,支持高性能应用。 跨平台、芯片支持广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖哥王老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值