RT-Thread 学习笔记(八)---开启基于SPI Flash的elmfat文件系统(下)

IOT-OS之RT-Thread(十)--- DFS文件系统管理与devfs/elmfat示例 文件系统是一套实现了数据的存储、分级组织、访问和获取等操作的抽象数据类型 (Abstract data type),是一种用于向用户提供底层数据访问的机制。文件系统通常存储的基本单位是文件,即数据是按照一个个文件的方式进行组织。当文件比较多时,将导致文件繁多,不易分类、重名的问题。而文件夹作为一个容纳多个文件的容器而存在。 阅读详情

软件环境:Win7,Keil MDK 4.72a, IAR EWARM 7.2, GCC 4.2,Python 2.7 ,SCons 2.3.2

硬件环境:Armfly STM32F103ZE-EK v3.0开发板

参考文章:RT-Thread编程指南

[RTthread]新版本RTT中的SPI驱动框架

Github托管的Realtouch分支中examples目录中spi flash的例程

上篇文章中介绍了通过添加SPI Flash驱动,能够成功识别出SPI Flash芯片型号,但还是不能挂载文件系统,无法对文件系统进行相关操作,因此在这篇文章中要研究这问题。

【1】熟悉RT-Thread的内置命令(系统默认是C-Express Style)

RT-Thread 在默认情况下是开启了Shell终端功能的,而且使用的是USART1串口,这一切是我们所需要的而且在当前的这款开发板上不用改动,按默认即可。开发板上已经烧录进了上次编译的程序,这次只需该开发板上电或者复位即可。在串口的Shell终端,我们熟悉下RT-Thread的内置命令,然后我可以按照相同的方法添加我们自定义的命令。

(1)list():显示当前系统中存在的命令及变量

在Finsh提示符下输入list(),结果显示如下:

finsh>>list()               
--Function List:
led              -- set led[0 - 1] on[1] or off[0].
list_mem         -- list memory usage information
mkfs             -- make a file system
df               -- get disk free
ls               -- list directory contents
rm               -- remove files or directories
cat              -- print file
copy             -- copy file or dir
mkdir            -- create a directory
hello            -- say hello world
version          -- show RT-Thread version information
list_thread      -- list thread
list_sem         -- list semaphone in system
list_event       -- list event in system
list_mutex       -- list mutex in system
list_mailbox     -- list mail box in system
list_msgqueue    -- list message queue in system
list_mempool     -- list memory pool in system
list_timer       -- list timer in system
list_device      -- list device in system
list             -- list all symbol in system
--Variable List:
dummy            -- dummy variable for finsh
        0, 0x00000000
finsh>>

这些命令以list开头的在RT-Thread编程指南的finsh shell部分有说明,这里不再赘述。

下面看下led.c中有关led命令的代码:

#ifdef RT_USING_FINSH
#include <finsh.h>
static rt_uint8_t led_inited = 0;
void led(rt_uint32_t led, rt_uint32_t value)
{
    /* init led configuration if it's not inited. */
    if (!led_inited)
    {
        rt_hw_led_init();
        led_inited = 1;
    }
    if ( led == 0 )
    {
        /* set led status */
        switch (value)
        {
        case 0:
            rt_hw_led_off(0);
            break;
        case 1:
            rt_hw_led_on(0);
            break;
        default:
            break;
        }
    }
    if ( led == 1 )
    {
        /* set led status */
        switch (value)
        {
        case 0:
            rt_hw_led_off(1);
            break;
        case 1:
            rt_hw_led_on(1);
            break;
        default:
            break;
        }
    }
}
FINSH_FUNCTION_EXPORT(led, set led[0 - 1] on[1] or off[0].)
#endif

上面开关led的代码很简单,尽管实际操作中写入的值和命令描述的刚好相反,那是因为硬件驱动逻辑问题,不是我想研究问题的关键,关键是上面蓝色粗体部分,是一个宏定义,在finsh.h文件的324行给出的定义如下:

#define FINSH_FUNCTION_EXPORT(name, desc)   \
    FINSH_FUNCTION_EXPORT_CMD(name, name, desc)

