Mbed OS Device Management example for various ST boards.

DEPRECATED

This example application is not maintained and not recommended. It uses an old version of Mbed OS, Pelion DM and Arm toolchain. It doesn't work with Mbed Studio.

Please use: https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-pelion/

This example is known to work great on the following platforms:

  • DISCO_L475E_IOT01A - onboard WiFI and onboard QSPI flash. Board specific example using onboard sensors is available here.
  • DISCO_F413H - onboard WiFI and onboard QSPI flash.
  • DISCO_F469NI - WizFi310 WiFI shield and onboard QSPI flash (see WiFi shield instructions).
  • DISCO_F746NG - onboard Ethernet and using onboard QSPI flash.
  • DISCO_F769NI - onboard Ethernet and using onboard QSPI flash.
  • DISCO_L496AG - WizFi310 WiFI shield and onboard QSPI flash (see WiFi shield instructions).
  • NUCLEO_F207ZG - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_F412ZG - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).
  • NUCLEO_F429ZI - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_F746ZG - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_F767ZI - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_L476RG - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).
  • NUCLEO_L496ZG - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).
  • NUCLEO_L4R5ZI - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).

Follow the Quick-Start instructions: https://cloud.mbed.com/quick-start

DISCO_L475E_IOT01A DISCO_F413H DISCO_F746NG NUCLEO_F429ZI, NUCLEO_F767ZI, NUCLEO_F746ZG,NUCLEO_F207ZG

Example functionality

This example showcases the following device functionality:

  • Read ADC temperature and ADC vref, and report them as Pelion LWM2M resources (see image below).
  • On user button click, increment Pelion LWM2M button resource.
  • Allow the user to change the state of the board LED from Pelion LWM2M led_state resource and PUT request.

/media/uploads/screamer/pelion_st_adc_reading.png

SD card wiring

The ST Nucleo family of boards don't have storage onboard and therefore you will need an SD card. A limitation on ST Nucleo 144 boards is that there's a conflict between Ethernet and SPI pins on Arduino D11. Due to this, the SD card must be wired to different SPI bus that doesn't conflict with other functionality. The image below provide instructions on how to wire an SD card to a non-conflicting SPI instance.

/media/uploads/screamer/st_nucleo_144_sd.jpeg?v=4

If you are not a first-time Pelion Device Management user your device's SD card may already have connect and update certificates on it. If this is the case, remove and manually format your micro SD card, flash the binary to the device and then re-insert your micro SD card.

WiFi shield setup/wiring

Some ST Nucleo and Discovery boards don't have IP connectivity option, but bundled with a WiFi shield, they can take benefit of full device management capabilities. See links to reference images below on how to wire WizFI310 WiFi shield and/or SD card shield:

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import /teams/ST/code/pelion-example-common

cd pelion-example-common

2. Install the CLOUD_SDK_API_KEY

mbed config -G CLOUD_SDK_API_KEY <PELION_DM_API_KEY>

For instructions on how to generate your API key, please see the documentation.

3. Initialize firmware credentials (done once per repository). You can use the following command:

mbed dm init -d "<your company name in Pelion DM>" --model-name "<product model identifier>" -q --force

If above command do not work for your Mbed CLI, please consider upgrading Mbed CLI to version 1.8.x or above.

4. Compile and program:

mbed compile -t <toolchain> -m <TARGET_BOARD>

(supported toolchains : GCC_ARM / ARM / IAR)

