背景:

  • MCU:STM32F207
  • SPI flash: Winbond W25Q16BV
  • OS: RTT V1.1.1
  • bsp: STM32F20x

1 将spi_core.c,spi_dev.c及spi.h三个文件加入工程

spi_core.c,spi_dev.c这两个文件位于RTT\components\drivers\spi目录下,而spi.h头文件位于RTT\\components\drivers\include\drivers目录下.

可在MKD工程的Drivers组下将上面两个源文件加进行,并将spi.h头文件所在目录添加到工程的include path下.

spi_core.c文件实现了spi的抽象操作,如注册spi总线(spi_bus),向SPI总线添加设备函数等.

注: 这里将MCU的一路spi外设虚拟成spi总线,然后总线上可以挂很多spi设备(spi_device),很个spi_device有一个片选cs.

spi总线和spi设备要在RTT中可以生效就必须先向RTT注册,因此就需要使用上面的注册SPI总线函数和向SPI总线中添加SPI设备.

spi_core.c还包含了配置SPI函数,发送和接收等通信函数,占用和释放SPI总线函数及选择SPI设备函数.这些函数都是抽象出来的,反映出SPI总线上的一些常规操作.真正执行这些操作的过程并不在spi_core.c源文件中,实际上,这些操作信息都是通过注册SPI总线和向总线添加SPI设备时这些操作集就已经"注册"下来了,真正操作时是通过注册信息内的操作函数去实现,也可以说是一种回调操作.

而spi_dev.c实现了SPI设备的一些抽象操作,比如读,写,打开,关闭,初始化等,当然当MCU操作SPI设备的时候,是需要通过SPI总线与SPI设备进行通信的,既然通信就必然会有SPI通信协议,但是通信协议并不在这里具体,spi_dev.c这里还只是SPI设备的抽象操作而已,它只是简单地调用spi_core.c源文件中的抽象通信而已,具体实现还是要靠上层通过SPI总线或SPI设备注册下来的信息而实现的.

在确保了spi_core.c,spi_dev.c和spi.h这三个源文件在MDK工程内之后,接着往下走.

2 添加stm32f20x_40x_spi.c及其对应头文件

将stm32f20x_40x_spi.c添加到Drivers组内.这个stm32f20x_40x_spi.c要在realtouch源码工程里找来,在文件系统示例代码中有.

在源文件在spi.h的基础上根据STM32F20x这款MCU的特点进行了进一步封装.这里修改的地方只有一处理:

即在config函数内配置SPI最大时钟时可根据MCU的具体特性配置为:30000000;

//#ifdef STM32F4XX
// stm32_spi_max_clock = 37500000;
//#elif STM32F2XX
stm32_spi_max_clock = 30000000;
//#endif

3 添加spi_flash_w25qxx.c进工程

由于这里使用的FLASH是Winbond的W25Q16BV,所以以此文件命名,此源文件及其头文件可以在realtouch的源文件中找到.realtouch工程正好也是使用的此flash.

顾名思义,此源文件正是针对w25q16这款芯片的特点来实现的,当然包含

在这里,具体实现了SPI通信的参数,这些参数传递给stm32f20x_4-x_spi.c文件中定义的函数,然后再进一步传递给spi_core来进行通信,spi_core的通信过程又会回调回来.

spi_flash_w25qxx.c还实现了read.write,open,close这些标准操作,这些函数就封装到一个结构体中通信注册函数注册到spi_core内部以供其回调所用.同时spi_flash_w25qxx.c还传递操作所必要的参数下去.

4 初始化 spi flash

接下来就是在RTT系统初始化时对SPI FLASH做些必要的初始化.

如下:

#ifdef RT_USING_SPI
rt_hw_spi2_init(); #ifdef RT_USING_DFS
w25qxx_init("flash0", "spi20");
#endif /* RT_USING_DFS */

rt_hw_spi2_int()函数的作用是向RTT设备管理系统注册SPI2总线和向SPI2总线添加spi设备及其必要的IO管脚初始化. 这里仅仅只是注册设备而已.

w25qxx_init的作用是将SPI2总线上的SPI设备spi20注册成FLASH设备,也就是说将之前的设备告诉RTT其实是FLASH存储设备,然后配上相关的SPI FLASH存储设备参数.

在w25qxx_init函数内会读取spi flash的device id, 这里得根据自己所使用的具体FLASH进行修改.

rt_hw_spi_init函数如下:

这里PB12用作SPI FLASH的片选管脚.