一看又是一个宏定义,继续往下看,定位到finsh.h文件的231行,代码如下:

#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc)      \
                const char __fsym_##cmd##_name[] = #cmd;            \
                const char __fsym_##cmd##_desc[] = #desc;          \
                const struct finsh_syscall __fsym_##cmdSECTION("FSymTab")= \
                {                           \
                    __fsym_##cmd##_name,    \
                    __fsym_##cmd##_desc,    \
                    (syscall_func)&name     \
                };

在finsh.h文件的116行,我们可以看到上面有关finsh_syscall和syscall_func的定义:

typedef long (*syscall_func)();
/* system call table */
struct finsh_syscall
{
const char* name; /* the name of system call */
#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
const char* desc; /* description of system call */
#endif
syscall_func func;/* the function address of system call */
};

syscall_func是一个函数指针,返回值是long型,是finsh_syscall类中的一个成员,这样一来有关finsh的命令实现就很清楚了,当FINSH_FUNCTION_EXPOR宏被调用时,led函数的入口地址被传给finsh_syscall类的实例化对象__fsym_##cmd,并且被传进来的参数初始化。

具体点讲,led()被传递给了finsh_syscall类对象的一个成员syscall类型的func,并以 (syscall_func)&name的身份来初始化,显然name要被强制转换成syscall_func类型,也就是说led传递给func,返回值类型为long型。finsh_syscall类对象__fsym_##cmd通过SECTION宏指定在一个特定代码段FSymTab,当线程执行着个代码时,这个命令的功能函数也就被调用了。至于cmd,desc参数通过##连词符重新装配和替换则显得相对简单。

【2】用FINSH_FUNCTION_EXPOR宏导入的命令(Finsh终端的命令操作函数)在finsh_thread线程中调用的实现

参考文章:RT-Thread下finsh原理浅析(出处: amoBBS 阿莫电子论坛)

我们全局搜索下finsh_thread,可以定位到shell.c文件的291行void finsh_thread_entry(void* parameter),这个线程shell的命令接口线程,对终端命令的响应就是从这里发出的,如下

... ...

#ifdef RT_USING_CONSOLE
        shell->device = rt_console_get_device();
        RT_ASSERT(shell->device);
        rt_device_open(shell->device, RT_DEVICE_OFLAG_RDWR);
        rt_device_set_rx_indicate(shell->device,finsh_rx_ind);
#else
        RT_ASSERT(shell->device);
