RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 2:7aab896b1a3b 1 /* mbed Microcontroller Library
kevman 2:7aab896b1a3b 2 * Copyright (c) 2018 ARM Limited
kevman 2:7aab896b1a3b 3 *
kevman 2:7aab896b1a3b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kevman 2:7aab896b1a3b 5 * you may not use this file except in compliance with the License.
kevman 2:7aab896b1a3b 6 * You may obtain a copy of the License at
kevman 2:7aab896b1a3b 7 *
kevman 2:7aab896b1a3b 8 * http://www.apache.org/licenses/LICENSE-2.0
kevman 2:7aab896b1a3b 9 *
kevman 2:7aab896b1a3b 10 * Unless required by applicable law or agreed to in writing, software
kevman 2:7aab896b1a3b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kevman 2:7aab896b1a3b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 2:7aab896b1a3b 13 * See the License for the specific language governing permissions and
kevman 2:7aab896b1a3b 14 * limitations under the License.
kevman 2:7aab896b1a3b 15 */
kevman 2:7aab896b1a3b 16 #ifndef MBED_SPIF_BLOCK_DEVICE_H
kevman 2:7aab896b1a3b 17 #define MBED_SPIF_BLOCK_DEVICE_H
kevman 2:7aab896b1a3b 18
kevman 2:7aab896b1a3b 19 #include "SPI.h"
kevman 2:7aab896b1a3b 20 #include "DigitalOut.h"
kevman 2:7aab896b1a3b 21 #include "BlockDevice.h"
kevman 2:7aab896b1a3b 22
kevman 2:7aab896b1a3b 23 /** Enum spif standard error codes
kevman 2:7aab896b1a3b 24 *
kevman 2:7aab896b1a3b 25 * @enum spif_bd_error
kevman 2:7aab896b1a3b 26 */
kevman 2:7aab896b1a3b 27 enum spif_bd_error {
kevman 2:7aab896b1a3b 28 SPIF_BD_ERROR_OK = 0, /*!< no error */
kevman 2:7aab896b1a3b 29 SPIF_BD_ERROR_DEVICE_ERROR = BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */
kevman 2:7aab896b1a3b 30 SPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
kevman 2:7aab896b1a3b 31 SPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */
kevman 2:7aab896b1a3b 32 SPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
kevman 2:7aab896b1a3b 33 SPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
kevman 2:7aab896b1a3b 34 };
kevman 2:7aab896b1a3b 35
kevman 2:7aab896b1a3b 36
kevman 2:7aab896b1a3b 37 #define SPIF_MAX_REGIONS 10
kevman 2:7aab896b1a3b 38 #define MAX_NUM_OF_ERASE_TYPES 4
kevman 2:7aab896b1a3b 39
kevman 2:7aab896b1a3b 40 /** BlockDevice for SFDP based flash devices over SPI bus
kevman 2:7aab896b1a3b 41 *
kevman 2:7aab896b1a3b 42 * @code
kevman 2:7aab896b1a3b 43 * // Here's an example using SPI flash device on K82F target
kevman 2:7aab896b1a3b 44 * #include "mbed.h"
kevman 2:7aab896b1a3b 45 * #include "SPIFBlockDevice.h"
kevman 2:7aab896b1a3b 46 *
kevman 2:7aab896b1a3b 47 * // Create flash device on SPI bus with PTE5 as chip select
kevman 2:7aab896b1a3b 48 * SPIFBlockDevice spif(PTE2, PTE4, PTE1, PTE5);
kevman 2:7aab896b1a3b 49 *
kevman 2:7aab896b1a3b 50 * int main() {
kevman 2:7aab896b1a3b 51 * printf("spif test\n");
kevman 2:7aab896b1a3b 52 *
kevman 2:7aab896b1a3b 53 * // Initialize the SPI flash device and print the memory layout
kevman 2:7aab896b1a3b 54 * spif.init();
kevman 2:7aab896b1a3b 55 * printf("spif size: %llu\n", spif.size());
kevman 2:7aab896b1a3b 56 * printf("spif read size: %llu\n", spif.get_read_size());
kevman 2:7aab896b1a3b 57 * printf("spif program size: %llu\n", spif.get_program_size());
kevman 2:7aab896b1a3b 58 * printf("spif erase size: %llu\n", spif.get_erase_size());
kevman 2:7aab896b1a3b 59 *
kevman 2:7aab896b1a3b 60 * // Write "Hello World!" to the first block
kevman 2:7aab896b1a3b 61 * char *buffer = (char*)malloc(spif.get_erase_size());
kevman 2:7aab896b1a3b 62 * sprintf(buffer, "Hello World!\n");
kevman 2:7aab896b1a3b 63 * spif.erase(0, spif.get_erase_size());
kevman 2:7aab896b1a3b 64 * spif.program(buffer, 0, spif.get_erase_size());
kevman 2:7aab896b1a3b 65 *
kevman 2:7aab896b1a3b 66 * // Read back what was stored
kevman 2:7aab896b1a3b 67 * spif.read(buffer, 0, spif.get_erase_size());
kevman 2:7aab896b1a3b 68 * printf("%s", buffer);
kevman 2:7aab896b1a3b 69 *
kevman 2:7aab896b1a3b 70 * // Deinitialize the device
kevman 2:7aab896b1a3b 71 * spif.deinit();
kevman 2:7aab896b1a3b 72 * }
kevman 2:7aab896b1a3b 73 * @endcode
kevman 2:7aab896b1a3b 74 */
kevman 2:7aab896b1a3b 75 class SPIFBlockDevice : public BlockDevice {
kevman 2:7aab896b1a3b 76 public:
kevman 2:7aab896b1a3b 77 /** Creates a SPIFBlockDevice on a SPI bus specified by pins
kevman 2:7aab896b1a3b 78 *
kevman 2:7aab896b1a3b 79 * @param mosi SPI master out, slave in pin
kevman 2:7aab896b1a3b 80 * @param miso SPI master in, slave out pin
kevman 2:7aab896b1a3b 81 * @param sclk SPI clock pin
kevman 2:7aab896b1a3b 82 * @param csel SPI chip select pin
kevman 2:7aab896b1a3b 83 * @param freq Clock speed of the SPI bus (defaults to 40MHz)
kevman 2:7aab896b1a3b 84 */
kevman 2:7aab896b1a3b 85 SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq = 40000000);
kevman 2:7aab896b1a3b 86
kevman 2:7aab896b1a3b 87 /** Initialize a block device
kevman 2:7aab896b1a3b 88 *
kevman 2:7aab896b1a3b 89 * @return SPIF_BD_ERROR_OK(0) - success
kevman 2:7aab896b1a3b 90 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
kevman 2:7aab896b1a3b 91 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout
kevman 2:7aab896b1a3b 92 * SPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
kevman 2:7aab896b1a3b 93 */
kevman 2:7aab896b1a3b 94 virtual int init();
kevman 2:7aab896b1a3b 95
kevman 2:7aab896b1a3b 96 /** Deinitialize a block device
kevman 2:7aab896b1a3b 97 *
kevman 2:7aab896b1a3b 98 * @return SPIF_BD_ERROR_OK(0) - success
kevman 2:7aab896b1a3b 99 */
kevman 2:7aab896b1a3b 100 virtual int deinit();
kevman 2:7aab896b1a3b 101
kevman 2:7aab896b1a3b 102 /** Desctruct SPIFBlockDevie
kevman 2:7aab896b1a3b 103 */
kevman 2:7aab896b1a3b 104 ~SPIFBlockDevice()
kevman 2:7aab896b1a3b 105 {
kevman 2:7aab896b1a3b 106 deinit();
kevman 2:7aab896b1a3b 107 }
kevman 2:7aab896b1a3b 108
kevman 2:7aab896b1a3b 109 /** Read blocks from a block device
kevman 2:7aab896b1a3b 110 *
kevman 2:7aab896b1a3b 111 * @param buffer Buffer to write blocks to
kevman 2:7aab896b1a3b 112 * @param addr Address of block to begin reading from
kevman 2:7aab896b1a3b 113 * @param size Size to read in bytes, must be a multiple of read block size
kevman 2:7aab896b1a3b 114 * @return SPIF_BD_ERROR_OK(0) - success
kevman 2:7aab896b1a3b 115 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
kevman 2:7aab896b1a3b 116 */
kevman 2:7aab896b1a3b 117 virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
kevman 2:7aab896b1a3b 118
kevman 2:7aab896b1a3b 119 /** Program blocks to a block device
kevman 2:7aab896b1a3b 120 *
kevman 2:7aab896b1a3b 121 * The blocks must have been erased prior to being programmed
kevman 2:7aab896b1a3b 122 *
kevman 2:7aab896b1a3b 123 * @param buffer Buffer of data to write to blocks
kevman 2:7aab896b1a3b 124 * @param addr Address of block to begin writing to
kevman 2:7aab896b1a3b 125 * @param size Size to write in bytes, must be a multiple of program block size
kevman 2:7aab896b1a3b 126 * @return SPIF_BD_ERROR_OK(0) - success
kevman 2:7aab896b1a3b 127 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
kevman 2:7aab896b1a3b 128 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
kevman 2:7aab896b1a3b 129 * SPIF_BD_ERROR_WREN_FAILED - Write Enable failed
kevman 2:7aab896b1a3b 130 */
kevman 2:7aab896b1a3b 131 virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
kevman 2:7aab896b1a3b 132
kevman 2:7aab896b1a3b 133 /** Erase blocks on a block device
kevman 2:7aab896b1a3b 134 *
kevman 2:7aab896b1a3b 135 * The state of an erased block is undefined until it has been programmed
kevman 2:7aab896b1a3b 136 *
kevman 2:7aab896b1a3b 137 * @param addr Address of block to begin erasing
kevman 2:7aab896b1a3b 138 * @param size Size to erase in bytes, must be a multiple of erase block size
kevman 2:7aab896b1a3b 139 * @return SPIF_BD_ERROR_OK(0) - success
kevman 2:7aab896b1a3b 140 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
kevman 2:7aab896b1a3b 141 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
kevman 2:7aab896b1a3b 142 * SPIF_BD_ERROR_WREN_FAILED - Write Enable failed
kevman 2:7aab896b1a3b 143 * SPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
kevman 2:7aab896b1a3b 144 */
kevman 2:7aab896b1a3b 145 virtual int erase(bd_addr_t addr, bd_size_t size);
kevman 2:7aab896b1a3b 146
kevman 2:7aab896b1a3b 147 /** Get the size of a readable block
kevman 2:7aab896b1a3b 148 *
kevman 2:7aab896b1a3b 149 * @return Size of a readable block in bytes
kevman 2:7aab896b1a3b 150 */
kevman 2:7aab896b1a3b 151 virtual bd_size_t get_read_size() const;
kevman 2:7aab896b1a3b 152
kevman 2:7aab896b1a3b 153 /** Get the size of a programable block
kevman 2:7aab896b1a3b 154 *
kevman 2:7aab896b1a3b 155 * @return Size of a programable block in bytes
kevman 2:7aab896b1a3b 156 * @note Must be a multiple of the read size
kevman 2:7aab896b1a3b 157 */
kevman 2:7aab896b1a3b 158 virtual bd_size_t get_program_size() const;
kevman 2:7aab896b1a3b 159
kevman 2:7aab896b1a3b 160 /** Get the size of a eraseable block
kevman 2:7aab896b1a3b 161 *
kevman 2:7aab896b1a3b 162 * @return Size of a eraseable block in bytes
kevman 2:7aab896b1a3b 163 * @note Must be a multiple of the program size
kevman 2:7aab896b1a3b 164 */
kevman 2:7aab896b1a3b 165 virtual bd_size_t get_erase_size() const;
kevman 2:7aab896b1a3b 166
kevman 2:7aab896b1a3b 167 /** Get the size of minimal eraseable sector size of given address
kevman 2:7aab896b1a3b 168 *
kevman 2:7aab896b1a3b 169 * @param addr Any address within block queried for erase sector size (can be any address within flash size offset)
kevman 2:7aab896b1a3b 170 * @return Size of minimal erase sector size, in given address region, in bytes
kevman 2:7aab896b1a3b 171 * @note Must be a multiple of the program size
kevman 2:7aab896b1a3b 172 */
kevman 2:7aab896b1a3b 173 virtual bd_size_t get_erase_size(bd_addr_t addr);
kevman 2:7aab896b1a3b 174
kevman 2:7aab896b1a3b 175 /** Get the value of storage byte after it was erased
kevman 2:7aab896b1a3b 176 *
kevman 2:7aab896b1a3b 177 * If get_erase_value returns a non-negative byte value, the underlying
kevman 2:7aab896b1a3b 178 * storage is set to that value when erased, and storage containing
kevman 2:7aab896b1a3b 179 * that value can be programmed without another erase.
kevman 2:7aab896b1a3b 180 *
kevman 2:7aab896b1a3b 181 * @return The value of storage when erased, or -1 if you can't
kevman 2:7aab896b1a3b 182 * rely on the value of erased storage
kevman 2:7aab896b1a3b 183 */
kevman 2:7aab896b1a3b 184 virtual int get_erase_value() const;
kevman 2:7aab896b1a3b 185
kevman 2:7aab896b1a3b 186 /** Get the total size of the underlying device
kevman 2:7aab896b1a3b 187 *
kevman 2:7aab896b1a3b 188 * @return Size of the underlying device in bytes
kevman 2:7aab896b1a3b 189 */
kevman 2:7aab896b1a3b 190 virtual bd_size_t size() const;
kevman 2:7aab896b1a3b 191
kevman 2:7aab896b1a3b 192 private:
kevman 2:7aab896b1a3b 193
kevman 2:7aab896b1a3b 194 // Internal functions
kevman 2:7aab896b1a3b 195
kevman 2:7aab896b1a3b 196 /****************************************/
kevman 2:7aab896b1a3b 197 /* SFDP Detection and Parsing Functions */
kevman 2:7aab896b1a3b 198 /****************************************/
kevman 2:7aab896b1a3b 199 // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist)
kevman 2:7aab896b1a3b 200 int _sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size,
kevman 2:7aab896b1a3b 201 uint32_t &sector_map_table_addr, size_t &sector_map_table_size);
kevman 2:7aab896b1a3b 202
kevman 2:7aab896b1a3b 203 // Parse and Detect required Basic Parameters from Table
kevman 2:7aab896b1a3b 204 int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);
kevman 2:7aab896b1a3b 205
kevman 2:7aab896b1a3b 206 // Parse and read information required by Regions Secotr Map
kevman 2:7aab896b1a3b 207 int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size);
kevman 2:7aab896b1a3b 208
kevman 2:7aab896b1a3b 209 // Detect fastest read Bus mode supported by device
kevman 2:7aab896b1a3b 210 int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);
kevman 2:7aab896b1a3b 211
kevman 2:7aab896b1a3b 212 // Set Page size for program
kevman 2:7aab896b1a3b 213 unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
kevman 2:7aab896b1a3b 214
kevman 2:7aab896b1a3b 215 // Detect all supported erase types
kevman 2:7aab896b1a3b 216 int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
kevman 2:7aab896b1a3b 217 int &erase4k_inst,
kevman 2:7aab896b1a3b 218 int *erase_type_inst_arr, unsigned int *erase_type_size_arr);
kevman 2:7aab896b1a3b 219
kevman 2:7aab896b1a3b 220 /***********************/
kevman 2:7aab896b1a3b 221 /* Utilities Functions */
kevman 2:7aab896b1a3b 222 /***********************/
kevman 2:7aab896b1a3b 223 // Find the region to which the given offset belong to
kevman 2:7aab896b1a3b 224 int _utils_find_addr_region(bd_size_t offset);
kevman 2:7aab896b1a3b 225
kevman 2:7aab896b1a3b 226 // Iterate on all supported Erase Types of the Region to which the offset belong to.
kevman 2:7aab896b1a3b 227 // Iterates from highest type to lowest
kevman 2:7aab896b1a3b 228 int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry);
kevman 2:7aab896b1a3b 229
kevman 2:7aab896b1a3b 230 /********************************/
kevman 2:7aab896b1a3b 231 /* Calls to SPI Driver APIs */
kevman 2:7aab896b1a3b 232 /********************************/
kevman 2:7aab896b1a3b 233 // Send Program => Write command to Driver
kevman 2:7aab896b1a3b 234 spif_bd_error _spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr, bd_size_t size);
kevman 2:7aab896b1a3b 235
kevman 2:7aab896b1a3b 236 // Send Read command to Driver
kevman 2:7aab896b1a3b 237 //spif_bd_error _spi_send_read_command(uint8_t read_inst, void *buffer, bd_addr_t addr, bd_size_t size);
kevman 2:7aab896b1a3b 238 spif_bd_error _spi_send_read_command(int read_inst, uint8_t *buffer, bd_addr_t addr, bd_size_t size);
kevman 2:7aab896b1a3b 239
kevman 2:7aab896b1a3b 240 // Send Erase Instruction using command_transfer command to Driver
kevman 2:7aab896b1a3b 241 spif_bd_error _spi_send_erase_command(int erase_inst, bd_addr_t addr, bd_size_t size);
kevman 2:7aab896b1a3b 242
kevman 2:7aab896b1a3b 243 // Send Generic command_transfer command to Driver
kevman 2:7aab896b1a3b 244 spif_bd_error _spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer,
kevman 2:7aab896b1a3b 245 size_t tx_length, char *rx_buffer, size_t rx_length);
kevman 2:7aab896b1a3b 246
kevman 2:7aab896b1a3b 247 // Send set_frequency command to Driver
kevman 2:7aab896b1a3b 248 spif_bd_error _spi_set_frequency(int freq);
kevman 2:7aab896b1a3b 249 /********************************/
kevman 2:7aab896b1a3b 250
kevman 2:7aab896b1a3b 251 // Soft Reset Flash Memory
kevman 2:7aab896b1a3b 252 int _reset_flash_mem();
kevman 2:7aab896b1a3b 253
kevman 2:7aab896b1a3b 254 // Configure Write Enable in Status Register
kevman 2:7aab896b1a3b 255 int _set_write_enable();
kevman 2:7aab896b1a3b 256
kevman 2:7aab896b1a3b 257 // Wait on status register until write not-in-progress
kevman 2:7aab896b1a3b 258 bool _is_mem_ready();
kevman 2:7aab896b1a3b 259
kevman 2:7aab896b1a3b 260 private:
kevman 2:7aab896b1a3b 261 // Master side hardware
kevman 2:7aab896b1a3b 262 mbed::SPI _spi;
kevman 2:7aab896b1a3b 263 // Enable CS control (low/high) for SPI driver operatios
kevman 2:7aab896b1a3b 264 mbed::DigitalOut _cs;
kevman 2:7aab896b1a3b 265
kevman 2:7aab896b1a3b 266 // Mutex is used to protect Flash device for some SPI Driver commands that must be done sequentially with no other commands in between
kevman 2:7aab896b1a3b 267 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
kevman 2:7aab896b1a3b 268 static SingletonPtr<PlatformMutex> _mutex;
kevman 2:7aab896b1a3b 269
kevman 2:7aab896b1a3b 270 // Command Instructions
kevman 2:7aab896b1a3b 271 int _read_instruction;
kevman 2:7aab896b1a3b 272 int _prog_instruction;
kevman 2:7aab896b1a3b 273 int _erase_instruction;
kevman 2:7aab896b1a3b 274 int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h)
kevman 2:7aab896b1a3b 275
kevman 2:7aab896b1a3b 276 // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size)
kevman 2:7aab896b1a3b 277 int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES];
kevman 2:7aab896b1a3b 278 unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES];
kevman 2:7aab896b1a3b 279
kevman 2:7aab896b1a3b 280 // Sector Regions Map
kevman 2:7aab896b1a3b 281 int _regions_count; //number of regions
kevman 2:7aab896b1a3b 282 int _region_size_bytes[SPIF_MAX_REGIONS]; //regions size in bytes
kevman 2:7aab896b1a3b 283 bd_size_t _region_high_boundary[SPIF_MAX_REGIONS]; //region high address offset boundary
kevman 2:7aab896b1a3b 284 //Each Region can support a bit combination of any of the 4 Erase Types
kevman 2:7aab896b1a3b 285 uint8_t _region_erase_types_bitfield[SPIF_MAX_REGIONS];
kevman 2:7aab896b1a3b 286 unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists)
kevman 2:7aab896b1a3b 287
kevman 2:7aab896b1a3b 288 unsigned int _page_size_bytes; // Page size - 256 Bytes default
kevman 2:7aab896b1a3b 289 bd_size_t _device_size_bytes;
kevman 2:7aab896b1a3b 290
kevman 2:7aab896b1a3b 291 // Bus configuration
kevman 2:7aab896b1a3b 292 unsigned int _address_size; // number of bytes for address
kevman 2:7aab896b1a3b 293 unsigned int _read_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Read Bus Mode
kevman 2:7aab896b1a3b 294 unsigned int _write_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Write Bus Mode
kevman 2:7aab896b1a3b 295 unsigned int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode
kevman 2:7aab896b1a3b 296 uint32_t _init_ref_count;
kevman 2:7aab896b1a3b 297 bool _is_initialized;
kevman 2:7aab896b1a3b 298 };
kevman 2:7aab896b1a3b 299
kevman 2:7aab896b1a3b 300 #endif /* MBED_SPIF_BLOCK_DEVICE_H */