Mbed OS Reference
Loading...
Searching...
No Matches
QSPIFBlockDevice.h
1/* mbed Microcontroller Library
2 * Copyright (c) 2018 ARM Limited
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#ifndef MBED_QSPIF_BLOCK_DEVICE_H
18#define MBED_QSPIF_BLOCK_DEVICE_H
19
20#include "drivers/QSPI.h"
21#include "blockdevice/internal/SFDP.h"
22#include "blockdevice/BlockDevice.h"
23#include "platform/Callback.h"
24
25#ifndef MBED_CONF_QSPIF_QSPI_IO0
26#define MBED_CONF_QSPIF_QSPI_IO0 NC
27#endif
28#ifndef MBED_CONF_QSPIF_QSPI_IO1
29#define MBED_CONF_QSPIF_QSPI_IO1 NC
30#endif
31#ifndef MBED_CONF_QSPIF_QSPI_IO2
32#define MBED_CONF_QSPIF_QSPI_IO2 NC
33#endif
34#ifndef MBED_CONF_QSPIF_QSPI_IO3
35#define MBED_CONF_QSPIF_QSPI_IO3 NC
36#endif
37#ifndef MBED_CONF_QSPIF_QSPI_SCK
38#define MBED_CONF_QSPIF_QSPI_SCK NC
39#endif
40#ifndef MBED_CONF_QSPIF_QSPI_CSN
41#define MBED_CONF_QSPIF_QSPI_CSN NC
42#endif
43#ifndef MBED_CONF_QSPIF_QSPI_POLARITY_MODE
44#define MBED_CONF_QSPIF_QSPI_POLARITY_MODE 0
45#endif
46#ifndef MBED_CONF_QSPIF_QSPI_FREQ
47#define MBED_CONF_QSPIF_QSPI_FREQ 40000000
48#endif
49
50/** Enum qspif standard error codes
51 *
52 * @enum qspif_bd_error
53 */
54enum qspif_bd_error {
55 QSPIF_BD_ERROR_OK = 0, /*!< no error */
56 QSPIF_BD_ERROR_DEVICE_ERROR = mbed::BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */
57 QSPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
58 QSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */
59 QSPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
60 QSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
61 QSPIF_BD_ERROR_DEVICE_NOT_UNIQUE = -4006, /* Only one instance per csel is allowed */
62 QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007, /* Max active QSPIF devices exceeded */
63 QSPIF_BD_ERROR_INVALID_ARGUMENT = -4008 /* Invalid argument passed to function */
64};
65
66/** Enum qspif polarity mode
67 *
68 * @enum qspif_polarity_mode
69 */
70enum qspif_polarity_mode {
71 QSPIF_POLARITY_MODE_0 = 0, /* CPOL=0, CPHA=0 */
72 QSPIF_POLARITY_MODE_1 /* CPOL=1, CPHA=1 */
73};
74
75#define QSPIF_MAX_ACTIVE_FLASH_DEVICES 10
76
77/** BlockDevice for SFDP based flash devices over QSPI bus
78 *
79 * @code
80 * // Here's an example using QSPI flash device on DISCO_L476VG target
81 * #include "mbed.h"
82 * #include "QSPIFBlockDevice.h"
83 *
84 * QSPIFBlockDevice block_device(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3,
85 * QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ);
86 *
87 * int main()
88 * {
89 * printf("QSPI SFDP Flash Block Device example\n");
90 *
91 * // Initialize the SPI flash device and print the memory layout
92 * block_device.init();
93 * bd_size_t sector_size_at_address_0 = block_device.get_erase_size(0);
94 *
95 * printf("QSPIF BD size: %llu\n", block_device.size());
96 * printf("QSPIF BD read size: %llu\n", block_device.get_read_size());
97 * printf("QSPIF BD program size: %llu\n", block_device.get_program_size());
98 * printf("QSPIF BD erase size (at address 0): %llu\n", sector_size_at_address_0);
99 *
100 * // Write "Hello World!" to the first block
101 * char *buffer = (char *) malloc(sector_size_at_address_0);
102 * sprintf(buffer, "Hello World!\n");
103 * block_device.erase(0, sector_size_at_address_0);
104 * block_device.program(buffer, 0, sector_size_at_address_0);
105 *
106 * // Read back what was stored
107 * block_device.read(buffer, 0, sector_size_at_address_0);
108 * printf("%s", buffer);
109 *
110 * // Deinitialize the device
111 * block_device.deinit();
112 * }
113 * @endcode
114 */
116public:
117 /** Create QSPIFBlockDevice - An SFDP based Flash Block Device over QSPI bus
118 *
119 * @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
120 * @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
121 * @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
122 * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
123 * @param sclk QSPI Clock pin
124 * @param csel QSPI chip select pin
125 * @param clock_mode specifies the QSPI Clock Polarity mode (QSPIF_POLARITY_MODE_0/QSPIF_POLARITY_MODE_1)
126 * default value = 0
127 * @param freq Clock frequency of the QSPI bus (defaults to 40MHz)
128 */
129 QSPIFBlockDevice(PinName io0 = MBED_CONF_QSPIF_QSPI_IO0,
130 PinName io1 = MBED_CONF_QSPIF_QSPI_IO1,
131 PinName io2 = MBED_CONF_QSPIF_QSPI_IO2,
132 PinName io3 = MBED_CONF_QSPIF_QSPI_IO3,
133 PinName sclk = MBED_CONF_QSPIF_QSPI_SCK,
134 PinName csel = MBED_CONF_QSPIF_QSPI_CSN,
135 int clock_mode = MBED_CONF_QSPIF_QSPI_POLARITY_MODE,
136 int freq = MBED_CONF_QSPIF_QSPI_FREQ);
137
138 /** Initialize a block device
139 *
140 * @return QSPIF_BD_ERROR_OK(0) - success
141 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
142 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout
143 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
144 */
145 virtual int init();
146
147 /** Deinitialize a block device
148 *
149 * @return QSPIF_BD_ERROR_OK(0) - success
150 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
151 */
152 virtual int deinit();
153
154 /** Desctruct QSPIFBlockDevie
155 */
157 {
158 deinit();
159 }
160
161 /** Read blocks from a block device
162 *
163 * @param buffer Buffer to write blocks to
164 * @param addr Address of block to begin reading from
165 * @param size Size to read in bytes, must be a multiple of read block size
166 * @return QSPIF_BD_ERROR_OK(0) - success
167 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
168 */
169 virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
170
171 /** Program blocks to a block device
172 *
173 * The blocks must have been erased prior to being programmed
174 *
175 * @param buffer Buffer of data to write to blocks
176 * @param addr Address of block to begin writing to
177 * @param size Size to write in bytes, must be a multiple of program block size
178 * @return QSPIF_BD_ERROR_OK(0) - success
179 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
180 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
181 * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
182 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
183 */
184 virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
185
186 /** Erase blocks on a block device
187 *
188 * The state of an erased block is undefined until it has been programmed
189 *
190 * @param addr Address of block to begin erasing
191 * @param size Size to erase in bytes, must be a multiple of erase block size
192 * @return QSPIF_BD_ERROR_OK(0) - success
193 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
194 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
195 * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
196 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
197 * QSPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
198 */
200
201 /** Get the size of a readable block
202 *
203 * @return Size of a readable block in bytes
204 */
206
207 /** Get the size of a programable block
208 *
209 * @return Size of a program block size in bytes
210 * @note Must be a multiple of the read size
211 */
213
214 /** Get the size of a eraseable block
215 *
216 * @return Size of a minimal erase block, common to all regions, in bytes
217 * @note Must be a multiple of the program size
218 */
220
221 /** Get the size of minimal eraseable sector size of given address
222 *
223 * @param addr Any address within block queried for erase sector size (can be any address within flash size offset)
224 * @return Size of minimal erase sector size, in given address region, in bytes
225 * @note Must be a multiple of the program size
226 */
228
229 /** Get the value of storage byte after it was erased
230 *
231 * If get_erase_value returns a non-negative byte value, the underlying
232 * storage is set to that value when erased, and storage containing
233 * that value can be programmed without another erase.
234 *
235 * @return The value of storage when erased, or -1 if you can't
236 * rely on the value of erased storage
237 */
238 virtual int get_erase_value() const;
239
240 /** Get the total size of the underlying device
241 *
242 * @return Size of the underlying device in bytes
243 */
244 virtual mbed::bd_size_t size() const;
245
246 /** Get the BlockDevice class type.
247 *
248 * @return A string represent the BlockDevice class type.
249 */
250 virtual const char *get_type() const;
251
252protected:
253 /********************************/
254 /* Different Device Csel Mgmt */
255 /********************************/
256 // Add a new QSPI device CS to existing devices list.
257 // Only one QSPIFBlockDevice instance per CS is allowed
258 int add_new_csel_instance(PinName csel);
259
260 // Remove device CS from existing device list upon destroying object (last deinit is called)
261 int remove_csel_instance(PinName csel);
262
263 /********************************/
264 /* Calls to QSPI Driver APIs */
265 /********************************/
266 // Send Program/Write command to Driver
267 qspi_status_t _qspi_send_program_command(mbed::qspi_inst_t prog_instruction, const void *buffer,
269
270 // Send Read command to Driver
271 qspi_status_t _qspi_send_read_command(mbed::qspi_inst_t read_instruction, void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
272
273 // Send Erase Instruction using command_transfer command to Driver
274 qspi_status_t _qspi_send_erase_command(mbed::qspi_inst_t erase_instruction, mbed::bd_addr_t addr, mbed::bd_size_t size);
275
276 // Send Generic command_transfer command to Driver
277 qspi_status_t _qspi_send_general_command(mbed::qspi_inst_t instruction_int, mbed::bd_addr_t addr, const char *tx_buffer,
278 mbed::bd_size_t tx_length, const char *rx_buffer, mbed::bd_size_t rx_length);
279
280 // Send command to read from the SFDP table
281 int _qspi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
282 uint8_t inst, uint8_t dummy_cycles,
283 void *rx_buffer, mbed::bd_size_t rx_length);
284
285 // Read the contents of status registers 1 and 2 into a buffer (buffer must have a length of 2)
286 qspi_status_t _qspi_read_status_registers(uint8_t *reg_buffer);
287
288 // Set the contents of status registers 1 and 2 from a buffer (buffer must have a length of 2)
289 qspi_status_t _qspi_write_status_registers(uint8_t *reg_buffer);
290
291 // Send set_frequency command to Driver
292 qspi_status_t _qspi_set_frequency(int freq);
293
294 // Update the 4-byte addressing extension register with the MSB of the address if it is in use
295 qspi_status_t _qspi_update_4byte_ext_addr_reg(mbed::bd_addr_t addr);
296
297 /*********************************/
298 /* Flash Configuration Functions */
299 /*********************************/
300 // Clear the device's block protection
301 int _clear_block_protection();
302
303 // Configure Write Enable in Status Register
304 int _set_write_enable();
305
306 // Wait on status register until write not-in-progress
307 bool _is_mem_ready();
308
309 // Enable Fast Mode - for flash chips with low power default
310 int _enable_fast_mode();
311
312 // Query vendor ID and handle special behavior that isn't covered by SFDP data
313 int _handle_vendor_quirks();
314
315 /****************************************/
316 /* SFDP Detection and Parsing Functions */
317 /****************************************/
318 // Parse and Detect required Basic Parameters from Table
319 int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, mbed::bd_size_t)> sfdp_reader,
320 mbed::sfdp_hdr_info &sfdp_info);
321
322 // Detect the soft reset protocol and reset - returns error if soft reset is not supported
323 int _sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr);
324
325 // Detect fastest read Bus mode supported by device
326 int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
327 bool &set_quad_enable, bool &is_qpi_mode);
328
329 // Enable Quad mode if supported (1-1-4, 1-4-4, 4-4-4 bus modes)
330 int _sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr);
331
332 // Enable QPI mode (4-4-4)
333 int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr);
334
335 // Detect 4-byte addressing mode and enable it if supported
336 int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
337
338protected:
339 enum qspif_clear_protection_method_t {
340 QSPIF_BP_ULBPR, // Issue global protection unlock instruction
341 QSPIF_BP_CLEAR_SR, // Clear protection bits in status register 1
342 };
343
344 // QSPI Driver Object
345 mbed::QSPI _qspi;
346
347 // Number of active OSPIFBlockDevice chip select pins
348 static int _number_of_active_qspif_flash_csel;
349
350 int _unique_device_status;
351 PinName _csel;
352
353 // Mutex is used to protect Flash device for some QSPI Driver commands that must be done sequentially with no other commands in between
354 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
355 rtos::Mutex _mutex;
356
357 // Command Instructions
358 mbed::qspi_inst_t _read_instruction;
359
360 // Status register write/read instructions
361 unsigned int _num_status_registers;
362 mbed::qspi_inst_t _write_status_reg_2_inst;
363 mbed::qspi_inst_t _read_status_reg_2_inst; // If three registers, this instruction reads the latter two
364
365 // Attempt to enable 4-byte addressing. True by default, but may be disabled for some vendors
366 bool _attempt_4_byte_addressing;
367 // 4-byte addressing extension register write instruction
368 mbed::qspi_inst_t _4byte_msb_reg_write_inst;
369
370 // Quad mode enable status register and bit
371 int _quad_enable_register_idx;
372 int _quad_enable_bit;
373
374 bool _needs_fast_mode;
375
376 // S25FS512S needs a quirk
377 bool _S25FS512S_quirk;
378
379 // Clear block protection
380 qspif_clear_protection_method_t _clear_protection_method;
381
382 // Data extracted from the devices SFDP structure
383 mbed::sfdp_hdr_info _sfdp_info;
384
385 unsigned int _page_size_bytes; // Page size - 256 Bytes default
386 int _freq;
387
388 // Bus speed configuration
389 qspi_bus_width_t _inst_width; //Bus width for Instruction phase
390 qspi_bus_width_t _address_width; //Bus width for Address phase
391 qspi_address_size_t _address_size; //Number of bits for address
392 qspi_alt_size_t _alt_size; //Number of bits for alt
393 bool _alt_enabled; //Whether alt is enabled
394 uint8_t _dummy_cycles; //Number of Dummy cycles required by Current Bus Mode
395 qspi_bus_width_t _data_width; //Bus width for Data phase
396
397 uint32_t _init_ref_count;
398 bool _is_initialized;
399};
400
401#endif
BlockDevice for SFDP based flash devices over QSPI bus.
virtual const char * get_type() const
Get the BlockDevice class type.
virtual mbed::bd_size_t get_read_size() const
Get the size of a readable block.
virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
Read blocks from a block device.
virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
Program blocks to a block device.
virtual mbed::bd_size_t get_program_size() const
Get the size of a programable block.
virtual mbed::bd_size_t size() const
Get the total size of the underlying device.
QSPIFBlockDevice(PinName io0=NC, PinName io1=NC, PinName io2=NC, PinName io3=NC, PinName sclk=NC, PinName csel=NC, int clock_mode=0, int freq=40000000)
Create QSPIFBlockDevice - An SFDP based Flash Block Device over QSPI bus.
~QSPIFBlockDevice()
Desctruct QSPIFBlockDevie.
virtual mbed::bd_size_t get_erase_size() const
Get the size of a eraseable block.
virtual int deinit()
Deinitialize a block device.
virtual int erase(mbed::bd_addr_t addr, mbed::bd_size_t size)
Erase blocks on a block device.
virtual int init()
Initialize a block device.
virtual mbed::bd_size_t get_erase_size(mbed::bd_addr_t addr) const
Get the size of minimal eraseable sector size of given address.
virtual int get_erase_value() const
Get the value of storage byte after it was erased.
A hardware device capable of writing and reading blocks.
Definition: BlockDevice.h:53
Callback class based on template specialization.
Definition: Callback.h:53
A QSPI Driver, used for communicating with QSPI slave devices.
Definition: QSPI.h:86
The Mutex class is used to synchronize the execution of threads.
Definition: Mutex.h:70
int qspi_inst_t
Type representing a QSPI instruction.
Definition: QSPI.h:46
uint8_t qspi_alt_size_t
Alternative size in bits.
Definition: qspi_api.h:79
enum qspi_status qspi_status_t
QSPI return status.
enum qspi_bus_width qspi_bus_width_t
QSPI Bus width.
enum qspi_address_size qspi_address_size_t
Address size in bits.
uint64_t bd_size_t
Type representing a quantity of 8-bit bytes.
Definition: BlockDevice.h:48
uint64_t bd_addr_t
Type representing the address of a specific block.
Definition: BlockDevice.h:44
@ BD_ERROR_DEVICE_ERROR
Definition: BlockDevice.h:39
SFDP JEDEC Parameter Table info.
Definition: SFDP.h:95