1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2016-09-28 armink first version.
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <stdint.h>
12*10465441SEvalZero #include <rtdevice.h>
13*10465441SEvalZero #include "spi_flash.h"
14*10465441SEvalZero #include "spi_flash_sfud.h"
15*10465441SEvalZero
16*10465441SEvalZero #ifdef RT_USING_SFUD
17*10465441SEvalZero
18*10465441SEvalZero #ifdef RT_DEBUG_SFUD
19*10465441SEvalZero #define DEBUG_TRACE rt_kprintf("[SFUD] "); rt_kprintf
20*10465441SEvalZero #else
21*10465441SEvalZero #define DEBUG_TRACE(...)
22*10465441SEvalZero #endif /* RT_DEBUG_SFUD */
23*10465441SEvalZero
24*10465441SEvalZero #ifndef RT_SFUD_DEFAULT_SPI_CFG
25*10465441SEvalZero /* read the JEDEC SFDP command must run at 50 MHz or less */
26*10465441SEvalZero #define RT_SFUD_DEFAULT_SPI_CFG \
27*10465441SEvalZero { \
28*10465441SEvalZero .mode = RT_SPI_MODE_0 | RT_SPI_MSB, \
29*10465441SEvalZero .data_width = 8, \
30*10465441SEvalZero .max_hz = 50 * 1000 * 1000, \
31*10465441SEvalZero }
32*10465441SEvalZero #endif
33*10465441SEvalZero
34*10465441SEvalZero #ifdef SFUD_USING_QSPI
35*10465441SEvalZero #define RT_SFUD_DEFAULT_QSPI_CFG \
36*10465441SEvalZero { \
37*10465441SEvalZero RT_SFUD_DEFAULT_SPI_CFG, \
38*10465441SEvalZero .medium_size = 0x800000, \
39*10465441SEvalZero .ddr_mode = 0, \
40*10465441SEvalZero .qspi_dl_width = 4, \
41*10465441SEvalZero }
42*10465441SEvalZero #endif
43*10465441SEvalZero
44*10465441SEvalZero static char log_buf[RT_CONSOLEBUF_SIZE];
45*10465441SEvalZero
46*10465441SEvalZero void sfud_log_debug(const char *file, const long line, const char *format, ...);
47*10465441SEvalZero
rt_sfud_control(rt_device_t dev,int cmd,void * args)48*10465441SEvalZero static rt_err_t rt_sfud_control(rt_device_t dev, int cmd, void *args) {
49*10465441SEvalZero RT_ASSERT(dev != RT_NULL);
50*10465441SEvalZero
51*10465441SEvalZero switch (cmd) {
52*10465441SEvalZero case RT_DEVICE_CTRL_BLK_GETGEOME: {
53*10465441SEvalZero struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *) args;
54*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
55*10465441SEvalZero
56*10465441SEvalZero if (rtt_dev == RT_NULL || geometry == RT_NULL) {
57*10465441SEvalZero return -RT_ERROR;
58*10465441SEvalZero }
59*10465441SEvalZero
60*10465441SEvalZero geometry->bytes_per_sector = rtt_dev->geometry.bytes_per_sector;
61*10465441SEvalZero geometry->sector_count = rtt_dev->geometry.sector_count;
62*10465441SEvalZero geometry->block_size = rtt_dev->geometry.block_size;
63*10465441SEvalZero break;
64*10465441SEvalZero }
65*10465441SEvalZero case RT_DEVICE_CTRL_BLK_ERASE: {
66*10465441SEvalZero rt_uint32_t *addrs = (rt_uint32_t *) args, start_addr = addrs[0], end_addr = addrs[1], phy_start_addr;
67*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
68*10465441SEvalZero sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data);
69*10465441SEvalZero rt_size_t phy_size;
70*10465441SEvalZero
71*10465441SEvalZero if (addrs == RT_NULL || start_addr > end_addr || rtt_dev == RT_NULL || sfud_dev == RT_NULL) {
72*10465441SEvalZero return -RT_ERROR;
73*10465441SEvalZero }
74*10465441SEvalZero
75*10465441SEvalZero if (end_addr == start_addr) {
76*10465441SEvalZero end_addr ++;
77*10465441SEvalZero }
78*10465441SEvalZero
79*10465441SEvalZero phy_start_addr = start_addr * rtt_dev->geometry.bytes_per_sector;
80*10465441SEvalZero phy_size = (end_addr - start_addr) * rtt_dev->geometry.bytes_per_sector;
81*10465441SEvalZero
82*10465441SEvalZero if (sfud_erase(sfud_dev, phy_start_addr, phy_size) != SFUD_SUCCESS) {
83*10465441SEvalZero return -RT_ERROR;
84*10465441SEvalZero }
85*10465441SEvalZero break;
86*10465441SEvalZero }
87*10465441SEvalZero }
88*10465441SEvalZero
89*10465441SEvalZero return RT_EOK;
90*10465441SEvalZero }
91*10465441SEvalZero
92*10465441SEvalZero
rt_sfud_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)93*10465441SEvalZero static rt_size_t rt_sfud_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) {
94*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
95*10465441SEvalZero sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data);
96*10465441SEvalZero /* change the block device's logic address to physical address */
97*10465441SEvalZero rt_off_t phy_pos = pos * rtt_dev->geometry.bytes_per_sector;
98*10465441SEvalZero rt_size_t phy_size = size * rtt_dev->geometry.bytes_per_sector;
99*10465441SEvalZero
100*10465441SEvalZero if (sfud_read(sfud_dev, phy_pos, phy_size, buffer) != SFUD_SUCCESS) {
101*10465441SEvalZero return 0;
102*10465441SEvalZero } else {
103*10465441SEvalZero return size;
104*10465441SEvalZero }
105*10465441SEvalZero }
106*10465441SEvalZero
rt_sfud_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)107*10465441SEvalZero static rt_size_t rt_sfud_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) {
108*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (dev->user_data);
109*10465441SEvalZero sfud_flash *sfud_dev = (sfud_flash *) (rtt_dev->user_data);
110*10465441SEvalZero /* change the block device's logic address to physical address */
111*10465441SEvalZero rt_off_t phy_pos = pos * rtt_dev->geometry.bytes_per_sector;
112*10465441SEvalZero rt_size_t phy_size = size * rtt_dev->geometry.bytes_per_sector;
113*10465441SEvalZero
114*10465441SEvalZero if (sfud_erase_write(sfud_dev, phy_pos, phy_size, buffer) != SFUD_SUCCESS) {
115*10465441SEvalZero return 0;
116*10465441SEvalZero } else {
117*10465441SEvalZero return size;
118*10465441SEvalZero }
119*10465441SEvalZero }
120*10465441SEvalZero
121*10465441SEvalZero /**
122*10465441SEvalZero * SPI write data then read data
123*10465441SEvalZero */
spi_write_read(const sfud_spi * spi,const uint8_t * write_buf,size_t write_size,uint8_t * read_buf,size_t read_size)124*10465441SEvalZero static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
125*10465441SEvalZero size_t read_size) {
126*10465441SEvalZero sfud_err result = SFUD_SUCCESS;
127*10465441SEvalZero sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
128*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
129*10465441SEvalZero #ifdef SFUD_USING_QSPI
130*10465441SEvalZero struct rt_qspi_device *qspi_dev = RT_NULL;
131*10465441SEvalZero #endif
132*10465441SEvalZero if (write_size) {
133*10465441SEvalZero RT_ASSERT(write_buf);
134*10465441SEvalZero }
135*10465441SEvalZero if (read_size) {
136*10465441SEvalZero RT_ASSERT(read_buf);
137*10465441SEvalZero }
138*10465441SEvalZero #ifdef SFUD_USING_QSPI
139*10465441SEvalZero if(rtt_dev->rt_spi_device->bus->mode & RT_SPI_BUS_MODE_QSPI) {
140*10465441SEvalZero qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
141*10465441SEvalZero if (write_size && read_size) {
142*10465441SEvalZero if (rt_qspi_send_then_recv(qspi_dev, write_buf, write_size, read_buf, read_size) == 0) {
143*10465441SEvalZero result = SFUD_ERR_TIMEOUT;
144*10465441SEvalZero }
145*10465441SEvalZero } else if (write_size) {
146*10465441SEvalZero if (rt_qspi_send(qspi_dev, write_buf, write_size) == 0) {
147*10465441SEvalZero result = SFUD_ERR_TIMEOUT;
148*10465441SEvalZero }
149*10465441SEvalZero }
150*10465441SEvalZero }
151*10465441SEvalZero else
152*10465441SEvalZero #endif
153*10465441SEvalZero {
154*10465441SEvalZero if (write_size && read_size) {
155*10465441SEvalZero if (rt_spi_send_then_recv(rtt_dev->rt_spi_device, write_buf, write_size, read_buf, read_size) != RT_EOK) {
156*10465441SEvalZero result = SFUD_ERR_TIMEOUT;
157*10465441SEvalZero }
158*10465441SEvalZero } else if (write_size) {
159*10465441SEvalZero if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) == 0) {
160*10465441SEvalZero result = SFUD_ERR_TIMEOUT;
161*10465441SEvalZero }
162*10465441SEvalZero } else {
163*10465441SEvalZero if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) == 0) {
164*10465441SEvalZero result = SFUD_ERR_TIMEOUT;
165*10465441SEvalZero }
166*10465441SEvalZero }
167*10465441SEvalZero }
168*10465441SEvalZero
169*10465441SEvalZero return result;
170*10465441SEvalZero }
171*10465441SEvalZero
172*10465441SEvalZero #ifdef SFUD_USING_QSPI
173*10465441SEvalZero /**
174*10465441SEvalZero * QSPI fast read data
175*10465441SEvalZero */
qspi_read(const struct __sfud_spi * spi,uint32_t addr,sfud_qspi_read_cmd_format * qspi_read_cmd_format,uint8_t * read_buf,size_t read_size)176*10465441SEvalZero static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format, uint8_t *read_buf, size_t read_size) {
177*10465441SEvalZero struct rt_qspi_message message;
178*10465441SEvalZero sfud_err result = SFUD_SUCCESS;
179*10465441SEvalZero
180*10465441SEvalZero sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
181*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
182*10465441SEvalZero struct rt_qspi_device *qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
183*10465441SEvalZero
184*10465441SEvalZero /* set message struct */
185*10465441SEvalZero message.instruction.content = qspi_read_cmd_format->instruction;
186*10465441SEvalZero message.instruction.qspi_lines = qspi_read_cmd_format->instruction_lines;
187*10465441SEvalZero
188*10465441SEvalZero message.address.content = addr;
189*10465441SEvalZero message.address.size = qspi_read_cmd_format->address_size;
190*10465441SEvalZero message.address.qspi_lines = qspi_read_cmd_format->address_lines;
191*10465441SEvalZero
192*10465441SEvalZero message.alternate_bytes.content = 0;
193*10465441SEvalZero message.alternate_bytes.size = 0;
194*10465441SEvalZero message.alternate_bytes.qspi_lines = 0;
195*10465441SEvalZero
196*10465441SEvalZero message.dummy_cycles = qspi_read_cmd_format->dummy_cycles;
197*10465441SEvalZero
198*10465441SEvalZero message.parent.send_buf = RT_NULL;
199*10465441SEvalZero message.parent.recv_buf = read_buf;
200*10465441SEvalZero message.parent.length = read_size;
201*10465441SEvalZero message.parent.cs_release = 1;
202*10465441SEvalZero message.parent.cs_take = 1;
203*10465441SEvalZero message.qspi_data_lines = qspi_read_cmd_format->data_lines;
204*10465441SEvalZero
205*10465441SEvalZero if (rt_qspi_transfer_message(qspi_dev, &message) != read_size) {
206*10465441SEvalZero result = SFUD_ERR_TIMEOUT;
207*10465441SEvalZero }
208*10465441SEvalZero
209*10465441SEvalZero return result;
210*10465441SEvalZero }
211*10465441SEvalZero #endif
212*10465441SEvalZero
spi_lock(const sfud_spi * spi)213*10465441SEvalZero static void spi_lock(const sfud_spi *spi) {
214*10465441SEvalZero sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
215*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
216*10465441SEvalZero
217*10465441SEvalZero rt_mutex_take(&(rtt_dev->lock), RT_WAITING_FOREVER);
218*10465441SEvalZero }
219*10465441SEvalZero
spi_unlock(const sfud_spi * spi)220*10465441SEvalZero static void spi_unlock(const sfud_spi *spi) {
221*10465441SEvalZero sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
222*10465441SEvalZero struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
223*10465441SEvalZero
224*10465441SEvalZero rt_mutex_release(&(rtt_dev->lock));
225*10465441SEvalZero }
226*10465441SEvalZero
retry_delay_100us(void)227*10465441SEvalZero static void retry_delay_100us(void) {
228*10465441SEvalZero /* 100 microsecond delay */
229*10465441SEvalZero rt_thread_delay((RT_TICK_PER_SECOND * 1 + 9999) / 10000);
230*10465441SEvalZero }
231*10465441SEvalZero
232*10465441SEvalZero /**
233*10465441SEvalZero * This function is print debug info.
234*10465441SEvalZero *
235*10465441SEvalZero * @param file the file which has call this function
236*10465441SEvalZero * @param line the line number which has call this function
237*10465441SEvalZero * @param format output format
238*10465441SEvalZero * @param ... args
239*10465441SEvalZero */
sfud_log_debug(const char * file,const long line,const char * format,...)240*10465441SEvalZero void sfud_log_debug(const char *file, const long line, const char *format, ...) {
241*10465441SEvalZero va_list args;
242*10465441SEvalZero
243*10465441SEvalZero /* args point to the first variable parameter */
244*10465441SEvalZero va_start(args, format);
245*10465441SEvalZero rt_kprintf("[SFUD] (%s:%ld) ", file, line);
246*10465441SEvalZero /* must use vprintf to print */
247*10465441SEvalZero rt_vsnprintf(log_buf, sizeof(log_buf), format, args);
248*10465441SEvalZero rt_kprintf("%s\n", log_buf);
249*10465441SEvalZero va_end(args);
250*10465441SEvalZero }
251*10465441SEvalZero
252*10465441SEvalZero /**
253*10465441SEvalZero * This function is print routine info.
254*10465441SEvalZero *
255*10465441SEvalZero * @param format output format
256*10465441SEvalZero * @param ... args
257*10465441SEvalZero */
sfud_log_info(const char * format,...)258*10465441SEvalZero void sfud_log_info(const char *format, ...) {
259*10465441SEvalZero va_list args;
260*10465441SEvalZero
261*10465441SEvalZero /* args point to the first variable parameter */
262*10465441SEvalZero va_start(args, format);
263*10465441SEvalZero rt_kprintf("[SFUD] ");
264*10465441SEvalZero /* must use vprintf to print */
265*10465441SEvalZero rt_vsnprintf(log_buf, sizeof(log_buf), format, args);
266*10465441SEvalZero rt_kprintf("%s\n", log_buf);
267*10465441SEvalZero va_end(args);
268*10465441SEvalZero }
269*10465441SEvalZero
sfud_spi_port_init(sfud_flash * flash)270*10465441SEvalZero sfud_err sfud_spi_port_init(sfud_flash *flash) {
271*10465441SEvalZero sfud_err result = SFUD_SUCCESS;
272*10465441SEvalZero
273*10465441SEvalZero /* port SPI device interface */
274*10465441SEvalZero flash->spi.wr = spi_write_read;
275*10465441SEvalZero #ifdef SFUD_USING_QSPI
276*10465441SEvalZero flash->spi.qspi_read = qspi_read;
277*10465441SEvalZero #endif
278*10465441SEvalZero flash->spi.lock = spi_lock;
279*10465441SEvalZero flash->spi.unlock = spi_unlock;
280*10465441SEvalZero flash->spi.user_data = flash;
281*10465441SEvalZero if (RT_TICK_PER_SECOND < 1000) {
282*10465441SEvalZero rt_kprintf("[SFUD] Warning: The OS tick(%d) is less than 1000. So the flash write will take more time.\n", RT_TICK_PER_SECOND);
283*10465441SEvalZero }
284*10465441SEvalZero /* 100 microsecond delay */
285*10465441SEvalZero flash->retry.delay = retry_delay_100us;
286*10465441SEvalZero /* 60 seconds timeout */
287*10465441SEvalZero flash->retry.times = 60 * 10000;
288*10465441SEvalZero
289*10465441SEvalZero return result;
290*10465441SEvalZero }
291*10465441SEvalZero
292*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
293*10465441SEvalZero const static struct rt_device_ops flash_device_ops =
294*10465441SEvalZero {
295*10465441SEvalZero RT_NULL,
296*10465441SEvalZero RT_NULL,
297*10465441SEvalZero RT_NULL,
298*10465441SEvalZero rt_sfud_read,
299*10465441SEvalZero rt_sfud_write,
300*10465441SEvalZero rt_sfud_control
301*10465441SEvalZero };
302*10465441SEvalZero #endif
303*10465441SEvalZero
304*10465441SEvalZero /**
305*10465441SEvalZero * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device.
306*10465441SEvalZero *
307*10465441SEvalZero * @param spi_flash_dev_name the name which will create SPI flash device
308*10465441SEvalZero * @param spi_dev_name using SPI device name
309*10465441SEvalZero *
310*10465441SEvalZero * @return probed SPI flash device, probe failed will return RT_NULL
311*10465441SEvalZero */
rt_sfud_flash_probe(const char * spi_flash_dev_name,const char * spi_dev_name)312*10465441SEvalZero rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name) {
313*10465441SEvalZero rt_spi_flash_device_t rtt_dev = RT_NULL;
314*10465441SEvalZero sfud_flash *sfud_dev = RT_NULL;
315*10465441SEvalZero char *spi_flash_dev_name_bak = RT_NULL, *spi_dev_name_bak = RT_NULL;
316*10465441SEvalZero /* using default flash SPI configuration for initialize SPI Flash
317*10465441SEvalZero * @note you also can change the SPI to other configuration after initialized finish */
318*10465441SEvalZero struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG;
319*10465441SEvalZero extern sfud_err sfud_device_init(sfud_flash *flash);
320*10465441SEvalZero #ifdef SFUD_USING_QSPI
321*10465441SEvalZero struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG;
322*10465441SEvalZero struct rt_qspi_device *qspi_dev = RT_NULL;
323*10465441SEvalZero #endif
324*10465441SEvalZero
325*10465441SEvalZero RT_ASSERT(spi_flash_dev_name);
326*10465441SEvalZero RT_ASSERT(spi_dev_name);
327*10465441SEvalZero
328*10465441SEvalZero rtt_dev = (rt_spi_flash_device_t) rt_malloc(sizeof(struct spi_flash_device));
329*10465441SEvalZero sfud_dev = (sfud_flash_t) rt_malloc(sizeof(sfud_flash));
330*10465441SEvalZero spi_flash_dev_name_bak = (char *) rt_malloc(rt_strlen(spi_flash_dev_name) + 1);
331*10465441SEvalZero spi_dev_name_bak = (char *) rt_malloc(rt_strlen(spi_dev_name) + 1);
332*10465441SEvalZero
333*10465441SEvalZero if (rtt_dev) {
334*10465441SEvalZero rt_memset(rtt_dev, 0, sizeof(struct spi_flash_device));
335*10465441SEvalZero /* initialize lock */
336*10465441SEvalZero rt_mutex_init(&(rtt_dev->lock), spi_flash_dev_name, RT_IPC_FLAG_FIFO);
337*10465441SEvalZero }
338*10465441SEvalZero
339*10465441SEvalZero if (rtt_dev && sfud_dev && spi_flash_dev_name_bak && spi_dev_name_bak) {
340*10465441SEvalZero rt_memset(sfud_dev, 0, sizeof(sfud_flash));
341*10465441SEvalZero rt_strncpy(spi_flash_dev_name_bak, spi_flash_dev_name, rt_strlen(spi_flash_dev_name));
342*10465441SEvalZero rt_strncpy(spi_dev_name_bak, spi_dev_name, rt_strlen(spi_dev_name));
343*10465441SEvalZero /* make string end sign */
344*10465441SEvalZero spi_flash_dev_name_bak[rt_strlen(spi_flash_dev_name)] = '\0';
345*10465441SEvalZero spi_dev_name_bak[rt_strlen(spi_dev_name)] = '\0';
346*10465441SEvalZero /* SPI configure */
347*10465441SEvalZero {
348*10465441SEvalZero /* RT-Thread SPI device initialize */
349*10465441SEvalZero rtt_dev->rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
350*10465441SEvalZero if (rtt_dev->rt_spi_device == RT_NULL || rtt_dev->rt_spi_device->parent.type != RT_Device_Class_SPIDevice) {
351*10465441SEvalZero rt_kprintf("ERROR: SPI device %s not found!\n", spi_dev_name);
352*10465441SEvalZero goto error;
353*10465441SEvalZero }
354*10465441SEvalZero sfud_dev->spi.name = spi_dev_name_bak;
355*10465441SEvalZero
356*10465441SEvalZero #ifdef SFUD_USING_QSPI
357*10465441SEvalZero /* set the qspi line number and configure the QSPI bus */
358*10465441SEvalZero if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
359*10465441SEvalZero qspi_dev = (struct rt_qspi_device *)rtt_dev->rt_spi_device;
360*10465441SEvalZero qspi_cfg.qspi_dl_width = qspi_dev->config.qspi_dl_width;
361*10465441SEvalZero rt_qspi_configure(qspi_dev, &qspi_cfg);
362*10465441SEvalZero }
363*10465441SEvalZero else
364*10465441SEvalZero #endif
365*10465441SEvalZero rt_spi_configure(rtt_dev->rt_spi_device, &cfg);
366*10465441SEvalZero }
367*10465441SEvalZero /* SFUD flash device initialize */
368*10465441SEvalZero {
369*10465441SEvalZero sfud_dev->name = spi_flash_dev_name_bak;
370*10465441SEvalZero /* accessed each other */
371*10465441SEvalZero rtt_dev->user_data = sfud_dev;
372*10465441SEvalZero rtt_dev->rt_spi_device->user_data = rtt_dev;
373*10465441SEvalZero rtt_dev->flash_device.user_data = rtt_dev;
374*10465441SEvalZero sfud_dev->user_data = rtt_dev;
375*10465441SEvalZero /* initialize SFUD device */
376*10465441SEvalZero if (sfud_device_init(sfud_dev) != SFUD_SUCCESS) {
377*10465441SEvalZero rt_kprintf("ERROR: SPI flash probe failed by SPI device %s.\n", spi_dev_name);
378*10465441SEvalZero goto error;
379*10465441SEvalZero }
380*10465441SEvalZero /* when initialize success, then copy SFUD flash device's geometry to RT-Thread SPI flash device */
381*10465441SEvalZero rtt_dev->geometry.sector_count = sfud_dev->chip.capacity / sfud_dev->chip.erase_gran;
382*10465441SEvalZero rtt_dev->geometry.bytes_per_sector = sfud_dev->chip.erase_gran;
383*10465441SEvalZero rtt_dev->geometry.block_size = sfud_dev->chip.erase_gran;
384*10465441SEvalZero #ifdef SFUD_USING_QSPI
385*10465441SEvalZero /* reconfigure the QSPI bus for medium size */
386*10465441SEvalZero if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
387*10465441SEvalZero qspi_cfg.medium_size = sfud_dev->chip.capacity;
388*10465441SEvalZero rt_qspi_configure(qspi_dev, &qspi_cfg);
389*10465441SEvalZero if(qspi_dev->enter_qspi_mode != RT_NULL)
390*10465441SEvalZero qspi_dev->enter_qspi_mode(qspi_dev);
391*10465441SEvalZero }
392*10465441SEvalZero /* set data lines width */
393*10465441SEvalZero sfud_qspi_fast_read_enable(sfud_dev, qspi_dev->config.qspi_dl_width);
394*10465441SEvalZero #endif /* SFUD_USING_QSPI */
395*10465441SEvalZero }
396*10465441SEvalZero
397*10465441SEvalZero /* register device */
398*10465441SEvalZero rtt_dev->flash_device.type = RT_Device_Class_Block;
399*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
400*10465441SEvalZero rtt_dev->flash_device.ops = &flash_device_ops;
401*10465441SEvalZero #else
402*10465441SEvalZero rtt_dev->flash_device.init = RT_NULL;
403*10465441SEvalZero rtt_dev->flash_device.open = RT_NULL;
404*10465441SEvalZero rtt_dev->flash_device.close = RT_NULL;
405*10465441SEvalZero rtt_dev->flash_device.read = rt_sfud_read;
406*10465441SEvalZero rtt_dev->flash_device.write = rt_sfud_write;
407*10465441SEvalZero rtt_dev->flash_device.control = rt_sfud_control;
408*10465441SEvalZero #endif
409*10465441SEvalZero
410*10465441SEvalZero rt_device_register(&(rtt_dev->flash_device), spi_flash_dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
411*10465441SEvalZero
412*10465441SEvalZero DEBUG_TRACE("Probe SPI flash %s by SPI device %s success.\n",spi_flash_dev_name, spi_dev_name);
413*10465441SEvalZero return rtt_dev;
414*10465441SEvalZero } else {
415*10465441SEvalZero rt_kprintf("ERROR: Low memory.\n");
416*10465441SEvalZero goto error;
417*10465441SEvalZero }
418*10465441SEvalZero
419*10465441SEvalZero error:
420*10465441SEvalZero
421*10465441SEvalZero if (rtt_dev) {
422*10465441SEvalZero rt_mutex_detach(&(rtt_dev->lock));
423*10465441SEvalZero }
424*10465441SEvalZero /* may be one of objects memory was malloc success, so need free all */
425*10465441SEvalZero rt_free(rtt_dev);
426*10465441SEvalZero rt_free(sfud_dev);
427*10465441SEvalZero rt_free(spi_flash_dev_name_bak);
428*10465441SEvalZero rt_free(spi_dev_name_bak);
429*10465441SEvalZero
430*10465441SEvalZero return RT_NULL;
431*10465441SEvalZero }
432*10465441SEvalZero
433*10465441SEvalZero /**
434*10465441SEvalZero * Delete SPI flash device
435*10465441SEvalZero *
436*10465441SEvalZero * @param spi_flash_dev SPI flash device
437*10465441SEvalZero *
438*10465441SEvalZero * @return the operation status, RT_EOK on successful
439*10465441SEvalZero */
rt_sfud_flash_delete(rt_spi_flash_device_t spi_flash_dev)440*10465441SEvalZero rt_err_t rt_sfud_flash_delete(rt_spi_flash_device_t spi_flash_dev) {
441*10465441SEvalZero sfud_flash *sfud_flash_dev = (sfud_flash *) (spi_flash_dev->user_data);
442*10465441SEvalZero
443*10465441SEvalZero RT_ASSERT(spi_flash_dev);
444*10465441SEvalZero RT_ASSERT(sfud_flash_dev);
445*10465441SEvalZero
446*10465441SEvalZero rt_device_unregister(&(spi_flash_dev->flash_device));
447*10465441SEvalZero
448*10465441SEvalZero rt_mutex_detach(&(spi_flash_dev->lock));
449*10465441SEvalZero
450*10465441SEvalZero rt_free(sfud_flash_dev->spi.name);
451*10465441SEvalZero rt_free(sfud_flash_dev->name);
452*10465441SEvalZero rt_free(sfud_flash_dev);
453*10465441SEvalZero rt_free(spi_flash_dev);
454*10465441SEvalZero
455*10465441SEvalZero return RT_EOK;
456*10465441SEvalZero }
457*10465441SEvalZero
rt_sfud_flash_find(const char * spi_dev_name)458*10465441SEvalZero sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name)
459*10465441SEvalZero {
460*10465441SEvalZero rt_spi_flash_device_t rtt_dev = RT_NULL;
461*10465441SEvalZero struct rt_spi_device *rt_spi_device = RT_NULL;
462*10465441SEvalZero sfud_flash_t sfud_dev = RT_NULL;
463*10465441SEvalZero
464*10465441SEvalZero rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
465*10465441SEvalZero if (rt_spi_device == RT_NULL || rt_spi_device->parent.type != RT_Device_Class_SPIDevice)
466*10465441SEvalZero {
467*10465441SEvalZero rt_kprintf("ERROR: SPI device %s not found!\n", spi_dev_name);
468*10465441SEvalZero goto error;
469*10465441SEvalZero }
470*10465441SEvalZero
471*10465441SEvalZero rtt_dev = (rt_spi_flash_device_t)(rt_spi_device->user_data);
472*10465441SEvalZero if (rtt_dev && rtt_dev->user_data)
473*10465441SEvalZero {
474*10465441SEvalZero sfud_dev = (sfud_flash_t)(rtt_dev->user_data);
475*10465441SEvalZero return sfud_dev;
476*10465441SEvalZero }
477*10465441SEvalZero else
478*10465441SEvalZero {
479*10465441SEvalZero rt_kprintf("ERROR: SFUD flash device not found!\n");
480*10465441SEvalZero goto error;
481*10465441SEvalZero }
482*10465441SEvalZero
483*10465441SEvalZero error:
484*10465441SEvalZero return RT_NULL;
485*10465441SEvalZero }
486*10465441SEvalZero
487*10465441SEvalZero #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
488*10465441SEvalZero
489*10465441SEvalZero #include <finsh.h>
490*10465441SEvalZero
sf(uint8_t argc,char ** argv)491*10465441SEvalZero static void sf(uint8_t argc, char **argv) {
492*10465441SEvalZero
493*10465441SEvalZero #define CMD_PROBE_INDEX 0
494*10465441SEvalZero #define CMD_READ_INDEX 1
495*10465441SEvalZero #define CMD_WRITE_INDEX 2
496*10465441SEvalZero #define CMD_ERASE_INDEX 3
497*10465441SEvalZero #define CMD_RW_STATUS_INDEX 4
498*10465441SEvalZero #define CMD_BENCH_INDEX 5
499*10465441SEvalZero
500*10465441SEvalZero sfud_err result = SFUD_SUCCESS;
501*10465441SEvalZero static const sfud_flash *sfud_dev = NULL;
502*10465441SEvalZero static rt_spi_flash_device_t rtt_dev = NULL, rtt_dev_bak = NULL;
503*10465441SEvalZero size_t i = 0;
504*10465441SEvalZero
505*10465441SEvalZero const char* sf_help_info[] = {
506*10465441SEvalZero [CMD_PROBE_INDEX] = "sf probe [spi_device] - probe and init SPI flash by given 'spi_device'",
507*10465441SEvalZero [CMD_READ_INDEX] = "sf read addr size - read 'size' bytes starting at 'addr'",
508*10465441SEvalZero [CMD_WRITE_INDEX] = "sf write addr data1 ... dataN - write some bytes 'data' to flash starting at 'addr'",
509*10465441SEvalZero [CMD_ERASE_INDEX] = "sf erase addr size - erase 'size' bytes starting at 'addr'",
510*10465441SEvalZero [CMD_RW_STATUS_INDEX] = "sf status [<volatile> <status>] - read or write '1:volatile|0:non-volatile' 'status'",
511*10465441SEvalZero [CMD_BENCH_INDEX] = "sf bench - full chip benchmark. DANGER: It will erase full chip!",
512*10465441SEvalZero };
513*10465441SEvalZero
514*10465441SEvalZero if (argc < 2) {
515*10465441SEvalZero rt_kprintf("Usage:\n");
516*10465441SEvalZero for (i = 0; i < sizeof(sf_help_info) / sizeof(char*); i++) {
517*10465441SEvalZero rt_kprintf("%s\n", sf_help_info[i]);
518*10465441SEvalZero }
519*10465441SEvalZero rt_kprintf("\n");
520*10465441SEvalZero } else {
521*10465441SEvalZero const char *operator = argv[1];
522*10465441SEvalZero uint32_t addr, size;
523*10465441SEvalZero
524*10465441SEvalZero if (!strcmp(operator, "probe")) {
525*10465441SEvalZero if (argc < 3) {
526*10465441SEvalZero rt_kprintf("Usage: %s.\n", sf_help_info[CMD_PROBE_INDEX]);
527*10465441SEvalZero } else {
528*10465441SEvalZero char *spi_dev_name = argv[2];
529*10465441SEvalZero rtt_dev_bak = rtt_dev;
530*10465441SEvalZero
531*10465441SEvalZero /* delete the old SPI flash device */
532*10465441SEvalZero if(rtt_dev_bak) {
533*10465441SEvalZero rt_sfud_flash_delete(rtt_dev_bak);
534*10465441SEvalZero }
535*10465441SEvalZero
536*10465441SEvalZero rtt_dev = rt_sfud_flash_probe("sf_cmd", spi_dev_name);
537*10465441SEvalZero if (!rtt_dev) {
538*10465441SEvalZero return;
539*10465441SEvalZero }
540*10465441SEvalZero
541*10465441SEvalZero sfud_dev = (sfud_flash_t)rtt_dev->user_data;
542*10465441SEvalZero if (sfud_dev->chip.capacity < 1024 * 1024) {
543*10465441SEvalZero rt_kprintf("%d KB %s is current selected device.\n", sfud_dev->chip.capacity / 1024, sfud_dev->name);
544*10465441SEvalZero } else {
545*10465441SEvalZero rt_kprintf("%d MB %s is current selected device.\n", sfud_dev->chip.capacity / 1024 / 1024,
546*10465441SEvalZero sfud_dev->name);
547*10465441SEvalZero }
548*10465441SEvalZero }
549*10465441SEvalZero } else {
550*10465441SEvalZero if (!sfud_dev) {
551*10465441SEvalZero rt_kprintf("No flash device selected. Please run 'sf probe'.\n");
552*10465441SEvalZero return;
553*10465441SEvalZero }
554*10465441SEvalZero if (!rt_strcmp(operator, "read")) {
555*10465441SEvalZero if (argc < 4) {
556*10465441SEvalZero rt_kprintf("Usage: %s.\n", sf_help_info[CMD_READ_INDEX]);
557*10465441SEvalZero return;
558*10465441SEvalZero } else {
559*10465441SEvalZero addr = atol(argv[2]);
560*10465441SEvalZero size = atol(argv[3]);
561*10465441SEvalZero uint8_t *data = rt_malloc(size);
562*10465441SEvalZero if (data) {
563*10465441SEvalZero result = sfud_read(sfud_dev, addr, size, data);
564*10465441SEvalZero if (result == SFUD_SUCCESS) {
565*10465441SEvalZero rt_kprintf("Read the %s flash data success. Start from 0x%08X, size is %ld. The data is:\n",
566*10465441SEvalZero sfud_dev->name, addr, size);
567*10465441SEvalZero rt_kprintf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
568*10465441SEvalZero for (i = 0; i < size; i++) {
569*10465441SEvalZero if (i % 16 == 0) {
570*10465441SEvalZero rt_kprintf("[%08X] ", addr + i);
571*10465441SEvalZero }
572*10465441SEvalZero rt_kprintf("%02X ", data[i]);
573*10465441SEvalZero if (((i + 1) % 16 == 0) || i == size - 1) {
574*10465441SEvalZero rt_kprintf("\n");
575*10465441SEvalZero }
576*10465441SEvalZero }
577*10465441SEvalZero rt_kprintf("\n");
578*10465441SEvalZero }
579*10465441SEvalZero rt_free(data);
580*10465441SEvalZero } else {
581*10465441SEvalZero rt_kprintf("Low memory!\n");
582*10465441SEvalZero }
583*10465441SEvalZero }
584*10465441SEvalZero } else if (!rt_strcmp(operator, "write")) {
585*10465441SEvalZero if (argc < 4) {
586*10465441SEvalZero rt_kprintf("Usage: %s.\n", sf_help_info[CMD_WRITE_INDEX]);
587*10465441SEvalZero return;
588*10465441SEvalZero } else {
589*10465441SEvalZero addr = atol(argv[2]);
590*10465441SEvalZero size = argc - 3;
591*10465441SEvalZero uint8_t *data = rt_malloc(size);
592*10465441SEvalZero if (data) {
593*10465441SEvalZero for (i = 0; i < size; i++) {
594*10465441SEvalZero data[i] = atoi(argv[3 + i]);
595*10465441SEvalZero }
596*10465441SEvalZero result = sfud_write(sfud_dev, addr, size, data);
597*10465441SEvalZero if (result == SFUD_SUCCESS) {
598*10465441SEvalZero rt_kprintf("Write the %s flash data success. Start from 0x%08X, size is %ld.\n",
599*10465441SEvalZero sfud_dev->name, addr, size);
600*10465441SEvalZero rt_kprintf("Write data: ");
601*10465441SEvalZero for (i = 0; i < size; i++) {
602*10465441SEvalZero rt_kprintf("%d ", data[i]);
603*10465441SEvalZero }
604*10465441SEvalZero rt_kprintf(".\n");
605*10465441SEvalZero }
606*10465441SEvalZero rt_free(data);
607*10465441SEvalZero } else {
608*10465441SEvalZero rt_kprintf("Low memory!\n");
609*10465441SEvalZero }
610*10465441SEvalZero }
611*10465441SEvalZero } else if (!rt_strcmp(operator, "erase")) {
612*10465441SEvalZero if (argc < 4) {
613*10465441SEvalZero rt_kprintf("Usage: %s.\n", sf_help_info[CMD_ERASE_INDEX]);
614*10465441SEvalZero return;
615*10465441SEvalZero } else {
616*10465441SEvalZero addr = atol(argv[2]);
617*10465441SEvalZero size = atol(argv[3]);
618*10465441SEvalZero result = sfud_erase(sfud_dev, addr, size);
619*10465441SEvalZero if (result == SFUD_SUCCESS) {
620*10465441SEvalZero rt_kprintf("Erase the %s flash data success. Start from 0x%08X, size is %ld.\n", sfud_dev->name,
621*10465441SEvalZero addr, size);
622*10465441SEvalZero }
623*10465441SEvalZero }
624*10465441SEvalZero } else if (!rt_strcmp(operator, "status")) {
625*10465441SEvalZero if (argc < 3) {
626*10465441SEvalZero uint8_t status;
627*10465441SEvalZero result = sfud_read_status(sfud_dev, &status);
628*10465441SEvalZero if (result == SFUD_SUCCESS) {
629*10465441SEvalZero rt_kprintf("The %s flash status register current value is 0x%02X.\n", sfud_dev->name, status);
630*10465441SEvalZero }
631*10465441SEvalZero } else if (argc == 4) {
632*10465441SEvalZero bool is_volatile = atoi(argv[2]);
633*10465441SEvalZero uint8_t status = atoi(argv[3]);
634*10465441SEvalZero result = sfud_write_status(sfud_dev, is_volatile, status);
635*10465441SEvalZero if (result == SFUD_SUCCESS) {
636*10465441SEvalZero rt_kprintf("Write the %s flash status register to 0x%02X success.\n", sfud_dev->name, status);
637*10465441SEvalZero }
638*10465441SEvalZero } else {
639*10465441SEvalZero rt_kprintf("Usage: %s.\n", sf_help_info[CMD_RW_STATUS_INDEX]);
640*10465441SEvalZero return;
641*10465441SEvalZero }
642*10465441SEvalZero } else if (!rt_strcmp(operator, "bench")) {
643*10465441SEvalZero if ((argc > 2 && rt_strcmp(argv[2], "yes")) || argc < 3) {
644*10465441SEvalZero rt_kprintf("DANGER: It will erase full chip! Please run 'sf bench yes'.\n");
645*10465441SEvalZero return;
646*10465441SEvalZero }
647*10465441SEvalZero /* full chip benchmark test */
648*10465441SEvalZero addr = 0;
649*10465441SEvalZero size = sfud_dev->chip.capacity;
650*10465441SEvalZero uint32_t start_time, time_cast;
651*10465441SEvalZero size_t write_size = SFUD_WRITE_MAX_PAGE_SIZE, read_size = SFUD_WRITE_MAX_PAGE_SIZE;
652*10465441SEvalZero uint8_t *write_data = rt_malloc(write_size), *read_data = rt_malloc(read_size);
653*10465441SEvalZero
654*10465441SEvalZero if (write_data && read_data) {
655*10465441SEvalZero rt_memset(write_data, 0x55, write_size);
656*10465441SEvalZero /* benchmark testing */
657*10465441SEvalZero rt_kprintf("Erasing the %s %ld bytes data, waiting...\n", sfud_dev->name, size);
658*10465441SEvalZero start_time = rt_tick_get();
659*10465441SEvalZero result = sfud_erase(sfud_dev, addr, size);
660*10465441SEvalZero if (result == SFUD_SUCCESS) {
661*10465441SEvalZero time_cast = rt_tick_get() - start_time;
662*10465441SEvalZero rt_kprintf("Erase benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND,
663*10465441SEvalZero time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
664*10465441SEvalZero } else {
665*10465441SEvalZero rt_kprintf("Erase benchmark has an error. Error code: %d.\n", result);
666*10465441SEvalZero }
667*10465441SEvalZero /* write test */
668*10465441SEvalZero rt_kprintf("Writing the %s %ld bytes data, waiting...\n", sfud_dev->name, size);
669*10465441SEvalZero start_time = rt_tick_get();
670*10465441SEvalZero for (i = 0; i < size; i += write_size) {
671*10465441SEvalZero result = sfud_write(sfud_dev, addr + i, write_size, write_data);
672*10465441SEvalZero if (result != SFUD_SUCCESS) {
673*10465441SEvalZero break;
674*10465441SEvalZero }
675*10465441SEvalZero }
676*10465441SEvalZero if (result == SFUD_SUCCESS) {
677*10465441SEvalZero time_cast = rt_tick_get() - start_time;
678*10465441SEvalZero rt_kprintf("Write benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND,
679*10465441SEvalZero time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
680*10465441SEvalZero } else {
681*10465441SEvalZero rt_kprintf("Write benchmark has an error. Error code: %d.\n", result);
682*10465441SEvalZero }
683*10465441SEvalZero /* read test */
684*10465441SEvalZero rt_kprintf("Reading the %s %ld bytes data, waiting...\n", sfud_dev->name, size);
685*10465441SEvalZero start_time = rt_tick_get();
686*10465441SEvalZero for (i = 0; i < size; i += read_size) {
687*10465441SEvalZero if (i + read_size <= size) {
688*10465441SEvalZero result = sfud_read(sfud_dev, addr + i, read_size, read_data);
689*10465441SEvalZero } else {
690*10465441SEvalZero result = sfud_read(sfud_dev, addr + i, size - i, read_data);
691*10465441SEvalZero }
692*10465441SEvalZero /* data check */
693*10465441SEvalZero if (memcmp(write_data, read_data, read_size))
694*10465441SEvalZero {
695*10465441SEvalZero rt_kprintf("Data check ERROR! Please check you flash by other command.\n");
696*10465441SEvalZero result = SFUD_ERR_READ;
697*10465441SEvalZero }
698*10465441SEvalZero
699*10465441SEvalZero if (result != SFUD_SUCCESS) {
700*10465441SEvalZero break;
701*10465441SEvalZero }
702*10465441SEvalZero }
703*10465441SEvalZero if (result == SFUD_SUCCESS) {
704*10465441SEvalZero time_cast = rt_tick_get() - start_time;
705*10465441SEvalZero rt_kprintf("Read benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND,
706*10465441SEvalZero time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
707*10465441SEvalZero } else {
708*10465441SEvalZero rt_kprintf("Read benchmark has an error. Error code: %d.\n", result);
709*10465441SEvalZero }
710*10465441SEvalZero } else {
711*10465441SEvalZero rt_kprintf("Low memory!\n");
712*10465441SEvalZero }
713*10465441SEvalZero rt_free(write_data);
714*10465441SEvalZero rt_free(read_data);
715*10465441SEvalZero } else {
716*10465441SEvalZero rt_kprintf("Usage:\n");
717*10465441SEvalZero for (i = 0; i < sizeof(sf_help_info) / sizeof(char*); i++) {
718*10465441SEvalZero rt_kprintf("%s\n", sf_help_info[i]);
719*10465441SEvalZero }
720*10465441SEvalZero rt_kprintf("\n");
721*10465441SEvalZero return;
722*10465441SEvalZero }
723*10465441SEvalZero if (result != SFUD_SUCCESS) {
724*10465441SEvalZero rt_kprintf("This flash operate has an error. Error code: %d.\n", result);
725*10465441SEvalZero }
726*10465441SEvalZero }
727*10465441SEvalZero }
728*10465441SEvalZero }
729*10465441SEvalZero MSH_CMD_EXPORT(sf, SPI Flash operate.);
730*10465441SEvalZero #endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */
731*10465441SEvalZero
732*10465441SEvalZero #endif /* RT_USING_SFUD */
733