Committer:
screamer
Date:
Mon Dec 10 20:14:17 2018 +0000
Revision:
0:ea30ba97a865
Initial revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:ea30ba97a865 1 /* mbed Microcontroller Library
screamer 0:ea30ba97a865 2 * Copyright (c) 2018 ARM Limited
screamer 0:ea30ba97a865 3 *
screamer 0:ea30ba97a865 4 * Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:ea30ba97a865 5 * you may not use this file except in compliance with the License.
screamer 0:ea30ba97a865 6 * You may obtain a copy of the License at
screamer 0:ea30ba97a865 7 *
screamer 0:ea30ba97a865 8 * http://www.apache.org/licenses/LICENSE-2.0
screamer 0:ea30ba97a865 9 *
screamer 0:ea30ba97a865 10 * Unless required by applicable law or agreed to in writing, software
screamer 0:ea30ba97a865 11 * distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:ea30ba97a865 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:ea30ba97a865 13 * See the License for the specific language governing permissions and
screamer 0:ea30ba97a865 14 * limitations under the License.
screamer 0:ea30ba97a865 15 */
screamer 0:ea30ba97a865 16 #ifndef MBED_QSPIF_BLOCK_DEVICE_H
screamer 0:ea30ba97a865 17 #define MBED_QSPIF_BLOCK_DEVICE_H
screamer 0:ea30ba97a865 18
screamer 0:ea30ba97a865 19 #include "QSPI.h"
screamer 0:ea30ba97a865 20 #include "BlockDevice.h"
screamer 0:ea30ba97a865 21
screamer 0:ea30ba97a865 22 /** Enum qspif standard error codes
screamer 0:ea30ba97a865 23 *
screamer 0:ea30ba97a865 24 * @enum qspif_bd_error
screamer 0:ea30ba97a865 25 */
screamer 0:ea30ba97a865 26 enum qspif_bd_error {
screamer 0:ea30ba97a865 27 QSPIF_BD_ERROR_OK = 0, /*!< no error */
screamer 0:ea30ba97a865 28 QSPIF_BD_ERROR_DEVICE_ERROR = BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */
screamer 0:ea30ba97a865 29 QSPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
screamer 0:ea30ba97a865 30 QSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */
screamer 0:ea30ba97a865 31 QSPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
screamer 0:ea30ba97a865 32 QSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
screamer 0:ea30ba97a865 33 QSPIF_BD_ERROR_DEVICE_NOT_UNIQE = -4006, /* Only one instance per csel is allowed */
screamer 0:ea30ba97a865 34 QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007 /* Max active QSPIF devices exceeded */
screamer 0:ea30ba97a865 35 };
screamer 0:ea30ba97a865 36
screamer 0:ea30ba97a865 37 /** Enum qspif polarity mode
screamer 0:ea30ba97a865 38 *
screamer 0:ea30ba97a865 39 * @enum qspif_polarity_mode
screamer 0:ea30ba97a865 40 */
screamer 0:ea30ba97a865 41 enum qspif_polarity_mode {
screamer 0:ea30ba97a865 42 QSPIF_POLARITY_MODE_0 = 0, /* CPOL=0, CPHA=0 */
screamer 0:ea30ba97a865 43 QSPIF_POLARITY_MODE_1 /* CPOL=1, CPHA=1 */
screamer 0:ea30ba97a865 44 };
screamer 0:ea30ba97a865 45
screamer 0:ea30ba97a865 46 #define QSPIF_MAX_REGIONS 10
screamer 0:ea30ba97a865 47 #define MAX_NUM_OF_ERASE_TYPES 4
screamer 0:ea30ba97a865 48 #define QSPIF_MAX_ACTIVE_FLASH_DEVICES 10
screamer 0:ea30ba97a865 49
screamer 0:ea30ba97a865 50 /** BlockDevice for SFDP based flash devices over QSPI bus
screamer 0:ea30ba97a865 51 *
screamer 0:ea30ba97a865 52 * @code
screamer 0:ea30ba97a865 53 * // Here's an example using QSPI flash device on DISCO_L476VG target
screamer 0:ea30ba97a865 54 * #include "mbed.h"
screamer 0:ea30ba97a865 55 * #include "QSPIFBlockDevice.h"
screamer 0:ea30ba97a865 56 *
screamer 0:ea30ba97a865 57 * QSPIFBlockDevice block_device(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3,
screamer 0:ea30ba97a865 58 * QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ);
screamer 0:ea30ba97a865 59 *
screamer 0:ea30ba97a865 60 * int main()
screamer 0:ea30ba97a865 61 * {
screamer 0:ea30ba97a865 62 * printf("QSPI SFDP Flash Block Device example\n");
screamer 0:ea30ba97a865 63 *
screamer 0:ea30ba97a865 64 * // Initialize the SPI flash device and print the memory layout
screamer 0:ea30ba97a865 65 * block_device.init();
screamer 0:ea30ba97a865 66 * bd_size_t sector_size_at_address_0 = block_device.get_erase_size(0);
screamer 0:ea30ba97a865 67 *
screamer 0:ea30ba97a865 68 * printf("QSPIF BD size: %llu\n", block_device.size());
screamer 0:ea30ba97a865 69 * printf("QSPIF BD read size: %llu\n", block_device.get_read_size());
screamer 0:ea30ba97a865 70 * printf("QSPIF BD program size: %llu\n", block_device.get_program_size());
screamer 0:ea30ba97a865 71 * printf("QSPIF BD erase size (at address 0): %llu\n", sector_size_at_address_0);
screamer 0:ea30ba97a865 72 *
screamer 0:ea30ba97a865 73 * // Write "Hello World!" to the first block
screamer 0:ea30ba97a865 74 * char *buffer = (char *) malloc(sector_size_at_address_0);
screamer 0:ea30ba97a865 75 * sprintf(buffer, "Hello World!\n");
screamer 0:ea30ba97a865 76 * block_device.erase(0, sector_size_at_address_0);
screamer 0:ea30ba97a865 77 * block_device.program(buffer, 0, sector_size_at_address_0);
screamer 0:ea30ba97a865 78 *
screamer 0:ea30ba97a865 79 * // Read back what was stored
screamer 0:ea30ba97a865 80 * block_device.read(buffer, 0, sector_size_at_address_0);
screamer 0:ea30ba97a865 81 * printf("%s", buffer);
screamer 0:ea30ba97a865 82 *
screamer 0:ea30ba97a865 83 * // Deinitialize the device
screamer 0:ea30ba97a865 84 * block_device.deinit();
screamer 0:ea30ba97a865 85 * }
screamer 0:ea30ba97a865 86 * @endcode
screamer 0:ea30ba97a865 87 */
screamer 0:ea30ba97a865 88 class QSPIFBlockDevice : public BlockDevice {
screamer 0:ea30ba97a865 89 public:
screamer 0:ea30ba97a865 90 /** Create QSPIFBlockDevice - An SFDP based Flash Block Device over QSPI bus
screamer 0:ea30ba97a865 91 *
screamer 0:ea30ba97a865 92 * @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
screamer 0:ea30ba97a865 93 * @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
screamer 0:ea30ba97a865 94 * @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
screamer 0:ea30ba97a865 95 * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
screamer 0:ea30ba97a865 96 * @param sclk QSPI Clock pin
screamer 0:ea30ba97a865 97 * @param csel QSPI chip select pin
screamer 0:ea30ba97a865 98 * @param clock_mode specifies the QSPI Clock Polarity mode (QSPIF_POLARITY_MODE_0/QSPIF_POLARITY_MODE_1)
screamer 0:ea30ba97a865 99 * default value = 0
screamer 0:ea30ba97a865 100 * @param freq Clock frequency of the QSPI bus (defaults to 40MHz)
screamer 0:ea30ba97a865 101 *
screamer 0:ea30ba97a865 102 */
screamer 0:ea30ba97a865 103 QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel,
screamer 0:ea30ba97a865 104 int clock_mode, int freq = MBED_CONF_QSPIF_QSPI_FREQ);
screamer 0:ea30ba97a865 105
screamer 0:ea30ba97a865 106 /** Initialize a block device
screamer 0:ea30ba97a865 107 *
screamer 0:ea30ba97a865 108 * @return QSPIF_BD_ERROR_OK(0) - success
screamer 0:ea30ba97a865 109 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
screamer 0:ea30ba97a865 110 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout
screamer 0:ea30ba97a865 111 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
screamer 0:ea30ba97a865 112 */
screamer 0:ea30ba97a865 113 virtual int init();
screamer 0:ea30ba97a865 114
screamer 0:ea30ba97a865 115 /** Deinitialize a block device
screamer 0:ea30ba97a865 116 *
screamer 0:ea30ba97a865 117 * @return QSPIF_BD_ERROR_OK(0) - success
screamer 0:ea30ba97a865 118 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
screamer 0:ea30ba97a865 119 */
screamer 0:ea30ba97a865 120 virtual int deinit();
screamer 0:ea30ba97a865 121
screamer 0:ea30ba97a865 122 /** Desctruct QSPIFBlockDevie
screamer 0:ea30ba97a865 123 */
screamer 0:ea30ba97a865 124 ~QSPIFBlockDevice()
screamer 0:ea30ba97a865 125 {
screamer 0:ea30ba97a865 126 deinit();
screamer 0:ea30ba97a865 127 }
screamer 0:ea30ba97a865 128
screamer 0:ea30ba97a865 129 /** Read blocks from a block device
screamer 0:ea30ba97a865 130 *
screamer 0:ea30ba97a865 131 * @param buffer Buffer to write blocks to
screamer 0:ea30ba97a865 132 * @param addr Address of block to begin reading from
screamer 0:ea30ba97a865 133 * @param size Size to read in bytes, must be a multiple of read block size
screamer 0:ea30ba97a865 134 * @return QSPIF_BD_ERROR_OK(0) - success
screamer 0:ea30ba97a865 135 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
screamer 0:ea30ba97a865 136 */
screamer 0:ea30ba97a865 137 virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
screamer 0:ea30ba97a865 138
screamer 0:ea30ba97a865 139 /** Program blocks to a block device
screamer 0:ea30ba97a865 140 *
screamer 0:ea30ba97a865 141 * The blocks must have been erased prior to being programmed
screamer 0:ea30ba97a865 142 *
screamer 0:ea30ba97a865 143 * @param buffer Buffer of data to write to blocks
screamer 0:ea30ba97a865 144 * @param addr Address of block to begin writing to
screamer 0:ea30ba97a865 145 * @param size Size to write in bytes, must be a multiple of program block size
screamer 0:ea30ba97a865 146 * @return QSPIF_BD_ERROR_OK(0) - success
screamer 0:ea30ba97a865 147 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
screamer 0:ea30ba97a865 148 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
screamer 0:ea30ba97a865 149 * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
screamer 0:ea30ba97a865 150 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
screamer 0:ea30ba97a865 151 */
screamer 0:ea30ba97a865 152 virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
screamer 0:ea30ba97a865 153
screamer 0:ea30ba97a865 154 /** Erase blocks on a block device
screamer 0:ea30ba97a865 155 *
screamer 0:ea30ba97a865 156 * The state of an erased block is undefined until it has been programmed
screamer 0:ea30ba97a865 157 *
screamer 0:ea30ba97a865 158 * @param addr Address of block to begin erasing
screamer 0:ea30ba97a865 159 * @param size Size to erase in bytes, must be a multiple of erase block size
screamer 0:ea30ba97a865 160 * @return QSPIF_BD_ERROR_OK(0) - success
screamer 0:ea30ba97a865 161 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
screamer 0:ea30ba97a865 162 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
screamer 0:ea30ba97a865 163 * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
screamer 0:ea30ba97a865 164 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
screamer 0:ea30ba97a865 165 * QSPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
screamer 0:ea30ba97a865 166 */
screamer 0:ea30ba97a865 167 virtual int erase(bd_addr_t addr, bd_size_t size);
screamer 0:ea30ba97a865 168
screamer 0:ea30ba97a865 169 /** Get the size of a readable block
screamer 0:ea30ba97a865 170 *
screamer 0:ea30ba97a865 171 * @return Size of a readable block in bytes
screamer 0:ea30ba97a865 172 */
screamer 0:ea30ba97a865 173 virtual bd_size_t get_read_size() const;
screamer 0:ea30ba97a865 174
screamer 0:ea30ba97a865 175 /** Get the size of a programable block
screamer 0:ea30ba97a865 176 *
screamer 0:ea30ba97a865 177 * @return Size of a program block size in bytes
screamer 0:ea30ba97a865 178 * @note Must be a multiple of the read size
screamer 0:ea30ba97a865 179 */
screamer 0:ea30ba97a865 180 virtual bd_size_t get_program_size() const;
screamer 0:ea30ba97a865 181
screamer 0:ea30ba97a865 182 /** Get the size of a eraseable block
screamer 0:ea30ba97a865 183 *
screamer 0:ea30ba97a865 184 * @return Size of a minimal erase block, common to all regions, in bytes
screamer 0:ea30ba97a865 185 * @note Must be a multiple of the program size
screamer 0:ea30ba97a865 186 */
screamer 0:ea30ba97a865 187 virtual bd_size_t get_erase_size() const;
screamer 0:ea30ba97a865 188
screamer 0:ea30ba97a865 189 /** Get the size of minimal eraseable sector size of given address
screamer 0:ea30ba97a865 190 *
screamer 0:ea30ba97a865 191 * @param addr Any address within block queried for erase sector size (can be any address within flash size offset)
screamer 0:ea30ba97a865 192 * @return Size of minimal erase sector size, in given address region, in bytes
screamer 0:ea30ba97a865 193 * @note Must be a multiple of the program size
screamer 0:ea30ba97a865 194 */
screamer 0:ea30ba97a865 195 virtual bd_size_t get_erase_size(bd_addr_t addr);
screamer 0:ea30ba97a865 196
screamer 0:ea30ba97a865 197 /** Get the value of storage byte after it was erased
screamer 0:ea30ba97a865 198 *
screamer 0:ea30ba97a865 199 * If get_erase_value returns a non-negative byte value, the underlying
screamer 0:ea30ba97a865 200 * storage is set to that value when erased, and storage containing
screamer 0:ea30ba97a865 201 * that value can be programmed without another erase.
screamer 0:ea30ba97a865 202 *
screamer 0:ea30ba97a865 203 * @return The value of storage when erased, or -1 if you can't
screamer 0:ea30ba97a865 204 * rely on the value of erased storage
screamer 0:ea30ba97a865 205 */
screamer 0:ea30ba97a865 206 virtual int get_erase_value() const;
screamer 0:ea30ba97a865 207
screamer 0:ea30ba97a865 208 /** Get the total size of the underlying device
screamer 0:ea30ba97a865 209 *
screamer 0:ea30ba97a865 210 * @return Size of the underlying device in bytes
screamer 0:ea30ba97a865 211 */
screamer 0:ea30ba97a865 212 virtual bd_size_t size() const;
screamer 0:ea30ba97a865 213
screamer 0:ea30ba97a865 214 private:
screamer 0:ea30ba97a865 215 // Internal functions
screamer 0:ea30ba97a865 216
screamer 0:ea30ba97a865 217
screamer 0:ea30ba97a865 218 /********************************/
screamer 0:ea30ba97a865 219 /* Different Device Csel Mgmt */
screamer 0:ea30ba97a865 220 /********************************/
screamer 0:ea30ba97a865 221 // Add a new QSPI device CS to existing devices list.
screamer 0:ea30ba97a865 222 // Only one QSPIFBlockDevice instance per CS is allowed
screamer 0:ea30ba97a865 223 int add_new_csel_instance(PinName csel);
screamer 0:ea30ba97a865 224
screamer 0:ea30ba97a865 225 // Remove device CS from existing device list upon destroying object (last deinit is called)
screamer 0:ea30ba97a865 226 int remove_csel_instance(PinName csel);
screamer 0:ea30ba97a865 227
screamer 0:ea30ba97a865 228 /********************************/
screamer 0:ea30ba97a865 229 /* Calls to QSPI Driver APIs */
screamer 0:ea30ba97a865 230 /********************************/
screamer 0:ea30ba97a865 231 // Send Program => Write command to Driver
screamer 0:ea30ba97a865 232 qspi_status_t _qspi_send_program_command(unsigned int prog_instruction, const void *buffer, bd_addr_t addr,
screamer 0:ea30ba97a865 233 bd_size_t *size);
screamer 0:ea30ba97a865 234
screamer 0:ea30ba97a865 235 // Send Read command to Driver
screamer 0:ea30ba97a865 236 qspi_status_t _qspi_send_read_command(unsigned int read_instruction, void *buffer, bd_addr_t addr, bd_size_t size);
screamer 0:ea30ba97a865 237
screamer 0:ea30ba97a865 238 // Send Erase Instruction using command_transfer command to Driver
screamer 0:ea30ba97a865 239 qspi_status_t _qspi_send_erase_command(unsigned int erase_instruction, bd_addr_t addr, bd_size_t size);
screamer 0:ea30ba97a865 240
screamer 0:ea30ba97a865 241 // Send Generic command_transfer command to Driver
screamer 0:ea30ba97a865 242 qspi_status_t _qspi_send_general_command(unsigned int instruction_int, bd_addr_t addr, const char *tx_buffer,
screamer 0:ea30ba97a865 243 size_t tx_length, const char *rx_buffer, size_t rx_length);
screamer 0:ea30ba97a865 244
screamer 0:ea30ba97a865 245 // Send Bus configure_format command to Driver
screamer 0:ea30ba97a865 246 qspi_status_t _qspi_configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width,
screamer 0:ea30ba97a865 247 qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width,
screamer 0:ea30ba97a865 248 int dummy_cycles);
screamer 0:ea30ba97a865 249
screamer 0:ea30ba97a865 250 // Send set_frequency command to Driver
screamer 0:ea30ba97a865 251 qspi_status_t _qspi_set_frequency(int freq);
screamer 0:ea30ba97a865 252
screamer 0:ea30ba97a865 253 /*********************************/
screamer 0:ea30ba97a865 254 /* Flash Configuration Functions */
screamer 0:ea30ba97a865 255 /*********************************/
screamer 0:ea30ba97a865 256 // Soft Reset Flash Memory
screamer 0:ea30ba97a865 257 int _reset_flash_mem();
screamer 0:ea30ba97a865 258
screamer 0:ea30ba97a865 259 // Configure Write Enable in Status Register
screamer 0:ea30ba97a865 260 int _set_write_enable();
screamer 0:ea30ba97a865 261
screamer 0:ea30ba97a865 262 // Wait on status register until write not-in-progress
screamer 0:ea30ba97a865 263 bool _is_mem_ready();
screamer 0:ea30ba97a865 264
screamer 0:ea30ba97a865 265 // Enable Fast Mode - for flash chips with low power default
screamer 0:ea30ba97a865 266 int _enable_fast_mdoe();
screamer 0:ea30ba97a865 267
screamer 0:ea30ba97a865 268 /****************************************/
screamer 0:ea30ba97a865 269 /* SFDP Detection and Parsing Functions */
screamer 0:ea30ba97a865 270 /****************************************/
screamer 0:ea30ba97a865 271 // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist)
screamer 0:ea30ba97a865 272 int _sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size,
screamer 0:ea30ba97a865 273 uint32_t &sector_map_table_addr, size_t &sector_map_table_size);
screamer 0:ea30ba97a865 274
screamer 0:ea30ba97a865 275 // Parse and Detect required Basic Parameters from Table
screamer 0:ea30ba97a865 276 int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);
screamer 0:ea30ba97a865 277
screamer 0:ea30ba97a865 278 // Parse and read information required by Regions Secotr Map
screamer 0:ea30ba97a865 279 int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size);
screamer 0:ea30ba97a865 280
screamer 0:ea30ba97a865 281 // Detect fastest read Bus mode supported by device
screamer 0:ea30ba97a865 282 int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, bool &set_quad_enable,
screamer 0:ea30ba97a865 283 bool &is_qpi_mode, unsigned int &read_inst);
screamer 0:ea30ba97a865 284
screamer 0:ea30ba97a865 285 // Enable Quad mode if supported (1-1-4, 1-4-4, 4-4-4 bus modes)
screamer 0:ea30ba97a865 286 int _sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr);
screamer 0:ea30ba97a865 287
screamer 0:ea30ba97a865 288 // Enable QPI mode (4-4-4) is supported
screamer 0:ea30ba97a865 289 int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr);
screamer 0:ea30ba97a865 290
screamer 0:ea30ba97a865 291 // Set Page size for program
screamer 0:ea30ba97a865 292 int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
screamer 0:ea30ba97a865 293
screamer 0:ea30ba97a865 294 // Detect all supported erase types
screamer 0:ea30ba97a865 295 int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
screamer 0:ea30ba97a865 296 unsigned int &erase4k_inst,
screamer 0:ea30ba97a865 297 unsigned int *erase_type_inst_arr, unsigned int *erase_type_size_arr);
screamer 0:ea30ba97a865 298
screamer 0:ea30ba97a865 299 /***********************/
screamer 0:ea30ba97a865 300 /* Utilities Functions */
screamer 0:ea30ba97a865 301 /***********************/
screamer 0:ea30ba97a865 302 // Find the region to which the given offset belong to
screamer 0:ea30ba97a865 303 int _utils_find_addr_region(bd_size_t offset);
screamer 0:ea30ba97a865 304
screamer 0:ea30ba97a865 305 // Iterate on all supported Erase Types of the Region to which the offset belong to.
screamer 0:ea30ba97a865 306 // Iterates from highest type to lowest
screamer 0:ea30ba97a865 307 int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry);
screamer 0:ea30ba97a865 308
screamer 0:ea30ba97a865 309 private:
screamer 0:ea30ba97a865 310 // Internal Members
screamer 0:ea30ba97a865 311
screamer 0:ea30ba97a865 312 // QSPI Driver Object
screamer 0:ea30ba97a865 313 mbed::QSPI _qspi;
screamer 0:ea30ba97a865 314
screamer 0:ea30ba97a865 315 // Static List of different QSPI based Flash devices csel that already exist
screamer 0:ea30ba97a865 316 // Each QSPI Flash device csel can have only 1 QSPIFBlockDevice instance
screamer 0:ea30ba97a865 317 // _devices_mutex is used to lock csel list - only one QSPIFBlockDevice instance per csel is allowed
screamer 0:ea30ba97a865 318 static SingletonPtr<PlatformMutex> _devices_mutex;
screamer 0:ea30ba97a865 319 static int _number_of_active_qspif_flash_csel;
screamer 0:ea30ba97a865 320 static PinName *_active_qspif_flash_csel_arr;
screamer 0:ea30ba97a865 321
screamer 0:ea30ba97a865 322 int _unique_device_status;
screamer 0:ea30ba97a865 323 PinName _csel;
screamer 0:ea30ba97a865 324
screamer 0:ea30ba97a865 325 // Mutex is used to protect Flash device for some QSPI Driver commands that must be done sequentially with no other commands in between
screamer 0:ea30ba97a865 326 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
screamer 0:ea30ba97a865 327 PlatformMutex _mutex;
screamer 0:ea30ba97a865 328
screamer 0:ea30ba97a865 329 // Command Instructions
screamer 0:ea30ba97a865 330 unsigned int _read_instruction;
screamer 0:ea30ba97a865 331 unsigned int _prog_instruction;
screamer 0:ea30ba97a865 332 unsigned int _erase_instruction;
screamer 0:ea30ba97a865 333 unsigned int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h)
screamer 0:ea30ba97a865 334 unsigned int _write_register_inst; // Write status/config register instruction may vary between chips
screamer 0:ea30ba97a865 335 unsigned int _read_register_inst; // Read status/config register instruction may vary between chips
screamer 0:ea30ba97a865 336
screamer 0:ea30ba97a865 337 // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size)
screamer 0:ea30ba97a865 338 unsigned int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES];
screamer 0:ea30ba97a865 339 unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES];
screamer 0:ea30ba97a865 340
screamer 0:ea30ba97a865 341 // Sector Regions Map
screamer 0:ea30ba97a865 342 int _regions_count; //number of regions
screamer 0:ea30ba97a865 343 int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size in bytes
screamer 0:ea30ba97a865 344 bd_size_t _region_high_boundary[QSPIF_MAX_REGIONS]; //region high address offset boundary
screamer 0:ea30ba97a865 345 //Each Region can support a bit combination of any of the 4 Erase Types
screamer 0:ea30ba97a865 346 uint8_t _region_erase_types_bitfield[QSPIF_MAX_REGIONS];
screamer 0:ea30ba97a865 347 unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists)
screamer 0:ea30ba97a865 348
screamer 0:ea30ba97a865 349 unsigned int _page_size_bytes; // Page size - 256 Bytes default
screamer 0:ea30ba97a865 350 int _freq;
screamer 0:ea30ba97a865 351 bd_size_t _device_size_bytes;
screamer 0:ea30ba97a865 352
screamer 0:ea30ba97a865 353 // Bus speed configuration
screamer 0:ea30ba97a865 354 qspi_bus_width_t _inst_width; //Bus width for Instruction phase
screamer 0:ea30ba97a865 355 qspi_bus_width_t _address_width; //Bus width for Address phase
screamer 0:ea30ba97a865 356 qspi_address_size_t _address_size; // number of bytes for address
screamer 0:ea30ba97a865 357 qspi_bus_width_t _data_width; //Bus width for Data phase
screamer 0:ea30ba97a865 358 int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode
screamer 0:ea30ba97a865 359
screamer 0:ea30ba97a865 360 uint32_t _init_ref_count;
screamer 0:ea30ba97a865 361 bool _is_initialized;
screamer 0:ea30ba97a865 362 };
screamer 0:ea30ba97a865 363
screamer 0:ea30ba97a865 364 #endif