Mbed OS Reference
Loading...
Searching...
No Matches
SPIFBlockDevice.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_SPIF_BLOCK_DEVICE_H
18#define MBED_SPIF_BLOCK_DEVICE_H
19
20#include "platform/SingletonPtr.h"
21#include "drivers/SPI.h"
22#include "drivers/DigitalOut.h"
23#include "blockdevice/internal/SFDP.h"
24#include "blockdevice/BlockDevice.h"
25
26#ifndef MBED_CONF_SPIF_DRIVER_SPI_MOSI
27#define MBED_CONF_SPIF_DRIVER_SPI_MOSI NC
28#endif
29#ifndef MBED_CONF_SPIF_DRIVER_SPI_MISO
30#define MBED_CONF_SPIF_DRIVER_SPI_MISO NC
31#endif
32#ifndef MBED_CONF_SPIF_DRIVER_SPI_CLK
33#define MBED_CONF_SPIF_DRIVER_SPI_CLK NC
34#endif
35#ifndef MBED_CONF_SPIF_DRIVER_SPI_CS
36#define MBED_CONF_SPIF_DRIVER_SPI_CS NC
37#endif
38#ifndef MBED_CONF_SPIF_DRIVER_SPI_FREQ
39#define MBED_CONF_SPIF_DRIVER_SPI_FREQ 40000000
40#endif
41
42/** Enum spif standard error codes
43 *
44 * @enum spif_bd_error
45 */
46enum spif_bd_error {
47 SPIF_BD_ERROR_OK = 0, /*!< no error */
48 SPIF_BD_ERROR_DEVICE_ERROR = mbed::BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */
49 SPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
50 SPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Memory Ready failed */
51 SPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
52 SPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
53};
54
55
56/** BlockDevice for SFDP based flash devices over SPI bus
57 *
58 * @code
59 * // An example using SPI flash device on K82F target
60 * #include "mbed.h"
61 * #include "SPIFBlockDevice.h"
62 *
63 * // Create flash device on SPI bus with PTE5 as chip select
64 * SPIFBlockDevice spif(PTE2, PTE4, PTE1, PTE5);
65 *
66 * int main() {
67 * printf("spif test\n");
68 *
69 * // Initialize the SPI flash device and print the memory layout
70 * spif.init();
71 * printf("spif size: %llu\n", spif.size());
72 * printf("spif read size: %llu\n", spif.get_read_size());
73 * printf("spif program size: %llu\n", spif.get_program_size());
74 * printf("spif erase size: %llu\n", spif.get_erase_size());
75 *
76 * // Write "Hello World!" to the first block
77 * char *buffer = (char*)malloc(spif.get_erase_size());
78 * sprintf(buffer, "Hello World!\n");
79 * spif.erase(0, spif.get_erase_size());
80 * spif.program(buffer, 0, spif.get_erase_size());
81 *
82 * // Read back what was stored
83 * spif.read(buffer, 0, spif.get_erase_size());
84 * printf("%s", buffer);
85 *
86 * // Deinitialize the device
87 * spif.deinit();
88 * }
89 * @endcode
90 */
92public:
93 /** Creates a SPIFBlockDevice on a SPI bus specified by pins
94 *
95 * @param mosi SPI master out, slave in pin
96 * @param miso SPI master in, slave out pin
97 * @param sclk SPI clock pin
98 * @param csel SPI chip select pin
99 * @param freq Clock speed of the SPI bus (defaults to 40MHz)
100 *
101 *
102 */
103 SPIFBlockDevice(PinName mosi = MBED_CONF_SPIF_DRIVER_SPI_MOSI,
104 PinName miso = MBED_CONF_SPIF_DRIVER_SPI_MISO,
105 PinName sclk = MBED_CONF_SPIF_DRIVER_SPI_CLK,
106 PinName csel = MBED_CONF_SPIF_DRIVER_SPI_CS,
107 int freq = MBED_CONF_SPIF_DRIVER_SPI_FREQ);
108
109 /** Initialize a block device
110 *
111 * @return SPIF_BD_ERROR_OK(0) - success
112 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
113 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
114 * SPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
115 */
116 virtual int init();
117
118 /** Deinitialize a block device
119 *
120 * @return SPIF_BD_ERROR_OK(0) - success
121 */
122 virtual int deinit();
123
124 /** Desctruct SPIFBlockDevice
125 */
127 {
128 deinit();
129 }
130
131 /** Read blocks from a block device
132 *
133 * @param buffer Buffer to write blocks to
134 * @param addr Address of block to begin reading from
135 * @param size Size to read in bytes, must be a multiple of read block size
136 * @return SPIF_BD_ERROR_OK(0) - success
137 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
138 */
139 virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
140
141 /** Program blocks to a block device
142 *
143 * @note The blocks must have been erased prior to being programmed
144 *
145 * @param buffer Buffer of data to write to blocks
146 * @param addr Address of block to begin writing to
147 * @param size Size to write in bytes, must be a multiple of program block size
148 * @return SPIF_BD_ERROR_OK(0) - success
149 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
150 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
151 * SPIF_BD_ERROR_WREN_FAILED - Write Enable failed
152 */
153 virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
154
155 /** Erase blocks on a block device
156 *
157 * @note The state of an erased block is undefined until it has been programmed
158 *
159 * @param addr Address of block to begin erasing
160 * @param size Size to erase in bytes, must be a multiple of erase block size
161 * @return SPIF_BD_ERROR_OK(0) - success
162 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
163 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
164 * SPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
165 */
167
168 /** Get the size of a readable block
169 *
170 * @return Size of a readable block in bytes
171 */
173
174 /** Get the size of a programable block
175 *
176 * @return Size of a programable block in bytes
177 * @note Must be a multiple of the read size
178 */
180
181 /** Get the size of an erasable block
182 *
183 * @return Size of an erasable block in bytes
184 * @note Must be a multiple of the program size
185 */
187
188 /** Get the size of minimal erasable sector size of given address
189 *
190 * @param addr Any address within block queried for erase sector size (can be any address within flash size offset)
191 * @return Size of minimal erase sector size, in given address region, in bytes
192 * @note Must be a multiple of the program size
193 */
195
196 /** Get the value of storage byte after it was erased
197 *
198 * If get_erase_value returns a non-negative byte value, the underlying
199 * storage is set to that value when erased, and storage containing
200 * that value can be programmed without another erase.
201 *
202 * @return The value of storage when erased, or -1 if you can't
203 * rely on the value of erased storage
204 */
205 virtual int get_erase_value() const;
206
207 /** Get the total size of the underlying device
208 *
209 * @return Size of the underlying device in bytes
210 */
211 virtual mbed::bd_size_t size() const;
212
213 /** Get the BlockDevice class type.
214 *
215 * @return A string representation of the BlockDevice class type.
216 */
217 virtual const char *get_type() const;
218
219private:
220 /****************************************/
221 /* SFDP Detection and Parsing Functions */
222 /****************************************/
223 // Send SFDP Read command to Driver
224 int _spi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
225 uint8_t inst, uint8_t dummy_cycles,
226 void *rx_buffer, mbed::bd_size_t rx_length);
227
228 // Parse and Detect required Basic Parameters from Table
229 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,
230 mbed::sfdp_hdr_info &hdr_info);
231
232 // Detect fastest read Bus mode supported by device
233 int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);
234
235 /********************************/
236 /* Calls to SPI Driver APIs */
237 /********************************/
238 // Send Program => Write command to Driver
239 spif_bd_error _spi_send_program_command(int prog_inst, const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
240
241 // Send Read command to Driver
242 //spif_bd_error _spi_send_read_command(uint8_t read_inst, void *buffer, bd_addr_t addr, bd_size_t size);
243 spif_bd_error _spi_send_read_command(int read_inst, uint8_t *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
244
245 // Send Erase Instruction using command_transfer command to Driver
246 spif_bd_error _spi_send_erase_command(int erase_inst, mbed::bd_addr_t addr, mbed::bd_size_t size);
247
248 // Send Generic command_transfer command to Driver
249 spif_bd_error _spi_send_general_command(int instruction, mbed::bd_addr_t addr, char *tx_buffer,
250 size_t tx_length, char *rx_buffer, size_t rx_length);
251
252 // Send set_frequency command to Driver
253 spif_bd_error _spi_set_frequency(int freq);
254 /********************************/
255
256 // Soft Reset Flash Memory
257 int _reset_flash_mem();
258
259 // Configure Write Enable in Status Register
260 int _set_write_enable();
261
262 // Wait on status register until write not-in-progress
263 bool _is_mem_ready();
264
265 // Query vendor ID and handle special behavior that isn't covered by SFDP data
266 int _handle_vendor_quirks();
267
268private:
269 // Master side hardware
270 mbed::SPI _spi;
271
272 // Mutex is used to protect Flash device for some SPI Driver commands that must be done sequentially with no other commands in between
273 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
274 static SingletonPtr<rtos::Mutex> _mutex;
275
276 // Command Instructions
277 int _read_instruction;
278 int _prog_instruction;
279 int _erase_instruction;
280
281 // Data extracted from the devices SFDP structure
282 mbed::sfdp_hdr_info _sfdp_info;
283
284 unsigned int _page_size_bytes; // Page size - 256 Bytes default
285 mbed::bd_size_t _device_size_bytes;
286
287 // Bus configuration
288 unsigned int _address_size; // number of bytes for address
289 unsigned int _read_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Read Bus Mode
290 unsigned int _write_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Write Bus Mode
291 unsigned int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode
292 uint32_t _init_ref_count;
293 bool _is_initialized;
294};
295
296#endif /* MBED_SPIF_BLOCK_DEVICE_H */
BlockDevice for SFDP based flash devices over SPI 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.
SPIFBlockDevice(PinName mosi=NC, PinName miso=NC, PinName sclk=NC, PinName csel=NC, int freq=40000000)
Creates a SPIFBlockDevice on a SPI bus specified by pins.
virtual mbed::bd_size_t get_erase_size() const
Get the size of an erasable 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.
~SPIFBlockDevice()
Desctruct SPIFBlockDevice.
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 erasable 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
An SPI Master, used for communicating with SPI slave devices.
Definition: SPI.h:263
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
Utility class for creating and using a singleton.
Definition: SingletonPtr.h:88
SFDP JEDEC Parameter Table info.
Definition: SFDP.h:95