STM32F1与STM32CubeIDE编程实例-W25Q-SPI-Flash与SPIFFS移植

W25Q-SPI-Flash与SPIFFS移植

SPIFFS 是用于嵌入式目标上的 SPI NOR 闪存设备的文件系统。 它支持磨损均衡、文件系统一致性检查等。本文将详细介绍如何将SPIFFS移植到STM32F1中。通过前面的文章,我们成功驱动了W25Q SPI Flash,请参考:

在这个基础上,移植SPIFFS就变得很简单了。

1、SPIFFS移植

关于STM32CubeIDE工程创建、配置请参考前面文章:

第一步,下载SPIFFS源码:https://github.com/pellepl/spiffs

第二步,将SPIFFS源码的src目录复制到STM32CubeIDE工程中。
在这里插入图片描述

第三步,添加SPIFFS移植文件,实现SPIFFS适合接口移植。

在src文件中,添加spiffs_port.hspiffs_port.c文件。其内容分别如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/\*
\* spiffs\_port.h
\*
\* Created on: Jun 14, 2022
\* Author: jenson
\*/

#ifndef SPIFFS\_SRC\_SPIFFS\_PORT\_H\_
#define SPIFFS\_SRC\_SPIFFS\_PORT\_H\_

#include "spiffs.h"

extern spiffs spiffs_fs;

int spiffs\_port\_init(void);

#endif /\* SPIFFS\_SRC\_SPIFFS\_PORT\_H\_ \*/


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/\*
\* spiffs\_port.c
\*
\* Created on: Jun 14, 2022
\* Author: jenson
\*/

#include "spiffs.h"
#include "w25qxx/w25qxx\_drv.h"
#include "main.h"
#include "spi.h"
#include <stm32f1xx\_hal.h>
#include <stdio.h>

w25qxx\_t __spiffs_w25qxx;

static int32\_t \_spiffs\_erase(uint32\_t addr, uint32\_t len) {
w25qxx\_erase\_sector(&__spiffs_w25qxx, addr);
return 0;
}

static int32\_t \_spiffs\_read(uint32\_t addr, uint32\_t size, uint8\_t \*dst) {
w25qxx\_read(&__spiffs_w25qxx, dst, addr, size);
return 0;
}

static int32\_t \_spiffs\_write(uint32\_t addr, uint32\_t size, uint8\_t \*dst) {
w25qxx\_write(&__spiffs_w25qxx, dst, addr, size);
return 0;
}

uint8\_t FS_Work_Buf[256 \* 2];
uint8\_t FS_FDS[32 \* 4];
uint8\_t FS_Cache_Buf[(256 + 32) \* 4];

spiffs_config spiffs_cfg;
spiffs spiffs_fs;

int spiffs\_port\_init(void) {
// SPIFFS接口注册
spiffs_cfg.hal_erase_f = _spiffs_erase;
spiffs_cfg.hal_read_f = _spiffs_read;
spiffs_cfg.hal_write_f = _spiffs_write;

// W25Q SPI Flash驱动实现
__spiffs_w25qxx.SPI_CS_Pin = FLASH_CS_Pin;
__spiffs_w25qxx.SPI_CS_Port = FLASH_CS_GPIO_Port;
__spiffs_w25qxx.SPI_Handle = &hspi1;

if (!w25qxx\_init(&__spiffs_w25qxx)) {
return SPIFFS_ERR_NOT_CONFIGURED;
}
// 打印W25Q信息
w25qxx\_display\_info(&__spiffs_w25qxx);

int res = -1;
// 挂载SPIFFS,如果没有找到文件系统,则格式化W25Q和格式化SPIFFS文件系统
if ((res = SPIFFS\_mount(&spiffs_fs, &spiffs_cfg, FS_Work_Buf, FS_FDS,
sizeof(FS_FDS), FS_Cache_Buf, sizeof(FS_Cache_Buf),
NULL)) != SPIFFS_OK
&& SPIFFS\_errno(&spiffs_fs) == SPIFFS_ERR_NOT_A_FS) {
printf("not found SPIFFS ...\n");
printf("erase chip...\r\n");
w25qxx\_erase\_chip(&__spiffs_w25qxx); // 擦除芯片
printf("erase chip done\r\n");
printf("SPIFFS start format ...\r\n");
if (SPIFFS\_format(&spiffs_fs) != SPIFFS_OK) { // 格式化文件系统
printf("SPIFFS format failed: %d\n", SPIFFS\_errno(&spiffs_fs));
return SPIFFS\_errno(&spiffs_fs);
}
printf("SPIFFS format ok\n");
printf("SPIFFS mounting...\n");
// 重新挂载SPIFFS文件系统
res = SPIFFS\_mount(&spiffs_fs, &spiffs_cfg, FS_Work_Buf, FS_FDS,
sizeof(FS_FDS), FS_Cache_Buf, sizeof(FS_Cache_Buf),
NULL);
if (res != SPIFFS_OK) {
printf("SPIFFS mount failed: %d\n", SPIFFS\_errno(&spiffs_fs));
return SPIFFS\_errno(&spiffs_fs);
}
}

printf("SPIFFS mounted\n");
return SPIFFS_OK;
}


实现SPIFFS移植主要步骤如下:

  • 1)注册SPIFFS读、写、擦除回调函数:
1
2
3
4
5
 // SPIFFS接口注册