static void rt_hw_spi2_init(void)
{
/* register spi bus */
{
static struct stm32_spi_bus stm32_spi;
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*!< SPI SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure); /* Connect alternate function */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); stm32_spi_register(SPI2, &stm32_spi, "spi2");
} /* attach cs */
{
static struct rt_spi_device spi_device;
static struct stm32_spi_cs spi_cs; GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* spi21: PB12 */
spi_cs.GPIOx = GPIOB;
spi_cs.GPIO_Pin = GPIO_Pin_12;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = spi_cs.GPIO_Pin;
GPIO_SetBits(spi_cs.GPIOx, spi_cs.GPIO_Pin);
GPIO_Init(spi_cs.GPIOx, &GPIO_InitStructure); rt_spi_bus_attach_device(&spi_device, "spi20", "spi2", (void*)&spi_cs);
}
}

注:在rt_config.h头文件中得将#define RT_USING_SPI宏打开.

5 移植ELM FAT文件系统

ELM FAT一般用不着移植,MDK工程中一般默认就有,如果没有就得自己添加了,一般包含6个C文件:

ff.c,dfs_elm.c,dfs.c,dfs_file.c,dfs_fs.c,dfs_posix.c,这些源文件在RTT\components\dfs目录下可以找到,一般不需要修改.

但是在rtconfig.h头文件中针对ELM需要做些修改,如下:

/* SECTION: device filesystem */
#define RT_USING_DFS
#define RT_USING_DFS_ELMFAT
#define RT_DFS_ELM_REENTRANT
#define RT_DFS_ELM_WORD_ACCESS
#define RT_DFS_ELM_DRIVES 1
#define RT_DFS_ELM_USE_LFN 0 //这里一般设置为0,不使用长文件名,否则需要加入另外的源文件才能编译通过
#define RT_DFS_ELM_MAX_LFN 255
#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 //这里一定要与实际的spi flash一个扇区所包含的字节数相符,太小了会出现内存非法覆盖的情况 /* the max number of mounted filesystem */
#define DFS_FILESYSTEMS_MAX 2
/* the max number of opened files */
#define DFS_FD_MAX 4

此时附上MDK工程示图如下:

6  初始化文件系统及挂载文件系统

/* Filesystem Initialization */
#ifdef RT_USING_DFS
{
/* init the device filesystem */
dfs_init(); #ifdef RT_USING_DFS_ELMFAT
/* init the elm chan FatFs filesystam*/
elm_init(); /* mount sd card fat partition 1 as root directory */
if (dfs_mount("flash0", "/", "elm", 0, 0) == 0)
{
rt_kprintf("flash0 mount to /.\n");
}
else
rt_kprintf("flash0 mount to / failed.\n");
#endif
}
#endif

7 格式化spi flash

烧录进MCU,首次时SPI FLASH是未格式化的,因此会挂载出错,此时可以在finish下使用mkfs来格式化FLASH,然后使用mkdir来创建一个目录,再使用ls指令来查看创建的目录是否存在,如果存在,则说明正常了.如下图:

通过这一步就说明SPI FLASH能正常工作了.

下面通过代码来测试.

8 通过代码来测试打开读写文件系统

在工程中加入如下测试代码:

{
//文件系统测试代码
int fd=0; fd =open("/myfile.txt",DFS_O_CREAT|DFS_O_RDWR,0);
if(fd <0)
{
rt_kprintf("open file failed!\r\n");
}
else
{
int count =write(fd,"123456",7);
char buf[10]; close(fd);
fd =0; rt_thread_delay(50);
rt_memset(buf,0,10);
fd =open("/myfile.txt",DFS_O_RDONLY,0);
if(read(fd,buf,7))
{
rt_kprintf("read=%s\r\n",buf);
}
else
{
rt_kprintf("read file err!\r\n");
} }
}

结果如下:

写进myfile.txt文件中的内容又可以原样读出来.

也可以通过ls指令再次查看/目录下的内容:

这样就验证了文件系统完全可以正常工作了.

完!