#endif
    }
    while (1)
    {

... ...

/* wait receive */
        if (rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER) != RT_EOK) continue;
        /* read one character from device */
        while (rt_device_read(shell->device, 0, &ch, 1) == 1)
        {

... ...

如果串口上没有收到任何数据,并且串口缓冲区中也无数据,即shell->rx_sem信号量的值为0,那么rt_sem_take这个信号量函数会使finsh_thread线程休眠,RTT内核会执行其他线程。当串口收到数据,系统调度程序会调用finsh_thread线程在rt_device_set_rx_indicate函数中设置的回调函数finsh_rx_ind,该函数调用rt_sem_release(&shell->rx_sem)来释放信号量,这会唤醒finsh_thread线程,该线程主动调用rt_device_read进行接收数据。在用户命令输入并回车确认后,会执行下面代码中finsh_run_line()函数进行语法解析。

... ...

#ifndef FINSH_USING_MSH_ONLY                
                    /* add ';' and run the command line */
                    shell->line[shell->line_position] = ';';
                    if (shell->line_position != 0) finsh_run_line(&shell->parser, shell->line);
                    else rt_kprintf("\n");
                #endif   

... ...

然后finsh_run_line()调用 finsh_parser_run(),代码如下:

#ifndef FINSH_USING_MSH_ONLY
void finsh_run_line(struct finsh_parser* parser, const char *line)
{
    const char* err_str;

    rt_kprintf("\n");
    finsh_parser_run(parser, (unsigned char*)line);

... ...

上面代码是对输入的命令进行语法解析,先对传入的字符串进行初步语法判断:

/*
expr_postfix -> expr_primary
| expr_postfix INC
| expr_postfix DEC
| expr_postfix '(' param_list ')'
*/
static struct finsh_node* proc_postfix_expr(struct finsh_parser* self)
{
enum finsh_token_type token;
struct finsh_node* postfix;

postfix =proc_primary_expr(self);

... ...

如上面代码所示,然后proc_primary_expr(self)调用finsh_node_new_id(id),finsh_node_new_id()代码如下:

... ...

/* then lookup system variable */
symbol = (void*)finsh_sysvar_lookup(id);
if (symbol == NULL)
{
/* then lookup system call */
symbol = (void*)finsh_syscall_lookup(id);
if (symbol != NULL) type = FINSH_IDTYPE_SYSCALL;
}

... ...

finsh_syscall_lookup()用来查找系统调用,代码如下:

struct finsh_syscall* finsh_syscall_lookup(const char* name)
{
struct finsh_syscall* index;
struct finsh_syscall_item* item;


for (index =_syscall_table_begin; index <_syscall_table_end; FINSH_NEXT_SYSCALL(index))
{
if (strcmp(index->name, name) == 0)
return index;
}

... ...

我们再看下_syscall_table_begin 和_syscall_table_end 的定义,代码如下:

#ifdef FINSH_USING_SYMTAB
struct finsh_syscall *_syscall_table_begin 	= NULL;
struct finsh_syscall *_syscall_table_end 	= NULL;
struct finsh_sysvar *_sysvar_table_begin 	= NULL;
struct finsh_sysvar *_sysvar_table_end 		= NULL;
#else
struct finsh_syscall _syscall_table[] =
{
	{"hello", hello},
	{"version", version},
	{"list", list},
	{"list_thread", list_thread},
#ifdef RT_USING_SEMAPHORE
	{"list_sem", list_sem},
#endif
#ifdef RT_USING_MUTEX
	{"list_mutex", list_mutex},
#endif
#ifdef RT_USING_FEVENT
	{"list_fevent", list_fevent},
#endif
#ifdef RT_USING_EVENT
	{"list_event", list_event},
#endif
#ifdef RT_USING_MAILBOX
	{"list_mb", list_mailbox},
#endif
#ifdef RT_USING_MESSAGEQUEUE
	{"list_mq", list_msgqueue},
#endif
#ifdef RT_USING_MEMPOOL
	{"list_memp", list_mempool},
#endif
	{"list_timer", list_timer},
};
struct finsh_syscall *_syscall_table_begin = &_syscall_table[0];
struct finsh_syscall *_syscall_table_end   = &_syscall_table[sizeof(_syscall_table) / sizeof(struct finsh_syscall)];
_syscall_table_begin  和 _syscall_table_end 的类型为finsh_syscall,这个类型前面有介绍过,就是FINSH_FUNCTION_EXPOR宏中用到的那个类型。 也就是用户定义的功能函数,如系统自带的led()函数调用 FINSH_FUNCTION_EXPOR宏导入 。在这里当finsh_thread线程被唤醒后又通过前面对setction(x)汇编指令指定的代码段去查询,如果用户定义的功能函数定义其中自然是能够解析通过,比如finsh_node_new_id(id)中的id就是功能函数led。如果再解析输入的命令语法再没有问题,下面运行编译函数讲语法树上的节点全部编译,之后再虚拟机finsh_vm_run()调用该命令。

    /* compile node root */
    if (finsh_errno() == 0)
    {
        finsh_compiler_run(parser->root);
    }
    else
    {
        err_str = finsh_error_string(finsh_errno());
        rt_kprintf("%s\n", err_str);
    }

    /* run virtual machine */
    if (finsh_errno() == 0)
    {
        char ch;
        finsh_vm_run();

有了上面的对led命令的认识,下面我们可以看下我们关心的对spi flash文件系统操作的命令mkfs等相关命令了。

【3】文件系统操作命令

(1) mkdfs 命令,在系统里全局搜索下,就可以在dfs_fs.c文件的492行找到可led命令一样的宏:

#ifdef RT_USING_FINSH
#include <finsh.h>
void mkfs(const char *fs_name, const char *device_name)
{
    dfs_mkfs(fs_name, device_name);
}
FINSH_FUNCTION_EXPORT(mkfs, make a file system);

同样地,mkdir,copy,rm等命令都是相同的方法导入finsh_thread线程中的。在终端中输入list_device()命令,显示如下:

finsh />list_device()
device    type      
-------- ---------- 
flash0   Block Device 
spi12    SPI Device 
spi11    SPI Device 
spi1     SPI Bus  
uart3    Character Device 
uart2    Character Device 
uart1    Character Device 
        0, 0x00000000
finsh />


finsh />mkfs("elm","flash0")   
        0, 0x00000000
finsh />

显然格式化成功,但为什么挂载不成功能呢?当调试追踪到ff.c文件的1986行时,return 2的条件成立,导致系统无法挂载,于是参考网友关于SPI flash的elm文件系统的帖子后突然想到可能是芯片不支持的问题,于是将开发板上的SST25VF016B跟换成25Q64FV,然后将底层驱动代码改为:

/* JEDEC Manufacturer¡¯s ID */
#define MF_ID           (0xEF)

... ...

/*else if(memory_type_capacity == MTC_SST25VF016B)
        {
            FLASH_TRACE("SST25VF016B detection\r\n");
            spi_flash_device.geometry.sector_count = 512;
        }*/
        else
        {
            FLASH_TRACE("Memory Capacity error!\r\n");
            return -RT_ENOSYS;
        }
    }

然后重新编译下载,第一启动时仍然挂载失败,在终端执行mkfs("elm","flash0") 显示格式化成功,复位后显示挂载成功,显示如下:

 \ | /
- RT -     Thread Operating System
 / | \     1.2.2 build Mar 31 2015
 2006 - 2013 Copyright by rt-thread team
W25Q64BV or W25Q64CV detection
finsh />flash0 mount to /.

再次跟踪到ff.c文件的1986行时,return 2的条件时,不成立了。

查看下flash空间

disk free: 8168 KB [ 2042 block, 4096 bytes per block ]
        0, 0x00000000
finsh />

【4】文件系统测试

在rt-thread-1.2.2/examples/test目录下可以找到文件fs_test.c,复制到当前分支的drivers目录下,然后加入到MDK 工程的Drivers组中,修改drivers目录下的Sconscript脚本,结果如下:

# add DFS drvers.
if GetDepend('RT_USING_DFS'):
src += ['rt_spi_device.c','rt_stm32f10x_spi.c','spi_flash_w25qxx.c','fs_test.c']
修改后保存。

打开fs_test.c文件,分别将文件中的64行,66行,79行,96行,122行的8000替换成10,读写次数太多,耗费时间。然后在线程while(1)末尾close(fd)下面添加如下代码:

/* close file */
        close(fd);			
	if(round >10) return;
    }
分别将文件中的173行,175行,188行,205行,231行的5000替换成10,也同样在 while(1)末尾close(fd)下面添加上面代码。目的是让这两个线程运行10round后退出。然后保存编译下载,重新复位后在终端中用list()命令查看下:

finsh />list()
--Function List:
led -- set led[0 - 1] on[1] or off[0].
fs_test -- file system R/W test. e.g: fs_test(3)
list_mem -- list memory usage information
mkfs -- make a file system
df -- get disk free
ls -- list directory contents

... ...

可以看到fs_test命令出现在列表中,现在可以调用这个命令来测试下:

finsh />fs_test(3)
arg is : 0x03   0, 0x00000000
finsh />thread fsrw1 round 1 rd:40000byte/s,wr:5217byte/s
thread fsrw2 round 1 rd:60000byte/s,wr:180000byte/s
thread fsrw1 round 2 rd:40000byte/s,wr:3428byte/s
thread fsrw2 round 2 rd:60000byte/s,wr:5806byte/s
thread fsrw1 round 3 rd:5454byte/s,wr:3333byte/s
thread fsrw2 round 3 rd:7200byte/s,wr:6000byte/s
thread fsrw1 round 4 rd:4615byte/s,wr:60000byte/s
thread fsrw2 round 4 rd:45000byte/s,wr:45000byte/s
thread fsrw1 round 5 rd:5000byte/s,wr:30000byte/s
thread fsrw2 round 5 rd:6923byte/s,wr:45000byte/s
thread fsrw1 round 6 rd:40000byte/s,wr:40000byte/s
thread fsrw2 round 6 rd:7200byte/s,wr:60000byte/s
thread fsrw1 round 7 rd:40000byte/s,wr:40000byte/s
thread fsrw2 round 7 rd:7200byte/s,wr:60000byte/s
thread fsrw1 round 8 rd:40000byte/s,wr:40000byte/s
thread fsrw2 round 8 rd:7200byte/s,wr:60000byte/s
thread fsrw1 round 9 rd:4800byte/s,wr:30000byte/s
thread fsrw2 round 9 rd:7500byte/s,wr:45000byte/s
thread fsrw1 round 10 rd:4800byte/s,wr:30000byte/s
thread fsrw2 round 10 rd:90000byte/s,wr:60000byte/s

finsh />

可以看到文件读写成功。看下根目录下这两个测试文件:

finsh />ls("/")
Directory /:
TEST1.DAT 1200
TEST2.DAT 1800
0, 0x00000000
finsh />

到此,我们已经在开发板上成功开启了基于SPI Flash的ELM FATFS文件系统。

RT-Thread的Finsh实现学习 如下是最简单的“hello world"函数, 在函数定义下面有一行宏,纸面意思是Finsh函数导出,下面对宏进行分析\n");先看下RT-Thread官方文档/* else分支下的宏定义 */{ \/* 上面宏定义中调用的宏的定义 *//* 上面宏定义中使用的结构体定义 *//* 上面宏定义中使用的函数指针定义 */ 阅读详情

相关推荐

elm FatFs文件系统移植总结

本文将根据我的一些理解,针对elm FatFs文件系统做一个初步总结。

放飞梦想,成就未来 1万+

RT-Thread交互接口finish框架分析

inux 的shell是属于脚本类的语言风格,finsih shell的语言风格明显是c的。毕竟c比较偏底层,资源占用少,这个对于资源贫瘠的嵌入式系统而言是非常适合的。finish shell从usart获取文本信息,在根据一定的语法规矩将文本语言重新按执行顺序组织一遍,最后再将重新组织的语句翻译成汇编指令,最后交由cpu执行指令。

挨踢农民的博客 4235

RT-Thread实战:基于SPI Flash的FATFS文件系统移植与优化

本文详细介绍了在RT-Thread实时操作系统中,如何基于SPI Flash移植和优化FATFS文件系统。从环境搭建、驱动移植到性能优化,提供了完整的实战指南,帮助开发者高效实现嵌入式设备的数据存储与管理。重点解析了SPI总线配置、SFUD驱动移植以及FATFS空间优化等关键技术,并分享掉电安全写入等高级应用技巧。

weixin_29291863的博客 387

rt-thread组件之elmfat文件系统浅析

上一文主要是讲到RTT的文件系统顶层dfs框架及其实现,接下来这篇博文主要是讲述其中间层的一个具体文件系统--elmfat文件系统。rt-thread的elmfat文件系统是一个开源的小型嵌入式文件系统,它的官网是http://elm-chan.org/fsw/ff/00index_e.html,RTT当前版本V1.1.0版本下的elmfat文件系统是从它的R0.08b版本移植而来。本文不打算详情

放飞梦想,成就未来 1万+

RT-Thread设备驱动移植避坑指南:以W25Q128挂载FATFS为例,详解SPI驱动注册与文件系统初始化流程

本文详细解析了RT-Thread设备驱动移植的关键技术,以W25Q128挂载FATFS为例,深入探讨SPI驱动注册与文件系统初始化流程。文章涵盖RT-Thread设备模型、SPI总线配置、FATFS文件系统挂载及调试优化技巧,帮助开发者避开常见陷阱,实现高效稳定的嵌入式存储解决方案。

weixin_30689307的博客 433

RT-Thread 入门与实战 - 第11章:FinSH 控制台开发

系统调试接口查看/修改系统参数调用系统函数执行自定义命令\n");关键点说明内置命令使用掌握list_thread/free等调试命令推荐的自定义命令方式参数处理argc/argv的规范使用方法线程安全避免在命令中执行耗时操作扩展阅读《RT-Thread编程指南》FinSH章节FinSH源码分析(components/finsh)

2301_79143213的博客 691

正点原子探索者stm32f407 rt-thread 文件系统使用

硬件说明:正点原子探索者stm32f407,板载SPI-FLASH W25Q128 系统说明:RT-Thread 3.1.2(以上的其他版本也可以) 在rt-thread-v3.1.2-stm32f407-elmfat\rt-thread\bsp\stm32\stm32f407-atk-explorer下,打开env配置工具, 第一步:进入Hardware Driver Config---&...

u011522841的专栏 3553

X3850x6 6241 fireware固件升级

登录联想https://datacentersupport.lenovo.com/cn/zc网站,选择system x,x3850 x6,type选择6241 选择驱动及应用程序,BIOS/UEFI 选择lnvgy_fw_uefi_a9e156a-4.90_anyos_32-64.uxz 文件,点击下载 选择IMM2, 下载lnvgy_fw_imm2_tcoo58b-5.80_anyos_noarch.uxz ps:3837和3839会跳转到ibm网站下载 笔记本直连.

zds00virtue的博客 5453

RT-Thread DFS 虚拟文件系统:3层架构解析与 FatFs/SPI Flash 实战挂载

本文深入解析RT-Thread DFS虚拟文件系统的3层架构设计,重点介绍FatFs在SPI Flash上的实战挂载方法。通过POSIX接口层、虚拟文件系统层和设备抽象层的协同工作,DFS实现了多文件系统共存与存储介质无关性,为嵌入式开发提供高效数据管理方案。文章包含详细的配置步骤、性能优化技巧和故障排查指南,帮助开发者快速掌握RT-Thread文件系统的核心应用。

weixin_30617797的博客 438

告别Selenium!纯Python+Requests搞定微信视频号登录Cookie(附完整代码与避坑指南)

本文详细介绍了如何利用纯Python和Requests库实现微信视频号的自动化登录,替代传统的Selenium方案。通过解析HTTP请求交互流程,提供完整的代码实现和避坑指南,显著提升爬虫效率和隐蔽性,适用于轻量化爬虫开发。

weixin_30642561的博客 312

手把手教你给STM32F103移植LVGL触摸驱动(基于野火开发板,附完整代码)

本文详细介绍了如何在野火STM32F103开发板上移植LVGL触摸驱动,提供从环境准备到代码实现的完整指南。通过XPT2046触摸芯片的底层驱动集成和LVGL输入设备接口配置,开发者可以快速实现触摸功能,并解决常见问题如触摸无响应、坐标偏移等。

weixin_30856725的博客 1021

rt-thread下调试elmfat 问题记录

硬件平台:stm32f107 SPI flash:w25q32 RTT版本:v2.1 w25q32的驱动大神们已经写好(w25qxx.c),我只需要照猫画虎的实现相应SPI的驱动程序即可(bsp例程都有),如此spi flash就可以读写了。查看device列表如下: 接着启用DFS功能和ELMFAT类型文件系统,并挂载文件系统名为“elm”的文件系统到介质为flash0的...

650

Cadence Virtuoso IC617:从零构建传输门与反相器的Schematic设计实战

本文详细介绍了使用Cadence Virtuoso IC617进行传输门与反相器Schematic设计的完整流程,包括环境准备、原理图绘制、Symbol创建、仿真验证及实用技巧。通过分步指导和实战经验分享,帮助初学者快速掌握集成电路设计基础,提升EDA工具应用能力。

weixin_29194693的博客 597

RT-Thread:在运行RTT的GD32E103的Flash芯片上挂载文件系统

文章目录前言一、pandas是什么?1.引入库2.读入数据总结 前言 一、pandas是什么? 添加文件件 添加路径 加大栈空间 加大动态内存池 运行成功 内存总使用情况 1.引入库 代码如下(示例): import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarnings('ignore')

小破孩的博客 1503

基于 国产USRP B210 的通信+侦测+干扰三合一实验平台,解锁无线攻防全场景!

在当代复杂电磁环境与多样化通信需求并存的背景下,软件定义无线电(SDR)技术正展现出前所未有的系统灵活性与功能可重构性。由两台USRP-LW B210软件无线电设备模拟无线链路通信过程,能够模拟多种无线通信信号传输及图像传输场景,适用于通信协议验证、抗干扰测试及教学实验。,支持"通信-侦测-干扰-优化"的闭环实验流程,为无线通信领域的教学科研与工程应用提供了一套经济高效、功能完备的解决方案。系统可对通信链路信号进行快速、自动化侦测、识别、告警,并支持多种干扰信号生成、模式切换及效果评估功能。

luowave2012的博客 832

生存曲线绘制及图例标签添加(使用R语言)

数据应该包含两列:一个是表示个体生存时间的时间变量(通常称为"时间(time)“)和一个是表示个体是否发生事件(如死亡)的事件变量(通常称为"事件(event)”)。通过修改上述代码中的数据和参数,您可以根据自己的需求绘制生存曲线,并添加相应的图例信息和标签。生存曲线是在生存分析中常用的工具,用于描述一组个体随时间的存活概率。函数的第一个参数指定图例的位置,这里我们选择了右上角(“topright”)。包来进行生存曲线的绘制,并通过添加图例信息和标签来增强可视化效果。的数据框,包含这两列数据。

CyberXZ的博客 555

RT-Thread 学习笔记(七)---开启基于SPI Flash的elmfat文件系统(中)

软件环境:Win7,Keil MDK 4.72a, IAR EWARM 7.2, GCC 4.2,Python 2.7 ,SCons 2.3.2 硬件环境:Baiwei STM32F103ZE-EK v3.0开发板 参考文章:RT-Thread编程指南 [RTthread]新版本RTT中的SPI驱动框架 Github托管的Realtouch分支中examples目录

aping_cs_dn的专栏 9461

POCV/SOCV 、LVF的差别

1.POCV与OCV、AOCV 为了模拟片上PVT的差异带来的影响,最早提出了OCV(On Chip Variation)给每个cell都设置一个固定的derate值,来覆盖最悲观的情况,但是随着工艺发展,设计规模增大,OCV过度的悲观开始限制性能,于是又有了AOCV(Advanced On Chip Variation),用基于depth和distance的derate来取代单一的全局的derate值,但时序收敛的过程中逻辑级数depth的变化让时序分析的时间变得非常长,由此POCV诞生了。 POCV

m0_61544122的博客 5363

RT-Thread 学习笔记(六)--- 开启基于SPI Flash的elmfat文件系统(上)

软件环境:Win7,Keil MDK 4.72a, IAR EWARM 7.2, GCC 4.2,Python 2.7 ,SCons 2.3.2 硬件环境:Armfly STM32F103ZE-EK v3.0开发板 参考文章:RT-Thread编程指南 在RT-Thread默认的是SD卡作为文件系统挂载,代码如下: /* Filesystem Initi

aping_cs_dn的专栏 1万+

黑猫带你学eMMC协议第22篇:emmc可靠写详解(Write Reliability)

1 前言 1.1 声明 本文依据eMMC JEDEC5.1、网络资料及个人工作经验整理而成,如有部分错误请留言。 本文部分内容可能源自网络,侵删。 本文结合eMMC JEDEC5.1协议手册查看效果更佳。 1.2 内容提要 1、什么是可靠性写属性(Write Reliability)? 2、可靠写和普通的写有什么区别? 3、设置可靠写的流程及流程框图。 4、可靠写需要遵循哪些规则? 1.3 参考链接 本文主要参考链接:http://www.up48.com/cn/support/8_37.html 2 什么

黑猫奥利奥的博客 3122

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

RT-Thread星火一号开发板BSP进阶:如何用ENV工具开启SD卡和W25Q128 Flash支持

本文详细介绍了如何在RT-Thread星火一号开发板上使用ENV工具配置SD卡和W25Q128 Flash支持。通过实战步骤和代码示例,帮助开发者快速启用存储设备并挂载文件系统,适用于STM32F407开发板的存储扩展需求。

weixin_33739523的博客 675

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

STM32F407+W25Q128上跑RT-Thread文件系统:DFS+elm-FAT+SFUD实战

虚拟文件系统(VFS)为嵌入式应用提供统一的POSIX文件操作接口,屏蔽底层存储介质差异。其核心原理是通过块设备抽象层将SPI Flash等硬件封装为标准块设备,再由elm-FAT等文件系统实现管理扇区分配与目录结构。在STM32F407与W25Q128平台上,结合RT-Thread的DFS、elm-FAT和SFUD组件,可快速构建稳定可靠的嵌入式文件系统,支持数据记录、固件备份与远程导出等场景。本文分享从块设备注册到文件读写的完整工程实践与避坑经验。

weixin_34195142的博客 265

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

RT-Thread—FAL与EasyFlash组件移植

一、FAL管理与示例   FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API ,FAL 框架图如下:   从上图可以看出FAL抽象层位于SFUD框架的上层,可以将多个Flash硬件(包括片内Flash和片外Flash)统一进行管理,并向上层比如DFS文件系统层提供对底层多个Flash硬件的统一访问接口,方便上层应用对底层

鸿墨轩 2224

RT-Thread DFS 排错指南:解决文件系统挂载失败的 5 个常见根因与修复

本文深入解析RT-Thread DFS文件系统挂载失败的5大常见问题,包括设备未注册、扇区大小不匹配、长文件名配置冲突等,提供详细的解决方案和调试技巧。通过实战案例和代码示例,帮助开发者快速定位并修复DFS虚拟文件系统问题,确保嵌入式系统稳定运行。

weixin_33874713的博客 411

STM32F407 上基于 RT-Thread 与 W25Q128 的 FAT 文件系统移植实战

虚拟文件系统(VFS)通过抽象物理存储接口,将 Flash 扇区操作转化为标准文件读写,显著提升嵌入式存储管理的灵活性。其核心原理在于分层驱动架构,结合 SPI 总线与 Flash 通用驱动(SFUD),实现块设备到文件系统的无缝对接。在 STM32F407 与 W25Q128 的典型应用中,借助 RT-Thread 的 DFS 框架和 elm-FAT 组件,开发者可快速构建类似 U 盘的文件管理能力,适用于配置存储、日志记录及数据缓存等场景。SPI Flash 文件系统移植的关键在于扇区大小匹配与底层通信

weixin_33912453的博客 206

RT-Thread DFS文件系统集成:W25Q128+ELM FATFS实战

嵌入式文件系统是实现数据持久化与结构化管理的核心技术,其本质是通过虚拟文件系统(VFS)抽象硬件差异,将底层块设备(如SPI Flash)映射为标准POSIX接口。RT-Thread的DFS框架以分层设计(设备驱动→DFS抽象→文件系统→VFS)支撑轻量级、可裁剪的工程落地,关键技术在于扇区对齐与擦除写入协同——尤其在W25Q128等SPI Flash上,必须严格匹配物理擦除单元(4096字节)与ELM FATFS逻辑扇区配置,否则导致挂载失败或数据损坏。该方案广泛应用于工业日志存储、固件升级、配置管理等需

juice的博客 644
上一篇: RT-Thread 学习笔记(七)---开启基于SPI Flash的elmfat文件系统(中)
下一篇: RT-Thread 学习笔记(九)---开启基于SD卡中的 Elm FatFS 文件系统
aping_cs_dn
博客等级 码龄19年 188粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

aping_cs_dn

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

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

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

打赏作者

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

抵扣说明:

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

余额充值