spiffs_cfg.hal_erase_f = _spiffs_erase;
spiffs_cfg.hal_read_f = _spiffs_read;
spiffs_cfg.hal_write_f = _spiffs_write;

  • 2)初始化W25Q
  • 3)挂载SPIFFS文件系统
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 挂载SPIFFS,如果没有找到文件系统,则格式化W25Q和格式化SPIFFS文件系统
if ((res = SPIFFS\_mount(&spiffs_fs, &spiffs_cfg, FS_Work_Buf, FS_FDS,
sizeof(FS_FDS), FS_Cache_Buf, sizeof(FS_Cache_Buf),
NULL)) != SPIFFS_OK
&& SPIFFS\_errno(&spiffs_fs) == SPIFFS_ERR_NOT_A_FS) {
printf("not found SPIFFS ...\n");
printf("erase chip...\r\n");
w25qxx\_erase\_chip(&__spiffs_w25qxx); // 擦除芯片
printf("erase chip done\r\n");
printf("SPIFFS start format ...\r\n");
if (SPIFFS\_format(&spiffs_fs) != SPIFFS_OK) { // 格式化文件系统
printf("SPIFFS format failed: %d\n", SPIFFS\_errno(&spiffs_fs));
return SPIFFS\_errno(&spiffs_fs);
}
printf("SPIFFS format ok\n");
printf("SPIFFS mounting...\n");
// 重新挂载SPIFFS文件系统
res = SPIFFS\_mount(&spiffs_fs, &spiffs_cfg, FS_Work_Buf, FS_FDS,
sizeof(FS_FDS), FS_Cache_Buf, sizeof(FS_Cache_Buf),
NULL);
if (res != SPIFFS_OK) {
printf("SPIFFS mount failed: %d\n", SPIFFS\_errno(&spiffs_fs));
return SPIFFS\_errno(&spiffs_fs);
}
}

2、SPIFFS调用

在STM32CubeIDE工程和Application目录中,分为添加如下文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/\*
\* spiffs\_demo.h
\*
\* Created on: Jul 12, 2022
\* Author: jenson
\*/

#ifndef SPIFFS\_DEMO\_H\_
#define SPIFFS\_DEMO\_H\_

#include "SPIFFS/src/spiffs.h"
#include "SPIFFS/src/spiffs\_port.h"

void spiffs\_demo(void);


#endif /\* SPIFFS\_DEMO\_H\_ \*/


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/\*
\* spiffs\_demo.c
\*
\* Created on: Jul 12, 2022
\* Author: jenson
\*/

#include "spiffs\_demo.h"
#include <stdio.h>
//#ifdef DEMO\_SPIFFS

#define SPIFFS\_FILE\_SIZE 512
uint8\_t spiffs_tx_buffer[SPIFFS_FILE_SIZE];
uint8\_t spiffs_rx_buffer[SPIFFS_FILE_SIZE];
#define FILE\_NAME "hello.txt"
extern spiffs spiffs_fs;

void spiffs\_read\_test(void) {
uint32\_t total = 0;
uint32\_t used_space = 0;
spiffs_file fd = SPIFFS\_open(&spiffs_fs, FILE_NAME, SPIFFS_RDWR, 0);
if (SPIFFS\_read(&spiffs_fs, fd, spiffs_rx_buffer, SPIFFS_FILE_SIZE) < 0) {
printf("spiffs read\_test errno %d\n", SPIFFS\_errno(&spiffs_fs));
} else {
printf("spiffs read\_test:\r\n%s\r\n", spiffs_rx_buffer);
}
SPIFFS\_close(&spiffs_fs, fd);
SPIFFS\_info(&spiffs_fs, &total, &used_space);
printf("spiffs info:\r\ntotal size = %d,used space = %d\r\n", total,
used_space);
}

void spiffs\_write\_test(void) {

memset(spiffs_tx_buffer, 'A', SPIFFS_FILE_SIZE);

spiffs_file fd = SPIFFS\_open(&spiffs_fs, FILE_NAME,
SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
printf("spiffs write\_test errno %d\n", SPIFFS\_errno(&spiffs_fs));
if (SPIFFS\_write(&spiffs_fs, fd, spiffs_tx_buffer, SPIFFS_FILE_SIZE) < 0) {
printf("spiffs write\_test %d\n", SPIFFS\_errno(&spiffs_fs));
}
SPIFFS\_close(&spiffs_fs, fd);
}

void spiffs\_demo(void) {
int res = spiffs\_port\_init();
if (res != SPIFFS_OK) {
printf("spiffs init faled:(%d)\r\n", res);
while (1)
;
}
spiffs\_write\_test();
spiffs\_read\_test();
}
//#endif


main.c文件中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/\* Private includes ----------------------------------------------------------\*/
/\* USER CODE BEGIN Includes \*/
#include<stdio.h>
#include "w25qxx/w25qxx.h"
#include "spiffs\_demo.h"
/\* USER CODE END Includes \*/

int main(void) {
/\* USER CODE BEGIN 1 \*/

/\* USER CODE END 1 \*/

/\* MCU Configuration--------------------------------------------------------\*/

/\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
HAL\_Init();

/\* USER CODE BEGIN Init \*/

/\* USER CODE END Init \*/

/\* Configure the system clock \*/
SystemClock\_Config();

/\* USER CODE BEGIN SysInit \*/

/\* USER CODE END SysInit \*/

/\* Initialize all configured peripherals \*/
MX\_GPIO\_Init();
MX\_USART1\_UART\_Init();
MX\_SPI1\_Init();
/\* USER CODE BEGIN 2 \*/
spiffs\_demo();
/\* USER CODE END 2 \*/

/\* Infinite loop \*/
/\* USER CODE BEGIN WHILE \*/
while (1) {
/\* USER CODE END WHILE \*/

/\* USER CODE BEGIN 3 \*/
}
/\* USER CODE END 3 \*/
}

运行结果如下:

在这里插入图片描述

文章来源: https://iotsmart.blog.csdn.net/article/details/125822926