RTT下spi flash+elm fat文件系统移植小记的更多相关文章

  1. SD卡fat文件系统移植

    经过充分的研究,发现fatfs文件系统移植的比较简单!因为代码都已经被别人做好了!我们只需把io层稍稍做个处理就ok了: 至于sd卡的驱动请看我这篇博客:http://blog.csdn.net/ie ...

  2. RTThread DFS文件系统使用: 基于使用SFUD驱动的SPI FLASH之上的ELM FATFS文件系统

    参考博文: 博文很长,但是实际要操作的步骤没几下. http://m.elecfans.com/article/730878.html  为了防止几年后文章链接找不到,我把文章复制过来了 /***** ...

  3. 【转】SPI FLASH与NOR FLASH的区别 详解SPI FLASH与NOR FLASH的不一样

    转自:http://m.elecfans.com/article/778203.html 本文主要是关于SPI FLASH与NOR FLASH的相关介绍,并着重对SPI FLASH与NOR FLASH ...

  4. UBI 文件系统移植 sys 设备信息【转】

    转自:http://blog.chinaunix.net/uid-25304914-id-3058647.html cat /sys/class/misc/ubi_ctrl/dev --------- ...

  5. Nand Flash,Nor Flash,CFI Flash,SPI Flash 之间的关系

    前言:    在嵌入式开发中,如uboot的移植,kernel的移植都需要对Flash 有基本的了解.下面细说一下标题中的中Flash中的关系 一,Flash的内存存储结构    flash按照内部存 ...

  6. openwrt spi flash 分区适配过程

    openwrt spi flash 分区适配过程 这里基于 openwrt mt7620a 平台来跟踪,主要是想理清 dts 里的分区描述是如何一步步转化成内核分区行为. 先来看看 dts 中关于分区 ...

  7. 【原创】All in One i.MXRT1050/RT1020 SPI Flash Algorithm for J-Flash

    2020年,这个给大家一种很漫长的恍惚感的一年,终于是过去了.这一年我们很多新的人生第一次就这么被发生了,第一次居家办公这么长时间(很多人肥膘都长了不少,我却瘦了2斤,不知是工作太积极了还是被家里小怪 ...

  8. 基于s5pv210嵌入式系统busybox文件系统移植

    基于s5pv210嵌入式系统busybox文件系统移植 1.下载源码 busybox.net/downloads下载最新版的busybox源码,最新源码为1.21.1 2.解压源码文件 tar xvf ...

  9. OpenRisc-32-ORPSoC烧写外部spi flash

    引言 经过前面的分析和介绍,我们对ORPSoC的启动过程(http://blog.csdn.net/rill_zhen/article/details/8855743)和 ORpSoC的debug子系 ...

随机推荐

  1. nginx 站点代理,负载均衡

    nginx服务器IP是192.168.1.201 web服务器 IP 192.168.1.200,192.168.1.199 1.主配置文件是/etc/nginx/下的nginx.conf,另外一个是 ...

  2. 理解 JavaScript 中的 Function.prototype.bind

    函数绑定(Function binding)很有可能是你在开始使用JavaScript时最少关注的一点,但是当你意识到你需要一个解决方案来解决如何在另一个函数中保持this上下文的时候,你真正需要的其 ...

  3. Matlab 常用绘图指令(二维图形)

    使用matlab的时候常常会忘掉一些指令,每次都要重新查找,挺麻烦的,这里收集一些常用的绘图指令,供自己和大家以后方便查找和使用. 1.例子-包含了常用绘图命令 clear clc %%数据准备 x ...

  4. Linux终端(Xshell等)的编码设置

    先简单说说一下遇到的情况吧: 在用类似Xshell的工具连接远端Linux时,运行命令ls时,如果有中文,就会显示有乱码: 网上查资料时,也把相应的连接属性修改为utf-8了(见下图),但是还是不行: ...

  5. VC获取屏幕分辨率及大小相关(转)

    vc得到屏幕的当前分辨率方法: 1.Windows API调用 int width = GetSystemMetrics ( SM_CXSCREEN );  int height= GetSystem ...

  6. 信用卡:银联,VISA,MasterCard

    国际信用卡是一种银行联合国际信用卡组织签发给那些资信良好的人士并可以在全球范围内进行透支消费的卡片,同时该卡也被用于在国际网络上确认用户的身份. 国际发卡组织是一个由全世界银行参与的非营利的国际性组织 ...

  7. PostgreSQL SystemTap on Linux 转

    PostgreSQL 支持动态跟踪, 可以通过dtrace或者systemtap工具统计相关探针的信息. 安装systemtap yum install systemtap kernel-debugi ...

  8. 关于ANDROID模拟器的一些事

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 继上一篇Android Studio VS Eclipse的文章后接着来分享AnDevCo ...

  9. VisualSVN Server 修改用户密码

    VisualSVN Server是非常方便好用的SVN服务器端软件,但有个问题,你在服务器端创建了用户名密码后,用户无法自己修改密码,据说VisualSVN的客户端可以修改用户密码,但客户端是收费软件 ...

  10. jQuery中的观察者模式(Observer Pattern)

    在jQuery中,on方法可以为元素绑定事件,trigger方法可以手动触发事件,围绕这2个方法,我们来体验jQuery中的观察者模式(Observer Pattern). ■ on方法绑定内置事件, ...