embox

Форк
0
/
stm32_qspi_flash_dev.c 
191 строка · 5.4 Кб
1
/**
2
 * @file stm32_qspi_flash_dev.c
3
 * @brief QSPI flash device driver (BSP-based)
4
 * @author Andrew Bursian
5
 * @date 05.05.2023
6
 */
7

8
#include <util/log.h>
9

10
#include <stdio.h>
11
#include <unistd.h>
12
#include <assert.h>
13
#include <string.h>
14
#include <stdbool.h>
15
#include <errno.h>
16

17
#include <util/math.h>
18
#include <util/macro.h>
19

20
//#include <arm/cpu_cache.h>
21
#include <drivers/flash/flash.h>
22
#include <drivers/flash/flash_cache.h>
23

24
#include <framework/mod/options.h>
25

26
#define FLASH_NAME     qspiflash
27

28
#if defined USE_STM32L475E_IOT01
29
#include "stm32l475e_iot01.h"
30
#include "stm32l475e_iot01_qspi.h" // includes "../Components/mx25r6435f/mx25r6435f.h"
31
#define QSPI_FLASH_SIZE MX25R6435F_FLASH_SIZE
32
#define QSPI_BLOCK_SIZE MX25R6435F_SECTOR_SIZE
33
#define QSPI_ERASE_TIME MX25R6435F_SECTOR_ERASE_MAX_TIME
34

35
#elif defined USE_STM32F769I_DISCOVERY
36
#include "stm32f769i_discovery.h"
37
#include "stm32f769i_discovery_qspi.h" // includes "../Components/mx25l512/mx25l512.h"
38
#define QSPI_FLASH_SIZE MX25L512_FLASH_SIZE
39
#define QSPI_BLOCK_SIZE MX25L512_SUBSECTOR_SIZE
40
#define QSPI_ERASE_TIME MX25L512_SUBSECTOR_ERASE_MAX_TIME
41

42
#error Unsupported platform // not tested properly yet
43

44
#else
45
#error Unsupported platform
46
#endif // defined USE_XXX
47

48
FLASH_CACHE_DEF(FLASH_NAME, sizeof(uint32_t), QSPI_BLOCK_SIZE);
49

50
/* reduce flash volume to check it fast */
51
#define	FLASH_CUT OPTION_GET(NUMBER,flash_cut)
52
#if	FLASH_CUT
53
#undef  QSPI_FLASH_SIZE
54
#define QSPI_FLASH_SIZE FLASH_CUT
55
#endif // FLASH_CUT
56

57
#define	QSPI_ERASE_CHECK OPTION_GET(NUMBER,erase_check)
58

59
static int qspi_flash_read(struct flash_dev *dev, uint32_t addr, void *data, size_t len) {
60
	if (addr + len > QSPI_FLASH_SIZE) {
61
		log_error("End address is out of range. addr=0x%x,len=0x%x", addr, len);
62
		return -1;
63
	}
64
	/* read can be unaligned */
65
	memcpy(data, (void *) QSPI_BASE + addr, len);
66
	return len;
67
}
68

69
static inline int poll_flash_busy(int maxms) {
70
	clock_t t0 = clock();
71
	while ((clock()-t0 < CLOCKS_PER_SEC*maxms/1000) && (BSP_QSPI_GetStatus() == QSPI_BUSY)) {
72
		usleep(1000);
73
	}
74
	return (clock()-t0)*1000/CLOCKS_PER_SEC;
75
}
76

77
static int qspi_flash_erase_block(struct flash_dev *dev, uint32_t block) {
78
	int res;
79
log_debug("Block %d", block);
80
	BSP_QSPI_Init(); // exit memory mapped mode
81
	if(poll_flash_busy(100) >= 100) {
82
		log_error("Fail after BSP_QSPI_Init: flash chip busy > 100 ms");
83
		BSP_QSPI_EnableMemoryMappedMode();
84
		return QSPI_BUSY;
85
	}
86

87
#if defined USE_STM32L475E_IOT01
88
	res = BSP_QSPI_Erase_Sector(block);
89
#elif defined USE_STM32F769I_DISCOVERY
90
	res = BSP_QSPI_Erase_Block(block * QSPI_BLOCK_SIZE);
91
#else
92
#error Unsupported platform
93
#endif // defined USE_XXX
94
	if(res != QSPI_OK) {
95
		log_error("Fail erasing block %d", block);
96
		}
97
	if(poll_flash_busy(QSPI_ERASE_TIME) >= QSPI_ERASE_TIME) {
98
		log_error("Fail erasing block: flash chip busy > %d ms", QSPI_ERASE_TIME);
99
		res = QSPI_BUSY;
100
	}
101

102
	BSP_QSPI_EnableMemoryMappedMode();
103
	//dcache_flush_all();	// or use dcache_flush(const void *p, size_t size);
104

105
#if QSPI_ERASE_CHECK
106
	/* check entire block */
107
	for (int a=0; a < QSPI_BLOCK_SIZE; a++) {
108
		if (*(uint8_t*)(QSPI_BASE + block * QSPI_BLOCK_SIZE + a) != 0xff) {
109
			log_error("Erase fail, block %d, offset %d", block, a);
110
			res = QSPI_ERROR;
111
			break;
112
		}
113
	}
114
#endif	
115
log_debug("Ok");
116
	return res;
117
}
118

