Fork for workshops

Revision:
0:6b753f761943
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/QSPIFBlockDevice.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,232 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2016 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MBED_QSPIF_BLOCK_DEVICE_H
+#define MBED_QSPIF_BLOCK_DEVICE_H
+
+
+#define DEVICE_QSPI 1
+
+#include <mbed.h>
+#include "BlockDevice.h"
+#include "QSPI.h"
+
+#define QSPIF_MAX_REGIONS	4
+
+class QSPIFBlockDevice : public BlockDevice {
+public:
+    /** Creates a QSPIFBlockDevice on a SPI bus specified by pins
+     *
+     *  @param mosi     SPI master out, slave in pin
+     *  @param miso     SPI master in, slave out pin
+     *  @param sclk     SPI clock pin
+     *  @param csel     SPI chip select pin
+     *  @param freq     Clock speed of the SPI bus (defaults to 40MHz)
+     */
+
+    /** Creates a QSPIFBlockDevice on an SPI bus specified by pins
+     *
+     *  io0-io3 is used to specify the Pins used for Quad SPI mode
+     *
+     *  @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
+     *  @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
+     *  @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
+     *  @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
+     *  @param sclk QSPI Clock pin
+     *  @param csel QSPI chip select pin
+     *  @param clock_mode specifies the SPI Clock Polarity mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
+     *         default value = 0
+     *  @param freq Clock frequency of the SPI bus (defaults to 40MHz)
+     *
+     */
+    QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, int clock_mode,
+                     int freq = 40000000);
+
+    /** Initialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int init();
+
+    /** Deinitialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int deinit();
+
+    /** Read blocks from a block device
+     *
+     *  @param buffer   Buffer to write blocks to
+     *  @param addr     Address of block to begin reading from
+     *  @param size     Size to read in bytes, must be a multiple of read block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Program blocks to a block device
+     *
+     *  The blocks must have been erased prior to being programmed
+     *
+     *  @param buffer   Buffer of data to write to blocks
+     *  @param addr     Address of block to begin writing to
+     *  @param size     Size to write in bytes, must be a multiple of program block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Erase blocks on a block device
+     *
+     *  The state of an erased block is undefined until it has been programmed
+     *
+     *  @param addr     Address of block to begin erasing
+     *  @param size     Size to erase in bytes, must be a multiple of erase block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int erase(bd_addr_t addr, bd_size_t size);
+
+    /** Get the size of a readable block
+     *
+     *  @return         Size of a readable block in bytes
+     */
+    virtual bd_size_t get_read_size() const;
+
+    /** Get the size of a programable block
+     *
+     *  @return         Size of a programable block in bytes
+     *  @note Must be a multiple of the read size
+     */
+    virtual bd_size_t get_program_size() const;
+
+    /** Get the size of a eraseable block
+     *
+     *  @return         Size of a eraseable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size() const;
+
+    /** Get the size of a eraseable block
+     *
+     *  @param addr     Address of block queried for erase sector size
+     *  @return         Size of a eraseable sector in bytes
+     *  @note Must be a multiple of the program size
+     */
+    bd_size_t get_erase_size(bd_addr_t addr);
+
+    /** Get the total size of the underlying device
+     *
+     *  @return         Size of the underlying device in bytes
+     */
+    virtual bd_size_t size() const;
+
+private:
+    // Internal functions
+
+    /********************************/
+    /*   Calls to QSPI Driver APIs  */
+    /********************************/
+    // Send Program => Write command to Driver
+    qspi_status_t _qspiSendProgramCommand(unsigned int progInstruction, const void *buffer, bd_addr_t addr,
+                                          bd_size_t *size);
+
+    // Send Read command to Driver
+    qspi_status_t _qspiSendReadCommand(unsigned int readInstruction, void *buffer, bd_addr_t addr, bd_size_t size);
+
+    // Send Erase => command_transfer command to Driver
+    qspi_status_t _qspiSendEraseCommand(unsigned int eraseInstruction, bd_addr_t addr, bd_size_t size);
+
+    // Send Generic command_transfer command to Driver
+    qspi_status_t _qspiSendGeneralCommand(unsigned int instructionint, bd_addr_t addr, const char *tx_buffer,
+                                          size_t tx_length, const char *rx_buffer, size_t rx_length);
+
+    // Send Bus configure_format command to Driver
+    qspi_status_t _qspiConfiureFormat(qspi_bus_width_t inst_width, qspi_bus_width_t address_width,
+                                      qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width,
+                                      int dummy_cycles);
+
+    // Send set_frequency command to Driver
+    qspi_status_t _qspiSetFrequency(int freq);
+    /********************************/
+
+
+    // Verify registers and Reset Flash Memory
+    int _resetFlashMem();
+
+    // Configure Write Enable in Status Register
+    int _setWriteEnable();
+
+    // Wait on status register until write not-in-progress
+    bool _isMemReady();
+
+
+    /* SFDP Detection and Parsing Functions */
+    /****************************************/
+    int _sfdpParseSFDPHeaders(uint32_t& basic_table_addr, size_t& basic_table_size,
+                              uint32_t& sector_map_table_addr, size_t& sector_map_table_size);
+    int _sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size);
+    int _sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size);
+    int _sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool& setQuadEnable, bool& isQPIMode,
+                                   unsigned int& readInst);
+    int _sfdpSetQuadEnabled(uint8_t *basicParamTablePtr);
+    int _sfdpSetQPIEnabled(uint8_t *basicParamTablePtr);
+    int _sfdpDetectPageSize(uint8_t *basicParamTablePtr);
+    int _sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int& erase4KInst,
+                                         unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr);
+
+    /* Utilities Functions */
+    /***********************/
+    int _utilsFindAddrRegion(int offset);
+    int _utilsIterateNextLargestEraseType(uint8_t& bitfield, int size, int offset, int boundry);
+    int _utilsMathPower(int base, int exp);
+
+private:
+
+    // QSPI Driver Object
+    QSPI _qspi;
+    //DigitalOut _cs;
+    bool is_initialized;
+    static SingletonPtr<PlatformMutex> _mutex;
+
+    // Command Instructions
+    unsigned int _readInstruction;
+    unsigned int _progInstruction;
+    unsigned int _eraseInstruction;
+    unsigned int _erase4KInst;
+    unsigned int _eraseTypeInstArr[4];
+    unsigned int _eraseTypeSizeArr[4];
+
+    // Sector Regions Map
+    int _regions_count; //number of regions
+    int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size
+    int _region_high_boundary[QSPIF_MAX_REGIONS]; //region high address offset boundary
+    uint8_t _region_erase_types[QSPIF_MAX_REGIONS]; //region erase type
+    int _minCommonEraseType; // minimal common erase size for all regions (-1 if none)
+    int _minCommonEraseSize; // minimal common erase size for all regions
+
+    int _pageSizeBytes; // Page size - 256 Bytes default
+    bd_size_t _deviceSizeBytes;
+
+    // Bus speed configuration
+    qspi_bus_width_t _inst_width; //Bus width for Instruction phase
+    qspi_bus_width_t _address_width; //Bus width for Address phase
+    qspi_address_size_t _address_size;
+    qspi_bus_width_t _alt_width; //Bus width for Alt phase
+    qspi_alt_size_t _alt_size;
+    qspi_bus_width_t _data_width; //Bus width for Data phase
+    int _dummy_and_mode_cycles;
+
+
+};
+
+#endif