119
static int qspi_flash_write(struct flash_dev *dev, uint32_t addr, const void *data, size_t len) {
120
	int res;
121
int t0=clock();
122
log_debug("Addr %d, length %d", addr, len);
123
	if (addr + len > QSPI_FLASH_SIZE) {
124
		log_error("End address is out of range. addr=0x%x,len=0x%x", addr, len);
125
		return -1;
126
	}
127

128
	BSP_QSPI_Init(); // exit memory mapped mode
129
log_debug("BSP_QSPI_Init(): %d", clock()-t0);t0=clock();
130
	if(poll_flash_busy(100) >= 100) {
131
		log_error("Fail after BSP_QSPI_Init: flash chip busy > 100 ms");
132
		BSP_QSPI_EnableMemoryMappedMode();
133
		return QSPI_BUSY;
134
	}
135
log_debug("poll_flash_busy(): %d", clock()-t0);t0=clock();
136

137
	res = BSP_QSPI_Write((uint8_t*) data, addr, len);
138
log_debug("BSP_QSPI_Write(): %d", clock()-t0);t0=clock();
139
	if(res != QSPI_OK) {
140
		log_error("QSPI write failed. addr=0x%x,len=0x%x", addr, len);
141
		BSP_QSPI_EnableMemoryMappedMode();
142
		return res;
143
		}
144
	if(poll_flash_busy(10) >= 10) {
145
		log_error("Fail writing block: flash chip busy > 10 ms");
146
		res = QSPI_BUSY;
147
	}
148
log_debug("poll_flash_busy(): %d", clock()-t0);t0=clock();
149

150
	BSP_QSPI_EnableMemoryMappedMode();
151
log_debug("BSP_QSPI_EnableMemoryMappedMode(): %d", clock()-t0);
152
	//dcache_flush_all();	// or use dcache_flush(const void *p, size_t size);
153
log_debug("Ok");
154
	return len;
155
}
156

157
static const struct flash_dev_drv qspi_flash_drv;
158

159
static int qspi_flash_init(struct flash_dev *dev, void *arg) {
160
	static uint32_t qspi_flash_aligned_word;
161
	struct flash_dev *flash;
162

163
	flash = flash_create(MACRO_STRING(FLASH_NAME), QSPI_FLASH_SIZE);
164
	if (flash == NULL) {
165
		log_error("Failed to create flash device!");
166
		return -1;
167
	}
168
	flash->drv = &qspi_flash_drv;
169
	flash->size = QSPI_FLASH_SIZE;
170
	flash->num_block_infos = 1;
171
	flash->block_info[0] = (struct flash_block_info) {
172
		.fbi_start_id = 0,
173
		.block_size = QSPI_BLOCK_SIZE,
174
		.blocks = QSPI_FLASH_SIZE / QSPI_BLOCK_SIZE,
175
	};
176
	flash->fld_aligned_word = &qspi_flash_aligned_word;
177
	flash->fld_word_size = sizeof(qspi_flash_aligned_word);
178

179
	flash->fld_cache = FLASH_CACHE_GET(flash, FLASH_NAME);
180

181
	return 0;
182
}
183

184
static const struct flash_dev_drv qspi_flash_drv = {
185
	.flash_init = qspi_flash_init,
186
	.flash_read = qspi_flash_read,
187
	.flash_erase_block = qspi_flash_erase_block,
188
	.flash_program = qspi_flash_write,
189
};
190

191
FLASH_DEV_DEF(MACRO_STRING(FLASH_NAME), &qspi_flash_drv);
192

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.