From 91e70b2f75a73509381800c86dce38c24044b0f6 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Fri, 3 Nov 2017 13:55:45 +0000
Subject: [PATCH 01/61] QSPI HAL addition
Adding new QSPI HAL header file. This should help to use memory-maped devices
as memories, graphical displays.
The API consist of few functions, most important are read/write/write_command functions.
The command format is:
```
----------------------------------------------
| Instruction | Address | Alt | Dummy | Data |
----------------------------------------------
```
We define only synch API at the moment.
---
hal/qspi_api.h | 186 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
create mode 100644 hal/qspi_api.h
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
new file mode 100644
index 00000000000..0c6503446e2
--- /dev/null
+++ b/hal/qspi_api.h
@@ -0,0 +1,186 @@
+
+/** \addtogroup hal */
+/** @{*/
+/* mbed Microcontroller Library
+ * Copyright (c) 2017 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_QSPI_API_H
+#define MBED_QSPI_API_H
+
+#include "device.h"
+
+#if DEVICE_QSPI
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup hal_qspi QSPI HAL
+ * @{
+ */
+
+/** QSPI HAL object declaration
+ */
+typedef struct qspi_s qspi_t;
+
+/** QSPI Bus width
+ *
+ * Some parts of commands provide variable bus width
+ */
+typedef enum qspi_bus_width {
+ QSPI_CFG_BUS_SINGLE,
+ QSPI_CFG_BUS_DUAL,
+ QSPI_CFG_BUS_QUAD,
+} qspi_bus_width_t;
+
+/** Address size
+ */
+typedef enum qspi_address_size {
+ QSPI_CFG_ADDR_SIZE_8,
+ QSPI_CFG_ADDR_SIZE_16,
+ QSPI_CFG_ADDR_SIZE_24,
+ QSPI_CFG_ADDR_SIZE_32,
+} qspi_address_size_t;
+
+/** Alternative size
+ */
+typedef enum qspi_alt_size {
+ QSPI_CFG_ALT_SIZE_8,
+ QSPI_CFG_ALT_SIZE_16,
+ QSPI_CFG_ALT_SIZE_24,
+ QSPI_CFG_ALT_SIZE_32,
+} qspi_alt_size_t;
+
+/** QSPI command declaration
+ *
+ * Defines a frame format
+ */
+typedef struct qspi_command {
+ struct instruction {
+ qspi_bus_width_t bus_width; /**< Bus width for the instruction >*/
+ uint8_t value; /**< Instruction, 0 - disabled, non-zero defined value used >*/
+ };
+ struct address {
+ qspi_bus_width_t bus_width; /**< Bus width for the address >*/
+ qspi_address_size_t size; /**< Address size >*/
+ uint32_t value; /**< Address, 0 - disabled, non-zero defined value used >*/
+ };
+ struct alt {
+ qspi_bus_width_t bus_width; /**< Bus width for alternative >*/
+ qspi_alt_size_t size; /**< Alternative size >*/
+ uint32_t value; /**< Alternative, 0 - disabled, non-zero defined value used >*/
+ };
+ uint8_t dummy_count; /**< Dummy cycles count >*/
+ struct data {
+ qspi_bus_width_t bus_width; /**< Bus width for data >*/
+ };
+} qspi_command_t;
+
+/** QSPI return status
+ */
+typedef enum qspi_status {
+ QSPI_STATUS_ERROR = -1, /**< Generic error >*/
+ QSPI_STATUS_INVALID_PARAMETER = -2, /**< The parameter is invalid >*/
+ QSPI_STATUS_OK = 0, /**< Function executed sucessfully >*/
+} qspi_status_t;
+
+/** Initialize QSPI peripheral.
+ *
+ * It should initialize QSPI pins (io0-io3, sclk and ssel), set frequency and SPI mode. The clock for the peripheral should be enabled
+ *
+ * @param obj QSPI object
+ * @param io0 Data pin 0
+ * @param io1 Data pin 1
+ * @param io2 Data pin 2
+ * @param io3 Data pin 3
+ * @param sclk The clock pin
+ * @param ssel The chip select pin
+ * @param hz The bus frequency
+ * @param mode SPI mode
+ * @return QSPI_STATUS_OK if initialisation successfully executed
+ QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
+ QSPI_STATUS_ERROR otherwise
+ */
+qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, uint32_t hz, uint8_t mode);
+
+/** Deinitilize QSPI peripheral
+ *
+ * It should release pins that are associated with the QSPI object, and disable clocks for QSPI peripheral module that was associated with the object
+ *
+ * @param obj QSPI object
+ * @return QSPI_STATUS_OK if deinitialisation successfully executed
+ QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
+ QSPI_STATUS_ERROR otherwise
+ */
+qspi_status_t qspi_free(qspi_t *obj);
+
+/** Set the QSPI baud rate
+ *
+ * Actual frequency may differ from the desired frequency due to available dividers and the bus clock
+ * Configures the QSPI peripheral's baud rate
+ * @param obj The SPI object to configure
+ * @param hz The baud rate in Hz
+ * @return QSPI_STATUS_OK if frequency was set
+ QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
+ QSPI_STATUS_ERROR otherwise
+ */
+qspi_status_t qspi_frequency(qspi_t *obj, int hz);
+
+/** Send only QSPI command
+ *
+ * @param obj QSPI object
+ * @param command QSPI command
+ * @return QSPI_STATUS_OK if command was sent without any error
+ QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
+ QSPI_STATUS_ERROR otherwise
+ */
+qspi_status_t qspi_write_command(qspi_t *obj, const qspi_command_t *command);
+
+/** Send a command and block of data
+ *
+ * @param obj QSPI object
+ * @param command QSPI command
+ * @param data TX buffer
+ * @param length TX buffer length in bytes
+ * @return QSPI_STATUS_OK if the data has been succesfully sent
+ QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
+ QSPI_STATUS_ERROR otherwise
+ */
+qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t length);
+
+/** Receive a command and block of data
+ *
+ * @param obj QSPI object
+ * @param command QSPI command
+ * @param data RX buffer
+ * @param length RX buffer length in bytes
+ * @return QSPI_STATUS_OK if data has been succesfully received
+ QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
+ QSPI_STATUS_ERROR otherwise
+ */
+qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t length);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
+
+/** @}*/
From db60d5791a47fc98990e11f473c7f6e57eaa4879 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 7 Nov 2017 14:31:24 +0000
Subject: [PATCH 02/61] QSPI: fix address/alt variable sizes (can be skipped)
Fixing by adding NONE values for both
---
hal/qspi_api.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 0c6503446e2..2b94fe9b84f 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -49,6 +49,7 @@ typedef enum qspi_bus_width {
/** Address size
*/
typedef enum qspi_address_size {
+ QSPI_CFG_ADDR_SIZE_NONE,
QSPI_CFG_ADDR_SIZE_8,
QSPI_CFG_ADDR_SIZE_16,
QSPI_CFG_ADDR_SIZE_24,
@@ -58,6 +59,7 @@ typedef enum qspi_address_size {
/** Alternative size
*/
typedef enum qspi_alt_size {
+ QSPI_CFG_ALT_SIZE_NONE,
QSPI_CFG_ALT_SIZE_8,
QSPI_CFG_ALT_SIZE_16,
QSPI_CFG_ALT_SIZE_24,
@@ -71,12 +73,12 @@ typedef enum qspi_alt_size {
typedef struct qspi_command {
struct instruction {
qspi_bus_width_t bus_width; /**< Bus width for the instruction >*/
- uint8_t value; /**< Instruction, 0 - disabled, non-zero defined value used >*/
+ uint8_t value; /**< Instruction value >*/
};
struct address {
qspi_bus_width_t bus_width; /**< Bus width for the address >*/
qspi_address_size_t size; /**< Address size >*/
- uint32_t value; /**< Address, 0 - disabled, non-zero defined value used >*/
+ uint32_t value; /**< Address value >*/
};
struct alt {
qspi_bus_width_t bus_width; /**< Bus width for alternative >*/
From bae69490733b84cf9f97c882a2ee314453aa442e Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 7 Nov 2017 14:36:16 +0000
Subject: [PATCH 03/61] QSPI: change length to be in/out parameter
This provides a way to return how many bytes have been written/read (as status codes
are returned via func ret value)
---
hal/qspi_api.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 2b94fe9b84f..0348c15d179 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -156,24 +156,24 @@ qspi_status_t qspi_write_command(qspi_t *obj, const qspi_command_t *command);
* @param obj QSPI object
* @param command QSPI command
* @param data TX buffer
- * @param length TX buffer length in bytes
+ * @param[in,out] in - length TX buffer length in bytes, out - number of bytes written
* @return QSPI_STATUS_OK if the data has been succesfully sent
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
*/
-qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t length);
+qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length);
/** Receive a command and block of data
*
* @param obj QSPI object
* @param command QSPI command
* @param data RX buffer
- * @param length RX buffer length in bytes
+ * @param[in,out] in - length RX buffer length in bytes, out - number of bytes read
* @return QSPI_STATUS_OK if data has been succesfully received
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
*/
-qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t length);
+qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length);
/**@}*/
From a905dfbf6866f76ff8bb3e0782ff7559214098e5 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Wed, 8 Nov 2017 13:58:57 +0000
Subject: [PATCH 04/61] QSPI: improve mode documentation
SPI mode means Clock polarity and phase mode (0 - 3)
---
hal/qspi_api.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 0348c15d179..c6475196e74 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -101,7 +101,7 @@ typedef enum qspi_status {
/** Initialize QSPI peripheral.
*
- * It should initialize QSPI pins (io0-io3, sclk and ssel), set frequency and SPI mode. The clock for the peripheral should be enabled
+ * It should initialize QSPI pins (io0-io3, sclk and ssel), set frequency, clock polarity and phase mode. The clock for the peripheral should be enabled
*
* @param obj QSPI object
* @param io0 Data pin 0
@@ -111,7 +111,7 @@ typedef enum qspi_status {
* @param sclk The clock pin
* @param ssel The chip select pin
* @param hz The bus frequency
- * @param mode SPI mode
+ * @param mode Clock polarity and phase mode (0 - 3)
* @return QSPI_STATUS_OK if initialisation successfully executed
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
From bbbd2cfbe64c63c68d9fb25f5ec8fe9ff248e2b7 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Fri, 10 Nov 2017 13:11:59 +0000
Subject: [PATCH 05/61] QSPI: fix command declaration names
---
hal/qspi_api.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index c6475196e74..12667e0fdb0 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -71,24 +71,24 @@ typedef enum qspi_alt_size {
* Defines a frame format
*/
typedef struct qspi_command {
- struct instruction {
+ struct {
qspi_bus_width_t bus_width; /**< Bus width for the instruction >*/
uint8_t value; /**< Instruction value >*/
- };
- struct address {
+ } instruction;
+ struct {
qspi_bus_width_t bus_width; /**< Bus width for the address >*/
qspi_address_size_t size; /**< Address size >*/
uint32_t value; /**< Address value >*/
- };
- struct alt {
+ } address;
+ struct {
qspi_bus_width_t bus_width; /**< Bus width for alternative >*/
qspi_alt_size_t size; /**< Alternative size >*/
uint32_t value; /**< Alternative, 0 - disabled, non-zero defined value used >*/
- };
+ } alt;
uint8_t dummy_count; /**< Dummy cycles count >*/
- struct data {
+ struct {
qspi_bus_width_t bus_width; /**< Bus width for data >*/
- };
+ } data;
} qspi_command_t;
/** QSPI return status
From f813587f28b0942bb2ec31c6f3c69b2ddf6f55c3 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Fri, 10 Nov 2017 12:24:13 +0000
Subject: [PATCH 06/61] QSPI: initial HAL nrf52840 version
This commit adds QSPI HAL implementation for nrf52840 MCU targets
---
.../TARGET_MCU_NRF52840/config/sdk_config.h | 130 +++++++++++
.../TARGET_NRF5x/TARGET_NRF52/objects.h | 11 +
targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c | 214 ++++++++++++++++++
targets/targets.json | 3 +-
4 files changed, 357 insertions(+), 1 deletion(-)
create mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h
index 834e1991563..a3cda38ffa9 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h
@@ -2748,6 +2748,136 @@
//
+// QSPI_ENABLED - nrf_drv_qspi - QSPI peripheral driver.
+//==========================================================
+#ifndef QSPI_ENABLED
+#define QSPI_ENABLED 1
+#endif
+#if QSPI_ENABLED
+// QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns). <0-255>
+
+
+#ifndef QSPI_CONFIG_SCK_DELAY
+#define QSPI_CONFIG_SCK_DELAY 1
+#endif
+
+// QSPI_CONFIG_READOC - Number of data lines and opcode used for reading.
+
+// <0=> FastRead
+// <1=> Read2O
+// <2=> Read2IO
+// <3=> Read4O
+// <4=> Read4IO
+
+#ifndef QSPI_CONFIG_READOC
+#define QSPI_CONFIG_READOC 4
+#endif
+
+// QSPI_CONFIG_WRITEOC - Number of data lines and opcode used for writing.
+
+// <0=> PP
+// <1=> PP2O
+// <2=> PP4O
+// <3=> PP4IO
+
+#ifndef QSPI_CONFIG_WRITEOC
+#define QSPI_CONFIG_WRITEOC 3
+#endif
+
+// QSPI_CONFIG_ADDRMODE - Addressing mode.
+
+// <0=> 24bit
+// <1=> 32bit
+
+#ifndef QSPI_CONFIG_ADDRMODE
+#define QSPI_CONFIG_ADDRMODE 0
+#endif
+
+// QSPI_CONFIG_MODE - SPI mode.
+
+// <0=> Mode 0
+// <1=> Mode 1
+
+#ifndef QSPI_CONFIG_MODE
+#define QSPI_CONFIG_MODE 0
+#endif
+
+// QSPI_CONFIG_FREQUENCY - Frequency divider.
+
+// <0=> 32MHz/1
+// <1=> 32MHz/2
+// <2=> 32MHz/3
+// <3=> 32MHz/4
+// <4=> 32MHz/5
+// <5=> 32MHz/6
+// <6=> 32MHz/7
+// <7=> 32MHz/8
+// <8=> 32MHz/9
+// <9=> 32MHz/10
+// <10=> 32MHz/11
+// <11=> 32MHz/12
+// <12=> 32MHz/13
+// <13=> 32MHz/14
+// <14=> 32MHz/15
+// <15=> 32MHz/16
+
+#ifndef QSPI_CONFIG_FREQUENCY
+#define QSPI_CONFIG_FREQUENCY 1
+#endif
+
+// QSPI_PIN_SCK - SCK pin value.
+#ifndef QSPI_PIN_SCK
+#define QSPI_PIN_SCK NRF_QSPI_PIN_NOT_CONNECTED
+#endif
+
+// QSPI_PIN_CSN - CSN pin value.
+#ifndef QSPI_PIN_CSN
+#define QSPI_PIN_CSN NRF_QSPI_PIN_NOT_CONNECTED
+#endif
+
+// QSPI_PIN_IO0 - IO0 pin value.
+#ifndef QSPI_PIN_IO0
+#define QSPI_PIN_IO0 NRF_QSPI_PIN_NOT_CONNECTED
+#endif
+
+// QSPI_PIN_IO1 - IO1 pin value.
+#ifndef QSPI_PIN_IO1
+#define QSPI_PIN_IO1 NRF_QSPI_PIN_NOT_CONNECTED
+#endif
+
+// QSPI_PIN_IO2 - IO2 pin value.
+#ifndef QSPI_PIN_IO2
+#define QSPI_PIN_IO2 NRF_QSPI_PIN_NOT_CONNECTED
+#endif
+
+// QSPI_PIN_IO3 - IO3 pin value.
+#ifndef QSPI_PIN_IO3
+#define QSPI_PIN_IO3 NRF_QSPI_PIN_NOT_CONNECTED
+#endif
+
+// QSPI_CONFIG_IRQ_PRIORITY - Interrupt priority
+
+
+// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
+// <0=> 0 (highest)
+// <1=> 1
+// <2=> 2
+// <3=> 3
+// <4=> 4
+// <5=> 5
+// <6=> 6
+// <7=> 7
+
+#ifndef QSPI_CONFIG_IRQ_PRIORITY
+#define QSPI_CONFIG_IRQ_PRIORITY 7
+#endif
+
+#endif //QSPI_ENABLED
+
+//
+
+//
+
// TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver
//==========================================================
#ifndef TIMER_ENABLED
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
index 47e6276a829..1a26f28db4c 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
@@ -142,6 +142,17 @@ struct flash_s {
uint32_t placeholder;
};
+#if DEVICE_QSPI
+
+// #include "nrf_drv_qspi.h"
+
+struct qspi_s {
+ uint32_t placeholder;
+ // nrf_drv_qspi_config_t config;
+};
+
+#endif
+
#include "gpio_object.h"
#ifdef __cplusplus
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
new file mode 100644
index 00000000000..b3f547e074f
--- /dev/null
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
+ * integrated circuit in a product or a software update for such product, must reproduce
+ * the above copyright notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary or object form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "qspi_api.h"
+
+#if DEVICE_QSPI
+
+#include "nrf_drv_common.h"
+#include "nrf_drv_qspi.h"
+
+/*
+TODO
+ - config inside obj - nordic headers have some problems with inclusion
+ - free - is it really empty, nothing to do there?
+ - prepare command - support more protocols that nordic can do (now limited)
+ - nordic does not support
+ - alt
+ - dummy cycles
+*/
+
+#define MBED_HAL_QSPI_HZ_TO_CONFIG(hz) ((32000000/(hz))-1)
+#define MBED_HAL_QSPI_MAX_FREQ 32000000UL
+
+static nrf_drv_qspi_config_t config;
+
+qspi_status_t qspi_prepare_command(qspi_t *obj, const qspi_command_t *command, bool write)
+{
+ // we need to remap to command-address-data - x_x_x
+ // most commmon are 1-1-1, 1-1-4, 1-4-4
+ // 1-1-1
+ if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->data.bus_width == QSPI_CFG_BUS_SINGLE) {
+ if (write) {
+ config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_FASTREAD;
+ }
+ // 1-1-4
+ } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->data.bus_width == QSPI_CFG_BUS_QUAD) {
+ // 1_1_4
+ if (write) {
+ config.prot_if.writeoc = QSPI_IFCONFIG0_WRITEOC_PP4O;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_READ4O;
+ }
+ // 1-4-4
+ } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_QUAD &&
+ command->data.bus_width == QSPI_CFG_BUS_QUAD) {
+ // 1_4_4
+ if (write) {
+ config.prot_if.writeoc = QSPI_IFCONFIG0_WRITEOC_PP4IO;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_READ4IO;
+ }
+ }
+
+ qspi_status_t ret = QSPI_STATUS_OK;
+
+ // supporting only 24 or 32 bit address
+ if (command->address.size == QSPI_CFG_ADDR_SIZE_24) {
+ config.prot_if.addrmode = NRF_QSPI_ADDRMODE_24BIT;
+ } else if (command->address.size == QSPI_CFG_ADDR_SIZE_32) {
+ config.prot_if.addrmode = QSPI_CFG_ADDR_SIZE_32;
+ } else {
+ ret = QSPI_STATUS_INVALID_PARAMETER;
+ }
+ return ret;
+}
+
+qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, uint32_t hz, uint8_t mode)
+{
+ (void)(obj);
+ if (hz > MBED_HAL_QSPI_MAX_FREQ) {
+ return QSPI_STATUS_INVALID_PARAMETER;
+ }
+
+ // memset(config, 0, sizeof(config));
+
+ config.pins.sck_pin = (uint32_t)sclk;
+ config.pins.csn_pin = (uint32_t)ssel;
+ config.pins.io0_pin = (uint32_t)io0;
+ config.pins.io1_pin = (uint32_t)io1;
+ config.pins.io2_pin = (uint32_t)io2;
+ config.pins.io3_pin = (uint32_t)io3;
+ config.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY;
+
+ config.phy_if.sck_freq = MBED_HAL_QSPI_HZ_TO_CONFIG(hz),
+ config.phy_if.sck_delay = 0x05,
+ config.phy_if.dpmen = false;
+ config.phy_if.spi_mode = mode == 0 ? NRF_QSPI_MODE_0 : NRF_QSPI_MODE_1;
+
+ nrf_drv_qspi_init(&config, NULL , NULL);
+
+ return 0;
+}
+
+qspi_status_t qspi_free(qspi_t *obj)
+{
+ (void)(obj);
+ // possibly here uninit from SDK driver
+ return QSPI_STATUS_OK;
+}
+
+qspi_status_t qspi_frequency(qspi_t *obj, int hz)
+{
+ config.phy_if.sck_freq = MBED_HAL_QSPI_HZ_TO_CONFIG(hz);
+ // use sync version, no handler
+ ret_code_t ret = nrf_drv_qspi_init(&config, NULL , NULL);
+ if (ret == NRF_SUCCESS ) {
+ return QSPI_STATUS_OK;
+ } else if (ret == NRF_ERROR_INVALID_PARAM) {
+ return QSPI_STATUS_INVALID_PARAMETER;
+ } else {
+ return QSPI_STATUS_ERROR;
+ }
+}
+
+qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length)
+{
+ qspi_status_t status = qspi_prepare_command(obj, command, true);
+ if (status != QSPI_STATUS_OK) {
+ return status;
+ }
+
+ // write here does not return how much it transfered, we return transfered all
+ ret_code_t ret = nrf_drv_qspi_write(data, *length, command->address.value);
+ if (ret == NRF_SUCCESS ) {
+ return QSPI_STATUS_OK;
+ } else {
+ return QSPI_STATUS_ERROR;
+ }
+}
+
+qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length)
+{
+ qspi_status_t status = qspi_prepare_command(obj, command, false);
+ if (status != QSPI_STATUS_OK) {
+ return status;
+ }
+
+ ret_code_t ret = nrf_drv_qspi_read(data, *length, command->address.value);
+ if (ret == NRF_SUCCESS ) {
+ return QSPI_STATUS_OK;
+ } else {
+ return QSPI_STATUS_ERROR;
+ }
+}
+
+// they provide 2 functions write or nrf_drv_qspi_cinstr_xfer
+// nrf_drv_qspi_cinstr_xfer seems like it accepts simplified config that is very simplified
+// and might not be useful for us.
+// write on other hand, needs to write some data (errors if buffer is NULL!)
+qspi_status_t qspi_write_command(qspi_t *obj, const qspi_command_t *command)
+{
+ // use simplified API, as we are sending only instruction here
+ nrf_qspi_cinstr_conf_t config;
+ config.length = NRF_QSPI_CINSTR_LEN_1B; // no data
+ config.opcode = command->instruction.value;
+ config.io2_level = false;
+ config.io3_level = false;
+ config.wipwait = false;
+ config.wren = false;
+
+ // no data phase, send only config
+ ret_code_t ret = nrf_drv_qspi_cinstr_xfer(&config, NULL, NULL);
+ if (ret == NRF_SUCCESS ) {
+ return QSPI_STATUS_OK;
+ } else {
+ return QSPI_STATUS_ERROR;
+ }
+}
+
+#endif
+
+/** @}*/
diff --git a/targets/targets.json b/targets/targets.json
index b39430eb64a..50adc78d8ee 100755
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -3776,7 +3776,8 @@
"SPI_ASYNCH",
"STCLK_OFF_DURING_SLEEP",
"TRNG",
- "USTICKER"
+ "USTICKER",
+ "QSPI"
],
"extra_labels": [
"NORDIC",
From fe3c3ab360dd6e767d649887f2651ba79d3969f5 Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Wed, 22 Nov 2017 19:02:56 -0600
Subject: [PATCH 07/61] Modify QSPI HAL API to include an API for
command-transfer operations
---
hal/qspi_api.h | 20 ++-
targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c | 162 ++++++++++++------
2 files changed, 119 insertions(+), 63 deletions(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 12667e0fdb0..8982aea5023 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -141,27 +141,33 @@ qspi_status_t qspi_free(qspi_t *obj);
*/
qspi_status_t qspi_frequency(qspi_t *obj, int hz);
-/** Send only QSPI command
+/** Send a command and block of data
*
* @param obj QSPI object
* @param command QSPI command
- * @return QSPI_STATUS_OK if command was sent without any error
+ * @param data TX buffer
+ * @param[in,out] in - length TX buffer length in bytes, out - number of bytes written
+ * @return QSPI_STATUS_OK if the data has been succesfully sent
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
*/
-qspi_status_t qspi_write_command(qspi_t *obj, const qspi_command_t *command);
+qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length);
-/** Send a command and block of data
+/** Send a command (and optionally data) and get the response. Can be used to send/receive device specific commands.
*
* @param obj QSPI object
* @param command QSPI command
- * @param data TX buffer
- * @param[in,out] in - length TX buffer length in bytes, out - number of bytes written
+ * @param tx_data TX buffer
+ * @param tx_length pointer to variable holding TX buffer length
+ * @param rx_data TX buffer
+ * @param rx_length pointer to variable holding TX buffer length
* @return QSPI_STATUS_OK if the data has been succesfully sent
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
*/
-qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length);
+
+qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size);
+
/** Receive a command and block of data
*
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
index b3f547e074f..10c8e6b1fc5 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
@@ -53,56 +53,79 @@ TODO
- dummy cycles
*/
-#define MBED_HAL_QSPI_HZ_TO_CONFIG(hz) ((32000000/(hz))-1)
-#define MBED_HAL_QSPI_MAX_FREQ 32000000UL
+#define MBED_HAL_QSPI_HZ_TO_CONFIG(hz) ((32000000/(hz))-1)
+#define MBED_HAL_QSPI_MAX_FREQ 32000000UL
static nrf_drv_qspi_config_t config;
qspi_status_t qspi_prepare_command(qspi_t *obj, const qspi_command_t *command, bool write)
{
- // we need to remap to command-address-data - x_x_x
- // most commmon are 1-1-1, 1-1-4, 1-4-4
- // 1-1-1
- if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
- command->address.bus_width == QSPI_CFG_BUS_SINGLE &&
- command->data.bus_width == QSPI_CFG_BUS_SINGLE) {
+ //Use custom command if provided by the caller
+ if(command->instruction.value != 0) {
+ //Use custom command if provided
if (write) {
- config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP;
+ config.prot_if.writeoc = (nrf_qspi_writeoc_t)command->instruction.value;
} else {
- config.prot_if.readoc = NRF_QSPI_READOC_FASTREAD;
+ config.prot_if.readoc = (nrf_qspi_readoc_t)command->instruction.value;
}
- // 1-1-4
- } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
- command->address.bus_width == QSPI_CFG_BUS_SINGLE &&
- command->data.bus_width == QSPI_CFG_BUS_QUAD) {
- // 1_1_4
- if (write) {
- config.prot_if.writeoc = QSPI_IFCONFIG0_WRITEOC_PP4O;
- } else {
- config.prot_if.readoc = NRF_QSPI_READOC_READ4O;
- }
- // 1-4-4
- } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
- command->address.bus_width == QSPI_CFG_BUS_QUAD &&
- command->data.bus_width == QSPI_CFG_BUS_QUAD) {
- // 1_4_4
- if (write) {
- config.prot_if.writeoc = QSPI_IFCONFIG0_WRITEOC_PP4IO;
- } else {
- config.prot_if.readoc = NRF_QSPI_READOC_READ4IO;
+ } else {
+ // we need to remap to command-address-data - x_x_x
+ // most commmon are 1-1-1, 1-1-4, 1-4-4
+ // 1-1-1
+ if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->data.bus_width == QSPI_CFG_BUS_SINGLE) {
+ if (write) {
+ config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_FASTREAD;
+ }
+ // 1-1-4
+ } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->data.bus_width == QSPI_CFG_BUS_QUAD) {
+ // 1_1_4
+ if (write) {
+ config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4O;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_READ4O;
+ }
+ // 1-4-4
+ } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_QUAD &&
+ command->data.bus_width == QSPI_CFG_BUS_QUAD) {
+ // 1_4_4
+ if (write) {
+ config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4IO;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_READ4IO;
+ }
}
- }
-
+ }
+
qspi_status_t ret = QSPI_STATUS_OK;
// supporting only 24 or 32 bit address
if (command->address.size == QSPI_CFG_ADDR_SIZE_24) {
config.prot_if.addrmode = NRF_QSPI_ADDRMODE_24BIT;
} else if (command->address.size == QSPI_CFG_ADDR_SIZE_32) {
- config.prot_if.addrmode = QSPI_CFG_ADDR_SIZE_32;
+ config.prot_if.addrmode = NRF_QSPI_ADDRMODE_32BIT;
} else {
ret = QSPI_STATUS_INVALID_PARAMETER;
}
+
+ //Configure QSPI with new command format
+ if(ret == QSPI_STATUS_OK) {
+ ret_code_t ret_status = nrf_drv_qspi_init(&config, NULL , NULL);
+ if (ret_status != NRF_SUCCESS ) {
+ if (ret_status == NRF_ERROR_INVALID_PARAM) {
+ return QSPI_STATUS_INVALID_PARAMETER;
+ } else {
+ return QSPI_STATUS_ERROR;
+ }
+ }
+ }
+
return ret;
}
@@ -123,14 +146,19 @@ qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinN
config.pins.io3_pin = (uint32_t)io3;
config.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY;
- config.phy_if.sck_freq = MBED_HAL_QSPI_HZ_TO_CONFIG(hz),
+ config.phy_if.sck_freq = (nrf_qspi_frequency_t)MBED_HAL_QSPI_HZ_TO_CONFIG(hz),
config.phy_if.sck_delay = 0x05,
config.phy_if.dpmen = false;
config.phy_if.spi_mode = mode == 0 ? NRF_QSPI_MODE_0 : NRF_QSPI_MODE_1;
- nrf_drv_qspi_init(&config, NULL , NULL);
-
- return 0;
+ ret_code_t ret = nrf_drv_qspi_init(&config, NULL , NULL);
+ if (ret == NRF_SUCCESS ) {
+ return QSPI_STATUS_OK;
+ } else if (ret == NRF_ERROR_INVALID_PARAM) {
+ return QSPI_STATUS_INVALID_PARAMETER;
+ } else {
+ return QSPI_STATUS_ERROR;
+ }
}
qspi_status_t qspi_free(qspi_t *obj)
@@ -142,7 +170,7 @@ qspi_status_t qspi_free(qspi_t *obj)
qspi_status_t qspi_frequency(qspi_t *obj, int hz)
{
- config.phy_if.sck_freq = MBED_HAL_QSPI_HZ_TO_CONFIG(hz);
+ config.phy_if.sck_freq = (nrf_qspi_frequency_t)MBED_HAL_QSPI_HZ_TO_CONFIG(hz);
// use sync version, no handler
ret_code_t ret = nrf_drv_qspi_init(&config, NULL , NULL);
if (ret == NRF_SUCCESS ) {
@@ -185,30 +213,52 @@ qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data,
}
}
-// they provide 2 functions write or nrf_drv_qspi_cinstr_xfer
-// nrf_drv_qspi_cinstr_xfer seems like it accepts simplified config that is very simplified
-// and might not be useful for us.
-// write on other hand, needs to write some data (errors if buffer is NULL!)
-qspi_status_t qspi_write_command(qspi_t *obj, const qspi_command_t *command)
+qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size)
{
- // use simplified API, as we are sending only instruction here
- nrf_qspi_cinstr_conf_t config;
- config.length = NRF_QSPI_CINSTR_LEN_1B; // no data
- config.opcode = command->instruction.value;
- config.io2_level = false;
- config.io3_level = false;
- config.wipwait = false;
- config.wren = false;
-
- // no data phase, send only config
- ret_code_t ret = nrf_drv_qspi_cinstr_xfer(&config, NULL, NULL);
- if (ret == NRF_SUCCESS ) {
- return QSPI_STATUS_OK;
- } else {
+ ret_code_t ret_code;
+ uint32_t i;
+ uint8_t data[8];
+ uint32_t data_size = tx_size + rx_size;
+
+ nrf_qspi_cinstr_conf_t qspi_cinstr_config;
+ qspi_cinstr_config.opcode = command->instruction.value;
+ qspi_cinstr_config.io2_level = false;
+ qspi_cinstr_config.io3_level = false;
+ qspi_cinstr_config.wipwait = false;
+ qspi_cinstr_config.wren = false;
+
+ if (data_size < 9)
+ {
+ qspi_cinstr_config.length = (nrf_qspi_cinstr_len_t)(NRF_QSPI_CINSTR_LEN_1B + data_size);
+ }
+ else
+ {
+ return QSPI_STATUS_ERROR;
+ }
+
+ // preparing data to send
+ for (i = 0; i < tx_size; ++i)
+ {
+ data[i] = ((uint8_t *)tx_data)[i];
+ }
+
+ ret_code = nrf_drv_qspi_cinstr_xfer(&qspi_cinstr_config, data, data);
+ if (ret_code != NRF_SUCCESS)
+ {
return QSPI_STATUS_ERROR;
}
+
+ // preparing received data
+ for (i = 0; i < rx_size; ++i)
+ {
+ // Data is sending as a normal SPI transmission so there is one buffer to send and receive data.
+ ((uint8_t *)rx_data)[i] = data[i];
+ }
+
+ return QSPI_STATUS_OK;
}
+
#endif
/** @}*/
From 29a588859b74e220c92e26652d99e0ff042c4c84 Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Wed, 22 Nov 2017 19:07:47 -0600
Subject: [PATCH 08/61] Enabling QSPI headers in Nordic HAL implementation and
fix for UART STDIO definitions
---
targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h | 4 ++--
.../TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
index 1a26f28db4c..10e19c7b507 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
@@ -144,11 +144,11 @@ struct flash_s {
#if DEVICE_QSPI
-// #include "nrf_drv_qspi.h"
+#include "nrf_drv_qspi.h"
struct qspi_s {
uint32_t placeholder;
- // nrf_drv_qspi_config_t config;
+ nrf_drv_qspi_config_t config;
};
#endif
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c
index 83287313a54..6e8a6aae99d 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c
@@ -122,10 +122,10 @@ ret_code_t nrf_drv_qspi_init(nrf_drv_qspi_config_t const * p_config,
nrf_drv_qspi_handler_t handler,
void * p_context)
{
- if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
+ /*if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
{
return NRF_ERROR_INVALID_STATE;
- }
+ }*/
if (!qspi_pins_configure(&p_config->pins))
{
From 4982703c7479e5bee6056667664c642cd1f104c7 Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Wed, 22 Nov 2017 19:12:13 -0600
Subject: [PATCH 09/61] QSPI driver implementation
---
drivers/QSPI.cpp | 297 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/QSPI.h | 232 ++++++++++++++++++++++++++++++++++++
2 files changed, 529 insertions(+)
create mode 100644 drivers/QSPI.cpp
create mode 100644 drivers/QSPI.h
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
new file mode 100644
index 00000000000..97e91f8aeaf
--- /dev/null
+++ b/drivers/QSPI.cpp
@@ -0,0 +1,297 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 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.
+ */
+#include "drivers/QSPI.h"
+#include "platform/mbed_critical.h"
+
+#if DEVICE_QSPI
+#define IS_BUS_WIDTH_VALID(width) ((width == 1) || (width == 2) || (width == 4))
+#define IS_SIZE_VALID(size) ((size == 8) || (size == 16) || (size == 24) || (size == 32))
+#define IS_ALT_SIZE_VALID(alt_size) ((alt_size == 0) || (alt_size == 8) || (alt_size == 16) || (alt_size == 24) || (alt_size == 32))
+
+namespace mbed {
+
+QSPI* QSPI::_owner = NULL;
+SingletonPtr QSPI::_mutex;
+
+QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) :
+ _qspi(),
+ _inst_width(QSPI_DEFAULT_INST_WIDTH),
+ _address_width(QSPI_DEFAULT_ADDRESS_WIDTH),
+ _address_size(QSPI_DEFAULT_ADDRESS_SIZE),
+ _alt_width(QSPI_DEFAULT_ALT_WIDTH),
+ _alt_size(QSPI_DEFAULT_ALT_SIZE),
+ _data_width(QSPI_DEFAULT_DATA_WIDTH),
+ _num_dummy_cycles(QSPI_DEFAULT_DUMMY_CYCLES),
+ _hz(QSPI_DEFAULT_HZ) {
+ // No lock needed in the constructor
+ _qspi_io0 = io0;
+ _qspi_io1 = io1;
+ _qspi_io2 = io2;
+ _qspi_io3 = io3;
+ _qspi_clk = sclk;
+ _qspi_cs = ssel;
+}
+
+bool QSPI::configure_format(int inst_width,
+ int address_width, int address_size,
+ int alt_width, int alt_size,
+ int data_width,
+ int dummy_cycles,
+ int mode ) {
+ if(!IS_BUS_WIDTH_VALID(inst_width)) return false;
+ if(!IS_BUS_WIDTH_VALID(address_width)) return false;
+ if(!IS_SIZE_VALID(address_size)) return false;
+ if(!IS_BUS_WIDTH_VALID(alt_width)) return false;
+ if(!IS_ALT_SIZE_VALID(alt_size)) return false;
+ if(!IS_BUS_WIDTH_VALID(data_width)) return false;
+ if(dummy_cycles < 0) return false;
+ if(mode != 0 && mode != 1) return false;
+
+ lock();
+ switch(inst_width) {
+ case 1:_inst_width = QSPI_CFG_BUS_SINGLE; break;
+ case 2:_inst_width = QSPI_CFG_BUS_DUAL; break;
+ case 4:_inst_width = QSPI_CFG_BUS_QUAD; break;
+ default:_inst_width = QSPI_CFG_BUS_SINGLE;
+ }
+
+ switch(address_width) {
+ case 1:_address_width = QSPI_CFG_BUS_SINGLE; break;
+ case 2:_address_width = QSPI_CFG_BUS_DUAL; break;
+ case 4:_address_width = QSPI_CFG_BUS_QUAD; break;
+ default:_address_width = QSPI_CFG_BUS_SINGLE;
+ }
+
+ switch(address_size) {
+ case 8:_address_size = QSPI_CFG_ADDR_SIZE_8; break;
+ case 16:_address_size = QSPI_CFG_ADDR_SIZE_16; break;
+ case 24:_address_size = QSPI_CFG_ADDR_SIZE_24; break;
+ case 32:_address_size = QSPI_CFG_ADDR_SIZE_32; break;
+ default:_address_size = QSPI_CFG_ADDR_SIZE_8;
+ }
+
+ switch(alt_width) {
+ case 1:_alt_width = QSPI_CFG_BUS_SINGLE; break;
+ case 2:_alt_width = QSPI_CFG_BUS_DUAL; break;
+ case 4:_alt_width = QSPI_CFG_BUS_QUAD; break;
+ default:_alt_width = QSPI_CFG_BUS_SINGLE;
+ }
+
+ switch(alt_size) {
+ case 0:_alt_size = QSPI_CFG_ALT_SIZE_NONE; break;
+ case 8:_alt_size = QSPI_CFG_ALT_SIZE_8; break;
+ case 16:_alt_size = QSPI_CFG_ALT_SIZE_16; break;
+ case 24:_alt_size = QSPI_CFG_ALT_SIZE_24; break;
+ case 32:_alt_size = QSPI_CFG_ALT_SIZE_32; break;
+ default:_alt_size = QSPI_CFG_ALT_SIZE_NONE;
+ }
+
+ switch(data_width) {
+ case 1:_data_width = QSPI_CFG_BUS_SINGLE; break;
+ case 2:_data_width = QSPI_CFG_BUS_DUAL; break;
+ case 4:_data_width = QSPI_CFG_BUS_QUAD; break;
+ default:_data_width = QSPI_CFG_BUS_SINGLE;
+ }
+
+ _num_dummy_cycles = dummy_cycles;
+ _mode = mode;
+ unlock();
+
+ return true;
+}
+
+bool QSPI::set_frequency(int hz) {
+
+ lock();
+ _hz = hz;
+
+ //If the same owner, just change freq.
+ //Otherwise we may have to change mode as well, so call _acquire
+ if (_owner == this) {
+ qspi_frequency(&_qspi, _hz);
+ } else {
+ _acquire();
+ }
+ unlock();
+
+ return true;
+}
+
+bool QSPI::initialize() {
+ lock();
+ qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
+ unlock();
+
+ return ( ret == QSPI_STATUS_OK )? true:false;
+}
+
+int QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
+ int ret = 0;
+
+ if( (rx_length != NULL) && (rx_buffer != NULL) ) {
+ if(*rx_length != 0) {
+ lock();
+ if( true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
+ if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
+ ret = 1;
+ }
+ }
+ unlock();
+ }
+ }
+
+ return ret;
+}
+
+int QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) {
+ int ret = 0;
+
+ if( (tx_length != NULL) && (tx_buffer != NULL) ) {
+ if(*tx_length != 0) {
+ lock();
+ if(true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
+ if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
+ ret = 1;
+ }
+ }
+ unlock();
+ }
+ }
+
+ return ret;
+}
+
+int QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length) {
+ int ret = 0;
+
+ if( (rx_length != NULL) && (rx_buffer != NULL) ) {
+ if(*rx_length != 0) {
+ lock();
+ if( true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
+ if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
+ ret = 1;
+ }
+ }
+ unlock();
+ }
+ }
+
+ return ret;
+}
+
+int QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length) {
+ int ret = 0;
+
+ if( (tx_length != NULL) && (tx_buffer != NULL) ) {
+ if(*tx_length != 0) {
+ lock();
+ if(true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
+ if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
+ ret = 1;
+ }
+ }
+ unlock();
+ }
+ }
+
+ return ret;
+}
+
+int QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) {
+ int ret = 1;
+
+ lock();
+ if(true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
+ if(QSPI_STATUS_OK != qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
+ //We got error status, return 0
+ ret = 0;
+ }
+ } else {
+ ret = 0;
+ }
+ unlock();
+
+ return ret;
+}
+
+void QSPI::lock() {
+ _mutex->lock();
+}
+
+void QSPI::unlock() {
+ _mutex->unlock();
+}
+
+// Note: Private function with no locking
+bool QSPI::_acquire() {
+ qspi_status_t ret = QSPI_STATUS_OK;
+
+ if (_owner != this) {
+ //This will set freq as well
+ ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
+ _owner = this;
+ }
+
+ return ( ret == QSPI_STATUS_OK )? true:false;
+}
+
+qspi_command_t *QSPI::_build_qspi_command(int instruction, int address, int alt) {
+
+ memset( &_qspi_command, 0, sizeof(qspi_command_t) );
+ //Set up instruction phase parameters
+ _qspi_command.instruction.bus_width = _inst_width;
+ if(instruction != -1) {
+ _qspi_command.instruction.value = instruction;
+ } else {
+ _qspi_command.instruction.value = 0;
+ }
+
+ //Set up address phase parameters
+ _qspi_command.address.bus_width = _address_width;
+ _qspi_command.address.size = _address_size;
+ if(address != -1) {
+ _qspi_command.address.value = address;
+ } else {
+ _qspi_command.address.value = 0;
+ }
+
+ //Set up alt phase parameters
+ _qspi_command.alt.bus_width = _alt_width;
+ _qspi_command.alt.size = _alt_size;
+ if(alt != -1) {
+ _qspi_command.alt.value = alt;
+ } else {
+ //In the case alt phase is absent, set the alt size to be NONE
+ _qspi_command.alt.value = 0;
+ }
+
+ //Set up dummy cycle count
+ _qspi_command.dummy_count = _num_dummy_cycles;
+
+ //Set up bus width for data phase
+ _qspi_command.data.bus_width = _data_width;
+
+ return &_qspi_command;
+}
+
+} // namespace mbed
+
+#endif
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
new file mode 100644
index 00000000000..365d73413c3
--- /dev/null
+++ b/drivers/QSPI.h
@@ -0,0 +1,232 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 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_QSPI_H
+#define MBED_QSPI_H
+
+#include "platform/platform.h"
+
+#if defined (DEVICE_QSPI) || defined(DOXYGEN_ONLY)
+
+#include "platform/PlatformMutex.h"
+#include "hal/qspi_api.h"
+#include "platform/SingletonPtr.h"
+#include "platform/NonCopyable.h"
+
+#define QSPI_DEFAULT_INST_WIDTH QSPI_CFG_BUS_SINGLE //Single bit mode for Instruction as most devices use 1-4-4 mode
+#define QSPI_DEFAULT_ADDRESS_WIDTH QSPI_CFG_BUS_QUAD //QuadSPI mode
+#define QSPI_DEFAULT_ADDRESS_SIZE QSPI_CFG_ADDR_SIZE_32
+#define QSPI_DEFAULT_ALT_WIDTH QSPI_CFG_BUS_QUAD //QuadSPI mode
+#define QSPI_DEFAULT_ALT_SIZE QSPI_CFG_ALT_SIZE_NONE
+#define QSPI_DEFAULT_DATA_WIDTH QSPI_CFG_BUS_QUAD //QuadSPI mode
+#define QSPI_DEFAULT_DUMMY_CYCLES 0
+#define _1_MHZ_ 1000000
+#define QSPI_DEFAULT_HZ _1_MHZ_
+
+namespace mbed {
+/** \addtogroup drivers */
+
+/** A QSPI Driver, used for communicating with QSPI slave devices
+ *
+ * The default format is set to Quad-SPI(4-4-4), and a clock frequency of 1MHz
+ * Most QSPI devices will also require Chip Select which is indicated by ssel.
+ *
+ * @note Synchronization level: Thread safe
+ *
+ * Example:
+ * @code
+ * // Write 4 byte array to a QSPI slave, and read the response, note that each device will have its specific read/write/alt values defined
+ *
+ * #include "mbed.h"
+ *
+ * // hardware ssel (where applicable)
+ * QSPI qspi_device(p5, p6, p7, p8, p9, p10); // io0, io1, io2, io3, sclk, ssel
+ *
+ *
+ * int main() {
+ * char tx_buf[] = { 0x11, 0x22, 0x33, 0x44 };
+ * char rx_buf[4];
+ * int buf_len = sizeof(tx_buf);
+ *
+ * int result = qspi_device.write( 0x12 , 0x100000 , 0 , tx_buf, &buf_len );
+ * if( !result ) printf("Write failed");
+ * int result = qspi_device.read( 0x13 , 0x100000 , 0 , rx_buf, &buf_len );
+ * if( !result ) printf("Read failed");
+ *
+ * }
+ * @endcode
+ * @ingroup drivers
+ */
+class QSPI : private NonCopyable {
+
+public:
+
+ /** Create a QSPI master connected to the specified pins
+ *
+ * io0-io3 is used to specify the Pins used for Quad SPI mode
+ *
+ * @param io0-io3 IO pins used for sending/receiving data during data phase of a transaction
+ * @param sclk QSPI Clock pin
+ * @param ssel QSPI chip select pin
+ */
+ QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel=NC);
+
+ /** Configure the data transmission format
+ *
+ * @param inst_width Bus width used by instruction phase(Valid values are 1,2,4)
+ * @param inst_size Size in bits used by instruction phase(Valid values are NONE,8,16,24,32)
+ * @param address_width Bus width used by address phase(Valid values are 1,2,4)
+ * @param address_size Size in bits used by address phase(Valid values are NONE,8,16,24,32)
+ * @param alt_width Bus width used by alt phase(Valid values are 1,2,4)
+ * @param alt_size Size in bits used by alt phase(Valid values are NONE,8,16,24,32)
+ * @param data_width Bus width used by data phase(Valid values are 1,2,4)
+ * @param dummy_cycles Number of dummy clock cycles to be used after alt phase
+ *
+ * @endcode
+ */
+ bool configure_format(int inst_width = QSPI_DEFAULT_INST_WIDTH,
+ int address_width = QSPI_DEFAULT_ADDRESS_WIDTH,
+ int address_size = QSPI_DEFAULT_ADDRESS_SIZE,
+ int alt_width = QSPI_DEFAULT_ALT_WIDTH,
+ int alt_size = QSPI_DEFAULT_ALT_SIZE,
+ int data_width = QSPI_DEFAULT_DATA_WIDTH,
+ int dummy_cycles = QSPI_DEFAULT_DUMMY_CYCLES,
+ int mode = 0);
+
+ /** Initialize QSPI interface
+ *
+ * This function must be called before doing any operation on the QSPI bus to initialize the interface
+ */
+ bool initialize();
+
+
+ /** Set the qspi bus clock frequency
+ *
+ * @param hz SCLK frequency in hz (default = 1MHz)
+ * @returns
+ * Returns true on successful, fails if the interface is already init-ed
+ */
+ bool set_frequency(int hz = QSPI_DEFAULT_HZ);
+
+ /** Read from QSPI peripheral with the preset read_instruction and alt_value
+ *
+ * @param address Address to be accessed in QSPI peripheral
+ * @param rx_buffer Buffer for data to be read from the peripheral
+ * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
+ *
+ * @returns
+ * Returns 1 on successful reads and 0 on failed reads.
+ */
+ int read(unsigned int address, char *rx_buffer, size_t *rx_length);
+
+ /** Write to QSPI peripheral with the preset write_instruction and alt_value
+ *
+ * @param address Address to be accessed in QSPI peripheral
+ * @param tx_buffer Buffer containing data to be sent to peripheral
+ * @param rx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
+ *
+ * @returns
+ * Returns 1 on successful writes and 0 on failed write operation.
+ */
+ int write(unsigned int address, const char *tx_buffer, size_t *tx_length);
+
+ /** Read from QSPI peripheral using custom read instruction, alt values
+ *
+ * @param instruction Instruction value to be used in instruction phase
+ * @param address Address to be accessed in QSPI peripheral
+ * @param alt Alt value to be used in instruction phase
+ * @param rx_buffer Buffer for data to be read from the peripheral
+ * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
+ *
+ * @returns
+ * Returns 1 on successful reads and 0 on failed reads.
+ */
+ int read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length);
+
+ /** Write to QSPI peripheral using custom write instruction, alt values
+ *
+ * @param instruction Instruction value to be used in instruction phase
+ * @param address Address to be accessed in QSPI peripheral
+ * @param alt Alt value to be used in instruction phase
+ * @param tx_buffer Buffer containing data to be sent to peripheral
+ * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
+ *
+ * @returns
+ * Returns 1 on successful writes and 0 on failed write operation.
+ */
+ int write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length);
+
+ /** Perform a transaction to write to an address(a control register) and get the status results
+ *
+ * @param instruction Instruction value to be used in instruction phase
+ * @param address Address to be accessed in QSPI peripheral
+ * @param alt Alt value to be used in instruction phase
+ * @param tx_buffer Buffer containing data to be sent to peripheral
+ * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
+ * @param rx_buffer Buffer for data to be read from the peripheral
+ * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
+ *
+ * @returns
+ * Returns 1 on successful command transaction and 0 if operation failed.
+ */
+ int command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
+
+ /** Acquire exclusive access to this SPI bus
+ */
+ virtual void lock(void);
+
+ /** Release exclusive access to this SPI bus
+ */
+ virtual void unlock(void);
+
+public:
+ virtual ~QSPI() {
+ }
+
+protected:
+ qspi_t _qspi;
+
+ bool acquire(void);
+ static QSPI *_owner;
+ static SingletonPtr _mutex;
+ 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
+ qspi_command_t _qspi_command; //QSPI Hal command struct
+ int _num_dummy_cycles; //Number of dummy cycles to be used
+ int _hz; //Bus Frequency
+ int _mode; //SPI mode
+ PinName _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs; //IO lines, clock and chip select
+
+private:
+ /* Private acquire function without locking/unlocking
+ * Implemented in order to avoid duplicate locking and boost performance
+ */
+ bool _acquire(void);
+
+ /*
+ * This function builds the qspi command struct to be send to Hal
+ */
+ inline qspi_command_t *_build_qspi_command(int instruction, int address, int alt);
+};
+
+} // namespace mbed
+
+#endif
+
+#endif
From 0373cfb023636d3892602c7bef8887ad0697cfcc Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Mon, 27 Nov 2017 16:52:32 -0600
Subject: [PATCH 10/61] Review fixes and doxygen changes
---
drivers/QSPI.cpp | 164 +++++++++---------
drivers/QSPI.h | 102 +++++++----
.../TARGET_NRF5x/TARGET_NRF52/objects.h | 2 +-
3 files changed, 151 insertions(+), 117 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 97e91f8aeaf..28fe402c192 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "drivers/QSPI.h"
#include "platform/mbed_critical.h"
#if DEVICE_QSPI
-#define IS_BUS_WIDTH_VALID(width) ((width == 1) || (width == 2) || (width == 4))
-#define IS_SIZE_VALID(size) ((size == 8) || (size == 16) || (size == 24) || (size == 32))
-#define IS_ALT_SIZE_VALID(alt_size) ((alt_size == 0) || (alt_size == 8) || (alt_size == 16) || (alt_size == 24) || (alt_size == 32))
+
+#define IS_BUS_WIDTH_VALID(width) ((width == QSPI_BUS_SINGLE) || (width == QSPI_BUS_DUAL) || (width == QSPI_BUS_QUAD))
+#define IS_SIZE_VALID(size) ((size == QSPI_ADDR_SIZE_NONE) || (size == QSPI_ADDR_SIZE_8) || (size == QSPI_ADDR_SIZE_16) || (size == QSPI_ADDR_SIZE_24) || (size == QSPI_ADDR_SIZE_32))
+#define IS_ALT_SIZE_VALID(alt_size) ((alt_size == QSPI_ALT_SIZE_NONE) || (alt_size == QSPI_ALT_SIZE_8) || (alt_size == QSPI_ALT_SIZE_16) || (alt_size == QSPI_ALT_SIZE_24) || (alt_size == QSPI_ALT_SIZE_32))
namespace mbed {
@@ -27,82 +29,78 @@ QSPI* QSPI::_owner = NULL;
SingletonPtr QSPI::_mutex;
QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) :
- _qspi(),
- _inst_width(QSPI_DEFAULT_INST_WIDTH),
- _address_width(QSPI_DEFAULT_ADDRESS_WIDTH),
- _address_size(QSPI_DEFAULT_ADDRESS_SIZE),
- _alt_width(QSPI_DEFAULT_ALT_WIDTH),
- _alt_size(QSPI_DEFAULT_ALT_SIZE),
- _data_width(QSPI_DEFAULT_DATA_WIDTH),
- _num_dummy_cycles(QSPI_DEFAULT_DUMMY_CYCLES),
- _hz(QSPI_DEFAULT_HZ) {
+ _qspi() {
// No lock needed in the constructor
_qspi_io0 = io0;
_qspi_io1 = io1;
_qspi_io2 = io2;
_qspi_io3 = io3;
_qspi_clk = sclk;
- _qspi_cs = ssel;
+ _qspi_cs = ssel;
+ _inst_width = QSPI_CFG_BUS_SINGLE;
+ _address_width = QSPI_CFG_BUS_SINGLE;
+ _address_size = QSPI_CFG_ADDR_SIZE_24;
+ _alt_width = QSPI_CFG_BUS_SINGLE;
+ _alt_size = QSPI_CFG_ALT_SIZE_NONE;
+ _data_width = QSPI_CFG_BUS_SINGLE;
+ _num_dummy_cycles = 0;
+ _mode = 0;
+ _hz = ONE_MHZ;
}
-bool QSPI::configure_format(int inst_width,
- int address_width, int address_size,
- int alt_width, int alt_size,
- int data_width,
- int dummy_cycles,
- int mode ) {
- if(!IS_BUS_WIDTH_VALID(inst_width)) return false;
- if(!IS_BUS_WIDTH_VALID(address_width)) return false;
- if(!IS_SIZE_VALID(address_size)) return false;
- if(!IS_BUS_WIDTH_VALID(alt_width)) return false;
- if(!IS_ALT_SIZE_VALID(alt_size)) return false;
- if(!IS_BUS_WIDTH_VALID(data_width)) return false;
- if(dummy_cycles < 0) return false;
- if(mode != 0 && mode != 1) return false;
+qspi_return_status_t QSPI::configure_format(qspi_config_bus_width_t inst_width, qspi_config_bus_width_t address_width, qspi_config_address_size_t address_size, qspi_config_bus_width_t alt_width, qspi_config_alt_size_t alt_size, qspi_config_bus_width_t data_width, int dummy_cycles, int mode ) {
+ if(!IS_BUS_WIDTH_VALID(inst_width)) return QSPI_INVALID_PARAMETER;
+ if(!IS_BUS_WIDTH_VALID(address_width)) return QSPI_INVALID_PARAMETER;
+ if(!IS_SIZE_VALID(address_size)) return QSPI_INVALID_PARAMETER;
+ if(!IS_BUS_WIDTH_VALID(alt_width)) return QSPI_INVALID_PARAMETER;
+ if(!IS_ALT_SIZE_VALID(alt_size)) return QSPI_INVALID_PARAMETER;
+ if(!IS_BUS_WIDTH_VALID(data_width)) return QSPI_INVALID_PARAMETER;
+ if(dummy_cycles < 0) return QSPI_INVALID_PARAMETER;
+ if(mode != 0 && mode != 1) return QSPI_INVALID_PARAMETER;
lock();
switch(inst_width) {
- case 1:_inst_width = QSPI_CFG_BUS_SINGLE; break;
- case 2:_inst_width = QSPI_CFG_BUS_DUAL; break;
- case 4:_inst_width = QSPI_CFG_BUS_QUAD; break;
+ case QSPI_BUS_SINGLE:_inst_width = QSPI_CFG_BUS_SINGLE; break;
+ case QSPI_BUS_DUAL:_inst_width = QSPI_CFG_BUS_DUAL; break;
+ case QSPI_BUS_QUAD:_inst_width = QSPI_CFG_BUS_QUAD; break;
default:_inst_width = QSPI_CFG_BUS_SINGLE;
}
switch(address_width) {
- case 1:_address_width = QSPI_CFG_BUS_SINGLE; break;
- case 2:_address_width = QSPI_CFG_BUS_DUAL; break;
- case 4:_address_width = QSPI_CFG_BUS_QUAD; break;
+ case QSPI_BUS_SINGLE:_address_width = QSPI_CFG_BUS_SINGLE; break;
+ case QSPI_BUS_DUAL:_address_width = QSPI_CFG_BUS_DUAL; break;
+ case QSPI_BUS_QUAD:_address_width = QSPI_CFG_BUS_QUAD; break;
default:_address_width = QSPI_CFG_BUS_SINGLE;
}
switch(address_size) {
- case 8:_address_size = QSPI_CFG_ADDR_SIZE_8; break;
- case 16:_address_size = QSPI_CFG_ADDR_SIZE_16; break;
- case 24:_address_size = QSPI_CFG_ADDR_SIZE_24; break;
- case 32:_address_size = QSPI_CFG_ADDR_SIZE_32; break;
+ case QSPI_ADDR_SIZE_8:_address_size = QSPI_CFG_ADDR_SIZE_8; break;
+ case QSPI_ADDR_SIZE_16:_address_size = QSPI_CFG_ADDR_SIZE_16; break;
+ case QSPI_ADDR_SIZE_24:_address_size = QSPI_CFG_ADDR_SIZE_24; break;
+ case QSPI_ADDR_SIZE_32:_address_size = QSPI_CFG_ADDR_SIZE_32; break;
default:_address_size = QSPI_CFG_ADDR_SIZE_8;
}
switch(alt_width) {
- case 1:_alt_width = QSPI_CFG_BUS_SINGLE; break;
- case 2:_alt_width = QSPI_CFG_BUS_DUAL; break;
- case 4:_alt_width = QSPI_CFG_BUS_QUAD; break;
+ case QSPI_BUS_SINGLE:_alt_width = QSPI_CFG_BUS_SINGLE; break;
+ case QSPI_BUS_DUAL:_alt_width = QSPI_CFG_BUS_DUAL; break;
+ case QSPI_BUS_QUAD:_alt_width = QSPI_CFG_BUS_QUAD; break;
default:_alt_width = QSPI_CFG_BUS_SINGLE;
}
switch(alt_size) {
- case 0:_alt_size = QSPI_CFG_ALT_SIZE_NONE; break;
- case 8:_alt_size = QSPI_CFG_ALT_SIZE_8; break;
- case 16:_alt_size = QSPI_CFG_ALT_SIZE_16; break;
- case 24:_alt_size = QSPI_CFG_ALT_SIZE_24; break;
- case 32:_alt_size = QSPI_CFG_ALT_SIZE_32; break;
+ case QSPI_ALT_SIZE_NONE:_alt_size = QSPI_CFG_ALT_SIZE_NONE; break;
+ case QSPI_ALT_SIZE_8:_alt_size = QSPI_CFG_ALT_SIZE_8; break;
+ case QSPI_ALT_SIZE_16:_alt_size = QSPI_CFG_ALT_SIZE_16; break;
+ case QSPI_ALT_SIZE_24:_alt_size = QSPI_CFG_ALT_SIZE_24; break;
+ case QSPI_ALT_SIZE_32:_alt_size = QSPI_CFG_ALT_SIZE_32; break;
default:_alt_size = QSPI_CFG_ALT_SIZE_NONE;
}
switch(data_width) {
- case 1:_data_width = QSPI_CFG_BUS_SINGLE; break;
- case 2:_data_width = QSPI_CFG_BUS_DUAL; break;
- case 4:_data_width = QSPI_CFG_BUS_QUAD; break;
+ case QSPI_BUS_SINGLE:_data_width = QSPI_CFG_BUS_SINGLE; break;
+ case QSPI_BUS_DUAL:_data_width = QSPI_CFG_BUS_DUAL; break;
+ case QSPI_BUS_QUAD:_data_width = QSPI_CFG_BUS_QUAD; break;
default:_data_width = QSPI_CFG_BUS_SINGLE;
}
@@ -110,36 +108,38 @@ bool QSPI::configure_format(int inst_width,
_mode = mode;
unlock();
- return true;
+ return QSPI_SUCCESS;
}
-bool QSPI::set_frequency(int hz) {
-
+qspi_return_status_t QSPI::set_frequency(int hz) {
+ qspi_return_status_t ret_status = QSPI_SUCCESS;
lock();
_hz = hz;
//If the same owner, just change freq.
//Otherwise we may have to change mode as well, so call _acquire
if (_owner == this) {
- qspi_frequency(&_qspi, _hz);
+ if(QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) {
+ ret_status = QSPI_ERROR;
+ }
} else {
_acquire();
}
unlock();
- return true;
+ return ret_status;
}
-bool QSPI::initialize() {
+qspi_return_status_t QSPI::initialize() {
lock();
qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
unlock();
- return ( ret == QSPI_STATUS_OK )? true:false;
+ return ( ret == QSPI_STATUS_OK )? QSPI_SUCCESS:QSPI_ERROR;
}
-int QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
- int ret = 0;
+qspi_return_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
+ qspi_return_status_t ret_status = QSPI_ERROR;
if( (rx_length != NULL) && (rx_buffer != NULL) ) {
if(*rx_length != 0) {
@@ -147,18 +147,20 @@ int QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
if( true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
- ret = 1;
+ ret_status = QSPI_SUCCESS;
}
}
unlock();
}
+ } else {
+ ret_status = QSPI_INVALID_PARAMETER;
}
- return ret;
+ return ret_status;
}
-int QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) {
- int ret = 0;
+qspi_return_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) {
+ qspi_return_status_t ret_status = QSPI_ERROR;
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
if(*tx_length != 0) {
@@ -166,18 +168,20 @@ int QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length)
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
- ret = 1;
+ ret_status = QSPI_SUCCESS;
}
}
unlock();
}
+ } else {
+ ret_status = QSPI_INVALID_PARAMETER;
}
- return ret;
+ return ret_status;
}
-int QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length) {
- int ret = 0;
+qspi_return_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length) {
+ qspi_return_status_t ret_status = QSPI_ERROR;
if( (rx_length != NULL) && (rx_buffer != NULL) ) {
if(*rx_length != 0) {
@@ -185,18 +189,20 @@ int QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt,
if( true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
- ret = 1;
+ ret_status = QSPI_SUCCESS;
}
}
unlock();
}
+ } else {
+ ret_status = QSPI_INVALID_PARAMETER;
}
- return ret;
+ return ret_status;
}
-int QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length) {
- int ret = 0;
+qspi_return_status_t QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length) {
+ qspi_return_status_t ret_status = QSPI_ERROR;
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
if(*tx_length != 0) {
@@ -204,32 +210,32 @@ int QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
- ret = 1;
+ ret_status = QSPI_SUCCESS;
}
}
unlock();
}
+ } else {
+ ret_status = QSPI_INVALID_PARAMETER;
}
- return ret;
+ return ret_status;
}
-int QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) {
- int ret = 1;
+qspi_return_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) {
+ qspi_return_status_t ret_status = QSPI_ERROR;
lock();
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
- if(QSPI_STATUS_OK != qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
+ if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
//We got error status, return 0
- ret = 0;
+ ret_status = QSPI_SUCCESS;
}
- } else {
- ret = 0;
- }
+ }
unlock();
- return ret;
+ return ret_status;
}
void QSPI::lock() {
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 365d73413c3..a3b672e30bd 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -20,20 +20,48 @@
#if defined (DEVICE_QSPI) || defined(DOXYGEN_ONLY)
-#include "platform/PlatformMutex.h"
#include "hal/qspi_api.h"
+#include "platform/PlatformMutex.h"
#include "platform/SingletonPtr.h"
#include "platform/NonCopyable.h"
-#define QSPI_DEFAULT_INST_WIDTH QSPI_CFG_BUS_SINGLE //Single bit mode for Instruction as most devices use 1-4-4 mode
-#define QSPI_DEFAULT_ADDRESS_WIDTH QSPI_CFG_BUS_QUAD //QuadSPI mode
-#define QSPI_DEFAULT_ADDRESS_SIZE QSPI_CFG_ADDR_SIZE_32
-#define QSPI_DEFAULT_ALT_WIDTH QSPI_CFG_BUS_QUAD //QuadSPI mode
-#define QSPI_DEFAULT_ALT_SIZE QSPI_CFG_ALT_SIZE_NONE
-#define QSPI_DEFAULT_DATA_WIDTH QSPI_CFG_BUS_QUAD //QuadSPI mode
-#define QSPI_DEFAULT_DUMMY_CYCLES 0
-#define _1_MHZ_ 1000000
-#define QSPI_DEFAULT_HZ _1_MHZ_
+#define ONE_MHZ 1000000
+
+/** QSPI Bus width Enum
+ */
+typedef enum qspi_config_bus_width {
+ QSPI_BUS_SINGLE,
+ QSPI_BUS_DUAL,
+ QSPI_BUS_QUAD,
+} qspi_config_bus_width_t;
+
+/** Address size Enum
+ */
+typedef enum qspi_config_address_size {
+ QSPI_ADDR_SIZE_NONE,
+ QSPI_ADDR_SIZE_8,
+ QSPI_ADDR_SIZE_16,
+ QSPI_ADDR_SIZE_24,
+ QSPI_ADDR_SIZE_32,
+} qspi_config_address_size_t;
+
+/** Alternative size Enum
+ */
+typedef enum qspi_config_alt_size {
+ QSPI_ALT_SIZE_NONE,
+ QSPI_ALT_SIZE_8,
+ QSPI_ALT_SIZE_16,
+ QSPI_ALT_SIZE_24,
+ QSPI_ALT_SIZE_32,
+} qspi_config_alt_size_t;
+
+/** QSPI Driver Return Status Enum
+ */
+typedef enum qspi_return_status {
+ QSPI_ERROR = -1, /**< Generic error >*/
+ QSPI_INVALID_PARAMETER = -2, /**< The parameter is invalid >*/
+ QSPI_SUCCESS = 0, /**< Function executed sucessfully >*/
+} qspi_return_status_t;
namespace mbed {
/** \addtogroup drivers */
@@ -77,7 +105,10 @@ class QSPI : private NonCopyable {
*
* io0-io3 is used to specify the Pins used for Quad SPI mode
*
- * @param io0-io3 IO pins used for sending/receiving data during data phase of a transaction
+ * @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 ssel QSPI chip select pin
*/
@@ -86,39 +117,38 @@ class QSPI : private NonCopyable {
/** Configure the data transmission format
*
* @param inst_width Bus width used by instruction phase(Valid values are 1,2,4)
- * @param inst_size Size in bits used by instruction phase(Valid values are NONE,8,16,24,32)
* @param address_width Bus width used by address phase(Valid values are 1,2,4)
* @param address_size Size in bits used by address phase(Valid values are NONE,8,16,24,32)
* @param alt_width Bus width used by alt phase(Valid values are 1,2,4)
* @param alt_size Size in bits used by alt phase(Valid values are NONE,8,16,24,32)
* @param data_width Bus width used by data phase(Valid values are 1,2,4)
* @param dummy_cycles Number of dummy clock cycles to be used after alt phase
+ * @param mode Mode specifies the SPI mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
*
- * @endcode
*/
- bool configure_format(int inst_width = QSPI_DEFAULT_INST_WIDTH,
- int address_width = QSPI_DEFAULT_ADDRESS_WIDTH,
- int address_size = QSPI_DEFAULT_ADDRESS_SIZE,
- int alt_width = QSPI_DEFAULT_ALT_WIDTH,
- int alt_size = QSPI_DEFAULT_ALT_SIZE,
- int data_width = QSPI_DEFAULT_DATA_WIDTH,
- int dummy_cycles = QSPI_DEFAULT_DUMMY_CYCLES,
- int mode = 0);
+ qspi_return_status_t configure_format(qspi_config_bus_width_t inst_width,
+ qspi_config_bus_width_t address_width,
+ qspi_config_address_size_t address_size,
+ qspi_config_bus_width_t alt_width,
+ qspi_config_alt_size_t alt_size,
+ qspi_config_bus_width_t data_width,
+ int dummy_cycles,
+ int mode);
/** Initialize QSPI interface
*
* This function must be called before doing any operation on the QSPI bus to initialize the interface
*/
- bool initialize();
+ qspi_return_status_t initialize();
/** Set the qspi bus clock frequency
*
* @param hz SCLK frequency in hz (default = 1MHz)
* @returns
- * Returns true on successful, fails if the interface is already init-ed
+ * Returns QSPI_SUCCESS on successful, fails if the interface is already init-ed
*/
- bool set_frequency(int hz = QSPI_DEFAULT_HZ);
+ qspi_return_status_t set_frequency(int hz = ONE_MHZ);
/** Read from QSPI peripheral with the preset read_instruction and alt_value
*
@@ -127,20 +157,20 @@ class QSPI : private NonCopyable {
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
- * Returns 1 on successful reads and 0 on failed reads.
+ * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
*/
- int read(unsigned int address, char *rx_buffer, size_t *rx_length);
+ qspi_return_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length);
/** Write to QSPI peripheral with the preset write_instruction and alt_value
*
* @param address Address to be accessed in QSPI peripheral
* @param tx_buffer Buffer containing data to be sent to peripheral
- * @param rx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
+ * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
*
* @returns
- * Returns 1 on successful writes and 0 on failed write operation.
+ * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
*/
- int write(unsigned int address, const char *tx_buffer, size_t *tx_length);
+ qspi_return_status_t write(unsigned int address, const char *tx_buffer, size_t *tx_length);
/** Read from QSPI peripheral using custom read instruction, alt values
*
@@ -151,9 +181,9 @@ class QSPI : private NonCopyable {
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
- * Returns 1 on successful reads and 0 on failed reads.
+ * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
*/
- int read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length);
+ qspi_return_status_t read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length);
/** Write to QSPI peripheral using custom write instruction, alt values
*
@@ -164,24 +194,22 @@ class QSPI : private NonCopyable {
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
*
* @returns
- * Returns 1 on successful writes and 0 on failed write operation.
+ * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
*/
- int write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length);
+ qspi_return_status_t write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length);
/** Perform a transaction to write to an address(a control register) and get the status results
*
* @param instruction Instruction value to be used in instruction phase
- * @param address Address to be accessed in QSPI peripheral
- * @param alt Alt value to be used in instruction phase
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
* @param rx_buffer Buffer for data to be read from the peripheral
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
- * Returns 1 on successful command transaction and 0 if operation failed.
+ * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
*/
- int command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
+ qspi_return_status_t command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
/** Acquire exclusive access to this SPI bus
*/
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
index 10e19c7b507..39c4b60f678 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h
@@ -148,7 +148,7 @@ struct flash_s {
struct qspi_s {
uint32_t placeholder;
- nrf_drv_qspi_config_t config;
+ //nrf_drv_qspi_config_t config;
};
#endif
From dd111e23595894c520664bee2cbd13b4a56fb625 Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Wed, 29 Nov 2017 14:01:04 -0600
Subject: [PATCH 11/61] Fix code style issues
---
drivers/QSPI.cpp | 132 +++++++++++++++++++++++++++++++++--------------
drivers/QSPI.h | 10 ++--
2 files changed, 100 insertions(+), 42 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 28fe402c192..99a06ed2f18 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -26,8 +26,8 @@
namespace mbed {
QSPI* QSPI::_owner = NULL;
-SingletonPtr QSPI::_mutex;
-
+SingletonPtr QSPI::_mutex;
+
QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) :
_qspi() {
// No lock needed in the constructor
@@ -49,59 +49,115 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
}
qspi_return_status_t QSPI::configure_format(qspi_config_bus_width_t inst_width, qspi_config_bus_width_t address_width, qspi_config_address_size_t address_size, qspi_config_bus_width_t alt_width, qspi_config_alt_size_t alt_size, qspi_config_bus_width_t data_width, int dummy_cycles, int mode ) {
- if(!IS_BUS_WIDTH_VALID(inst_width)) return QSPI_INVALID_PARAMETER;
- if(!IS_BUS_WIDTH_VALID(address_width)) return QSPI_INVALID_PARAMETER;
- if(!IS_SIZE_VALID(address_size)) return QSPI_INVALID_PARAMETER;
- if(!IS_BUS_WIDTH_VALID(alt_width)) return QSPI_INVALID_PARAMETER;
- if(!IS_ALT_SIZE_VALID(alt_size)) return QSPI_INVALID_PARAMETER;
- if(!IS_BUS_WIDTH_VALID(data_width)) return QSPI_INVALID_PARAMETER;
- if(dummy_cycles < 0) return QSPI_INVALID_PARAMETER;
- if(mode != 0 && mode != 1) return QSPI_INVALID_PARAMETER;
+ if(!IS_BUS_WIDTH_VALID(inst_width))
+ return QSPI_INVALID_PARAMETER;
+ if(!IS_BUS_WIDTH_VALID(address_width))
+ return QSPI_INVALID_PARAMETER;
+ if(!IS_SIZE_VALID(address_size))
+ return QSPI_INVALID_PARAMETER;
+ if(!IS_BUS_WIDTH_VALID(alt_width))
+ return QSPI_INVALID_PARAMETER;
+ if(!IS_ALT_SIZE_VALID(alt_size))
+ return QSPI_INVALID_PARAMETER;
+ if(!IS_BUS_WIDTH_VALID(data_width))
+ return QSPI_INVALID_PARAMETER;
+ if(dummy_cycles < 0)
+ return QSPI_INVALID_PARAMETER;
+ if(mode != 0 && mode != 1)
+ return QSPI_INVALID_PARAMETER;
lock();
switch(inst_width) {
- case QSPI_BUS_SINGLE:_inst_width = QSPI_CFG_BUS_SINGLE; break;
- case QSPI_BUS_DUAL:_inst_width = QSPI_CFG_BUS_DUAL; break;
- case QSPI_BUS_QUAD:_inst_width = QSPI_CFG_BUS_QUAD; break;
- default:_inst_width = QSPI_CFG_BUS_SINGLE;
+ case QSPI_BUS_SINGLE:
+ _inst_width = QSPI_CFG_BUS_SINGLE;
+ break;
+ case QSPI_BUS_DUAL:
+ _inst_width = QSPI_CFG_BUS_DUAL;
+ break;
+ case QSPI_BUS_QUAD:
+ _inst_width = QSPI_CFG_BUS_QUAD;
+ break;
+ default:
+ _inst_width = QSPI_CFG_BUS_SINGLE;
}
switch(address_width) {
- case QSPI_BUS_SINGLE:_address_width = QSPI_CFG_BUS_SINGLE; break;
- case QSPI_BUS_DUAL:_address_width = QSPI_CFG_BUS_DUAL; break;
- case QSPI_BUS_QUAD:_address_width = QSPI_CFG_BUS_QUAD; break;
- default:_address_width = QSPI_CFG_BUS_SINGLE;
+ case QSPI_BUS_SINGLE:
+ _address_width = QSPI_CFG_BUS_SINGLE;
+ break;
+ case QSPI_BUS_DUAL:
+ _address_width = QSPI_CFG_BUS_DUAL;
+ break;
+ case QSPI_BUS_QUAD:
+ _address_width = QSPI_CFG_BUS_QUAD;
+ break;
+ default:
+ _address_width = QSPI_CFG_BUS_SINGLE;
}
switch(address_size) {
- case QSPI_ADDR_SIZE_8:_address_size = QSPI_CFG_ADDR_SIZE_8; break;
- case QSPI_ADDR_SIZE_16:_address_size = QSPI_CFG_ADDR_SIZE_16; break;
- case QSPI_ADDR_SIZE_24:_address_size = QSPI_CFG_ADDR_SIZE_24; break;
- case QSPI_ADDR_SIZE_32:_address_size = QSPI_CFG_ADDR_SIZE_32; break;
- default:_address_size = QSPI_CFG_ADDR_SIZE_8;
+ case QSPI_ADDR_SIZE_8:
+ _address_size = QSPI_CFG_ADDR_SIZE_8;
+ break;
+ case QSPI_ADDR_SIZE_16:
+ _address_size = QSPI_CFG_ADDR_SIZE_16;
+ break;
+ case QSPI_ADDR_SIZE_24:
+ _address_size = QSPI_CFG_ADDR_SIZE_24;
+ break;
+ case QSPI_ADDR_SIZE_32:
+ _address_size = QSPI_CFG_ADDR_SIZE_32;
+ break;
+ default:
+ _address_size = QSPI_CFG_ADDR_SIZE_8;
}
switch(alt_width) {
- case QSPI_BUS_SINGLE:_alt_width = QSPI_CFG_BUS_SINGLE; break;
- case QSPI_BUS_DUAL:_alt_width = QSPI_CFG_BUS_DUAL; break;
- case QSPI_BUS_QUAD:_alt_width = QSPI_CFG_BUS_QUAD; break;
- default:_alt_width = QSPI_CFG_BUS_SINGLE;
+ case QSPI_BUS_SINGLE:
+ _alt_width = QSPI_CFG_BUS_SINGLE;
+ break;
+ case QSPI_BUS_DUAL:
+ _alt_width = QSPI_CFG_BUS_DUAL;
+ break;
+ case QSPI_BUS_QUAD:
+ _alt_width = QSPI_CFG_BUS_QUAD;
+ break;
+ default:
+ _alt_width = QSPI_CFG_BUS_SINGLE;
}
switch(alt_size) {
- case QSPI_ALT_SIZE_NONE:_alt_size = QSPI_CFG_ALT_SIZE_NONE; break;
- case QSPI_ALT_SIZE_8:_alt_size = QSPI_CFG_ALT_SIZE_8; break;
- case QSPI_ALT_SIZE_16:_alt_size = QSPI_CFG_ALT_SIZE_16; break;
- case QSPI_ALT_SIZE_24:_alt_size = QSPI_CFG_ALT_SIZE_24; break;
- case QSPI_ALT_SIZE_32:_alt_size = QSPI_CFG_ALT_SIZE_32; break;
- default:_alt_size = QSPI_CFG_ALT_SIZE_NONE;
+ case QSPI_ALT_SIZE_NONE:
+ _alt_size = QSPI_CFG_ALT_SIZE_NONE;
+ break;
+ case QSPI_ALT_SIZE_8:
+ _alt_size = QSPI_CFG_ALT_SIZE_8;
+ break;
+ case QSPI_ALT_SIZE_16:
+ _alt_size = QSPI_CFG_ALT_SIZE_16;
+ break;
+ case QSPI_ALT_SIZE_24:
+ _alt_size = QSPI_CFG_ALT_SIZE_24;
+ break;
+ case QSPI_ALT_SIZE_32:
+ _alt_size = QSPI_CFG_ALT_SIZE_32;
+ break;
+ default:
+ _alt_size = QSPI_CFG_ALT_SIZE_NONE;
}
switch(data_width) {
- case QSPI_BUS_SINGLE:_data_width = QSPI_CFG_BUS_SINGLE; break;
- case QSPI_BUS_DUAL:_data_width = QSPI_CFG_BUS_DUAL; break;
- case QSPI_BUS_QUAD:_data_width = QSPI_CFG_BUS_QUAD; break;
- default:_data_width = QSPI_CFG_BUS_SINGLE;
+ case QSPI_BUS_SINGLE:
+ _data_width = QSPI_CFG_BUS_SINGLE;
+ break;
+ case QSPI_BUS_DUAL:
+ _data_width = QSPI_CFG_BUS_DUAL;
+ break;
+ case QSPI_BUS_QUAD:
+ _data_width = QSPI_CFG_BUS_QUAD;
+ break;
+ default:
+ _data_width = QSPI_CFG_BUS_SINGLE;
}
_num_dummy_cycles = dummy_cycles;
@@ -135,7 +191,7 @@ qspi_return_status_t QSPI::initialize() {
qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
unlock();
- return ( ret == QSPI_STATUS_OK )? QSPI_SUCCESS:QSPI_ERROR;
+ return ( ret == QSPI_STATUS_OK )? QSPI_SUCCESS : QSPI_ERROR;
}
qspi_return_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index a3b672e30bd..f71bd106add 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -27,6 +27,9 @@
#define ONE_MHZ 1000000
+namespace mbed {
+
+// Config/Mode Defines
/** QSPI Bus width Enum
*/
typedef enum qspi_config_bus_width {
@@ -61,9 +64,8 @@ typedef enum qspi_return_status {
QSPI_ERROR = -1, /**< Generic error >*/
QSPI_INVALID_PARAMETER = -2, /**< The parameter is invalid >*/
QSPI_SUCCESS = 0, /**< Function executed sucessfully >*/
-} qspi_return_status_t;
-
-namespace mbed {
+} qspi_return_status_t;
+
/** \addtogroup drivers */
/** A QSPI Driver, used for communicating with QSPI slave devices
@@ -100,7 +102,7 @@ namespace mbed {
class QSPI : private NonCopyable {
public:
-
+
/** Create a QSPI master connected to the specified pins
*
* io0-io3 is used to specify the Pins used for Quad SPI mode
From d4389a999e3c6fc7f65b1955c2548eef24b9d112 Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Thu, 30 Nov 2017 11:45:44 -0600
Subject: [PATCH 12/61] Add support for 1_1_2 and 1_2_2 modes in HAL
---
targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c | 22 ++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
index 10c8e6b1fc5..63f07e109b9 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
@@ -100,11 +100,31 @@ qspi_status_t qspi_prepare_command(qspi_t *obj, const qspi_command_t *command, b
} else {
config.prot_if.readoc = NRF_QSPI_READOC_READ4IO;
}
+ // 1-1-2
+ } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->data.bus_width == QSPI_CFG_BUS_DUAL) {
+ // 1-1-2
+ if (write) {
+ config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP2O;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_READ2O;
+ }
+ // 1-2-2
+ } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE &&
+ command->address.bus_width == QSPI_CFG_BUS_DUAL &&
+ command->data.bus_width == QSPI_CFG_BUS_DUAL) {
+ // 1-2-2
+ if (write) {
+ //Currently NRF52840 does not define PP2IO, so use PP2O for 1-2-2 mode
+ config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP2O;
+ } else {
+ config.prot_if.readoc = NRF_QSPI_READOC_READ2IO;
+ }
}
}
qspi_status_t ret = QSPI_STATUS_OK;
-
// supporting only 24 or 32 bit address
if (command->address.size == QSPI_CFG_ADDR_SIZE_24) {
config.prot_if.addrmode = NRF_QSPI_ADDRMODE_24BIT;
From a6e3e2320fe82615a66f3ce8653892f87fdc5b0c Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Thu, 30 Nov 2017 11:46:25 -0600
Subject: [PATCH 13/61] Changing config and return definitions to adhere to HAL
defs
---
drivers/QSPI.cpp | 174 ++++++++++++-----------------------------------
drivers/QSPI.h | 75 ++++++--------------
2 files changed, 62 insertions(+), 187 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 99a06ed2f18..451180f8cf2 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -19,9 +19,9 @@
#if DEVICE_QSPI
-#define IS_BUS_WIDTH_VALID(width) ((width == QSPI_BUS_SINGLE) || (width == QSPI_BUS_DUAL) || (width == QSPI_BUS_QUAD))
-#define IS_SIZE_VALID(size) ((size == QSPI_ADDR_SIZE_NONE) || (size == QSPI_ADDR_SIZE_8) || (size == QSPI_ADDR_SIZE_16) || (size == QSPI_ADDR_SIZE_24) || (size == QSPI_ADDR_SIZE_32))
-#define IS_ALT_SIZE_VALID(alt_size) ((alt_size == QSPI_ALT_SIZE_NONE) || (alt_size == QSPI_ALT_SIZE_8) || (alt_size == QSPI_ALT_SIZE_16) || (alt_size == QSPI_ALT_SIZE_24) || (alt_size == QSPI_ALT_SIZE_32))
+#define IS_BUS_WIDTH_VALID(width) ((width == QSPI_CFG_BUS_SINGLE) || (width == QSPI_CFG_BUS_DUAL) || (width == QSPI_CFG_BUS_QUAD))
+#define IS_SIZE_VALID(size) ((size == QSPI_CFG_ADDR_SIZE_NONE) || (size == QSPI_CFG_ADDR_SIZE_8) || (size == QSPI_CFG_ADDR_SIZE_16) || (size == QSPI_CFG_ADDR_SIZE_24) || (size == QSPI_CFG_ADDR_SIZE_32))
+#define IS_ALT_SIZE_VALID(alt_size) ((alt_size == QSPI_CFG_ALT_SIZE_NONE) || (alt_size == QSPI_CFG_ALT_SIZE_8) || (alt_size == QSPI_CFG_ALT_SIZE_16) || (alt_size == QSPI_CFG_ALT_SIZE_24) || (alt_size == QSPI_CFG_ALT_SIZE_32))
namespace mbed {
@@ -30,7 +30,6 @@ SingletonPtr QSPI::_mutex;
QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) :
_qspi() {
- // No lock needed in the constructor
_qspi_io0 = io0;
_qspi_io1 = io1;
_qspi_io2 = io2;
@@ -48,127 +47,40 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_hz = ONE_MHZ;
}
-qspi_return_status_t QSPI::configure_format(qspi_config_bus_width_t inst_width, qspi_config_bus_width_t address_width, qspi_config_address_size_t address_size, qspi_config_bus_width_t alt_width, qspi_config_alt_size_t alt_size, qspi_config_bus_width_t data_width, int dummy_cycles, int mode ) {
+qspi_status_t QSPI::configure_format(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, int mode ) {
if(!IS_BUS_WIDTH_VALID(inst_width))
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
if(!IS_BUS_WIDTH_VALID(address_width))
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
if(!IS_SIZE_VALID(address_size))
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
if(!IS_BUS_WIDTH_VALID(alt_width))
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
if(!IS_ALT_SIZE_VALID(alt_size))
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
if(!IS_BUS_WIDTH_VALID(data_width))
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
if(dummy_cycles < 0)
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
if(mode != 0 && mode != 1)
- return QSPI_INVALID_PARAMETER;
+ return QSPI_STATUS_INVALID_PARAMETER;
lock();
- switch(inst_width) {
- case QSPI_BUS_SINGLE:
- _inst_width = QSPI_CFG_BUS_SINGLE;
- break;
- case QSPI_BUS_DUAL:
- _inst_width = QSPI_CFG_BUS_DUAL;
- break;
- case QSPI_BUS_QUAD:
- _inst_width = QSPI_CFG_BUS_QUAD;
- break;
- default:
- _inst_width = QSPI_CFG_BUS_SINGLE;
- }
-
- switch(address_width) {
- case QSPI_BUS_SINGLE:
- _address_width = QSPI_CFG_BUS_SINGLE;
- break;
- case QSPI_BUS_DUAL:
- _address_width = QSPI_CFG_BUS_DUAL;
- break;
- case QSPI_BUS_QUAD:
- _address_width = QSPI_CFG_BUS_QUAD;
- break;
- default:
- _address_width = QSPI_CFG_BUS_SINGLE;
- }
-
- switch(address_size) {
- case QSPI_ADDR_SIZE_8:
- _address_size = QSPI_CFG_ADDR_SIZE_8;
- break;
- case QSPI_ADDR_SIZE_16:
- _address_size = QSPI_CFG_ADDR_SIZE_16;
- break;
- case QSPI_ADDR_SIZE_24:
- _address_size = QSPI_CFG_ADDR_SIZE_24;
- break;
- case QSPI_ADDR_SIZE_32:
- _address_size = QSPI_CFG_ADDR_SIZE_32;
- break;
- default:
- _address_size = QSPI_CFG_ADDR_SIZE_8;
- }
-
- switch(alt_width) {
- case QSPI_BUS_SINGLE:
- _alt_width = QSPI_CFG_BUS_SINGLE;
- break;
- case QSPI_BUS_DUAL:
- _alt_width = QSPI_CFG_BUS_DUAL;
- break;
- case QSPI_BUS_QUAD:
- _alt_width = QSPI_CFG_BUS_QUAD;
- break;
- default:
- _alt_width = QSPI_CFG_BUS_SINGLE;
- }
-
- switch(alt_size) {
- case QSPI_ALT_SIZE_NONE:
- _alt_size = QSPI_CFG_ALT_SIZE_NONE;
- break;
- case QSPI_ALT_SIZE_8:
- _alt_size = QSPI_CFG_ALT_SIZE_8;
- break;
- case QSPI_ALT_SIZE_16:
- _alt_size = QSPI_CFG_ALT_SIZE_16;
- break;
- case QSPI_ALT_SIZE_24:
- _alt_size = QSPI_CFG_ALT_SIZE_24;
- break;
- case QSPI_ALT_SIZE_32:
- _alt_size = QSPI_CFG_ALT_SIZE_32;
- break;
- default:
- _alt_size = QSPI_CFG_ALT_SIZE_NONE;
- }
-
- switch(data_width) {
- case QSPI_BUS_SINGLE:
- _data_width = QSPI_CFG_BUS_SINGLE;
- break;
- case QSPI_BUS_DUAL:
- _data_width = QSPI_CFG_BUS_DUAL;
- break;
- case QSPI_BUS_QUAD:
- _data_width = QSPI_CFG_BUS_QUAD;
- break;
- default:
- _data_width = QSPI_CFG_BUS_SINGLE;
- }
-
+ _inst_width = inst_width;
+ _address_width = address_width;
+ _address_size = address_size;
+ _alt_width = alt_width;
+ _alt_size = alt_size;
+ _data_width = data_width;
_num_dummy_cycles = dummy_cycles;
_mode = mode;
unlock();
- return QSPI_SUCCESS;
+ return QSPI_STATUS_OK;
}
-qspi_return_status_t QSPI::set_frequency(int hz) {
- qspi_return_status_t ret_status = QSPI_SUCCESS;
+qspi_status_t QSPI::set_frequency(int hz) {
+ qspi_status_t ret_status = QSPI_STATUS_OK;
lock();
_hz = hz;
@@ -176,7 +88,7 @@ qspi_return_status_t QSPI::set_frequency(int hz) {
//Otherwise we may have to change mode as well, so call _acquire
if (_owner == this) {
if(QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) {
- ret_status = QSPI_ERROR;
+ ret_status = QSPI_STATUS_ERROR;
}
} else {
_acquire();
@@ -186,16 +98,16 @@ qspi_return_status_t QSPI::set_frequency(int hz) {
return ret_status;
}
-qspi_return_status_t QSPI::initialize() {
+qspi_status_t QSPI::initialize() {
lock();
qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
unlock();
- return ( ret == QSPI_STATUS_OK )? QSPI_SUCCESS : QSPI_ERROR;
+ return ( ret == QSPI_STATUS_OK )? QSPI_STATUS_OK : QSPI_STATUS_ERROR;
}
-qspi_return_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
- qspi_return_status_t ret_status = QSPI_ERROR;
+qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
if( (rx_length != NULL) && (rx_buffer != NULL) ) {
if(*rx_length != 0) {
@@ -203,20 +115,20 @@ qspi_return_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *r
if( true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
- ret_status = QSPI_SUCCESS;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
return ret_status;
}
-qspi_return_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) {
- qspi_return_status_t ret_status = QSPI_ERROR;
+qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) {
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
if(*tx_length != 0) {
@@ -224,20 +136,20 @@ qspi_return_status_t QSPI::write(unsigned int address, const char *tx_buffer, si
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
- ret_status = QSPI_SUCCESS;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
return ret_status;
}
-qspi_return_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length) {
- qspi_return_status_t ret_status = QSPI_ERROR;
+qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length) {
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
if( (rx_length != NULL) && (rx_buffer != NULL) ) {
if(*rx_length != 0) {
@@ -245,20 +157,20 @@ qspi_return_status_t QSPI::read(unsigned int instruction, unsigned int address,
if( true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
- ret_status = QSPI_SUCCESS;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
return ret_status;
}
-qspi_return_status_t QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length) {
- qspi_return_status_t ret_status = QSPI_ERROR;
+qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length) {
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
if(*tx_length != 0) {
@@ -266,27 +178,27 @@ qspi_return_status_t QSPI::write(unsigned int instruction, unsigned int address,
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
- ret_status = QSPI_SUCCESS;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
return ret_status;
}
-qspi_return_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) {
- qspi_return_status_t ret_status = QSPI_ERROR;
+qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) {
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
lock();
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
//We got error status, return 0
- ret_status = QSPI_SUCCESS;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index f71bd106add..7bc8f5744c8 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -29,43 +29,6 @@
namespace mbed {
-// Config/Mode Defines
-/** QSPI Bus width Enum
- */
-typedef enum qspi_config_bus_width {
- QSPI_BUS_SINGLE,
- QSPI_BUS_DUAL,
- QSPI_BUS_QUAD,
-} qspi_config_bus_width_t;
-
-/** Address size Enum
- */
-typedef enum qspi_config_address_size {
- QSPI_ADDR_SIZE_NONE,
- QSPI_ADDR_SIZE_8,
- QSPI_ADDR_SIZE_16,
- QSPI_ADDR_SIZE_24,
- QSPI_ADDR_SIZE_32,
-} qspi_config_address_size_t;
-
-/** Alternative size Enum
- */
-typedef enum qspi_config_alt_size {
- QSPI_ALT_SIZE_NONE,
- QSPI_ALT_SIZE_8,
- QSPI_ALT_SIZE_16,
- QSPI_ALT_SIZE_24,
- QSPI_ALT_SIZE_32,
-} qspi_config_alt_size_t;
-
-/** QSPI Driver Return Status Enum
- */
-typedef enum qspi_return_status {
- QSPI_ERROR = -1, /**< Generic error >*/
- QSPI_INVALID_PARAMETER = -2, /**< The parameter is invalid >*/
- QSPI_SUCCESS = 0, /**< Function executed sucessfully >*/
-} qspi_return_status_t;
-
/** \addtogroup drivers */
/** A QSPI Driver, used for communicating with QSPI slave devices
@@ -128,12 +91,12 @@ class QSPI : private NonCopyable {
* @param mode Mode specifies the SPI mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
*
*/
- qspi_return_status_t configure_format(qspi_config_bus_width_t inst_width,
- qspi_config_bus_width_t address_width,
- qspi_config_address_size_t address_size,
- qspi_config_bus_width_t alt_width,
- qspi_config_alt_size_t alt_size,
- qspi_config_bus_width_t data_width,
+ qspi_status_t configure_format(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,
int mode);
@@ -141,16 +104,16 @@ class QSPI : private NonCopyable {
*
* This function must be called before doing any operation on the QSPI bus to initialize the interface
*/
- qspi_return_status_t initialize();
+ qspi_status_t initialize();
/** Set the qspi bus clock frequency
*
* @param hz SCLK frequency in hz (default = 1MHz)
* @returns
- * Returns QSPI_SUCCESS on successful, fails if the interface is already init-ed
+ * Returns QSPI_STATUS_SUCCESS on successful, fails if the interface is already init-ed
*/
- qspi_return_status_t set_frequency(int hz = ONE_MHZ);
+ qspi_status_t set_frequency(int hz = ONE_MHZ);
/** Read from QSPI peripheral with the preset read_instruction and alt_value
*
@@ -159,9 +122,9 @@ class QSPI : private NonCopyable {
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
- * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
+ * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_return_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length);
+ qspi_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length);
/** Write to QSPI peripheral with the preset write_instruction and alt_value
*
@@ -170,9 +133,9 @@ class QSPI : private NonCopyable {
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
*
* @returns
- * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
+ * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_return_status_t write(unsigned int address, const char *tx_buffer, size_t *tx_length);
+ qspi_status_t write(unsigned int address, const char *tx_buffer, size_t *tx_length);
/** Read from QSPI peripheral using custom read instruction, alt values
*
@@ -183,9 +146,9 @@ class QSPI : private NonCopyable {
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
- * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
+ * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_return_status_t read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length);
+ qspi_status_t read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length);
/** Write to QSPI peripheral using custom write instruction, alt values
*
@@ -196,9 +159,9 @@ class QSPI : private NonCopyable {
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
*
* @returns
- * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
+ * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_return_status_t write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length);
+ qspi_status_t write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length);
/** Perform a transaction to write to an address(a control register) and get the status results
*
@@ -209,9 +172,9 @@ class QSPI : private NonCopyable {
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
- * Returns QSPI_SUCCESS on successful reads and QSPI_ERROR on failed reads.
+ * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_return_status_t command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
+ qspi_status_t command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
/** Acquire exclusive access to this SPI bus
*/
From a16d65d1680abae2055ddf87145517fffdeaec4d Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Fri, 1 Dec 2017 14:32:42 -0600
Subject: [PATCH 14/61] Remove explicit initialize API and coding style fixes
---
drivers/QSPI.cpp | 238 ++++++++++++++++++++++++++---------------------
drivers/QSPI.h | 2 +
2 files changed, 134 insertions(+), 106 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 451180f8cf2..1f4b37f2ee9 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -19,17 +19,13 @@
#if DEVICE_QSPI
-#define IS_BUS_WIDTH_VALID(width) ((width == QSPI_CFG_BUS_SINGLE) || (width == QSPI_CFG_BUS_DUAL) || (width == QSPI_CFG_BUS_QUAD))
-#define IS_SIZE_VALID(size) ((size == QSPI_CFG_ADDR_SIZE_NONE) || (size == QSPI_CFG_ADDR_SIZE_8) || (size == QSPI_CFG_ADDR_SIZE_16) || (size == QSPI_CFG_ADDR_SIZE_24) || (size == QSPI_CFG_ADDR_SIZE_32))
-#define IS_ALT_SIZE_VALID(alt_size) ((alt_size == QSPI_CFG_ALT_SIZE_NONE) || (alt_size == QSPI_CFG_ALT_SIZE_8) || (alt_size == QSPI_CFG_ALT_SIZE_16) || (alt_size == QSPI_CFG_ALT_SIZE_24) || (alt_size == QSPI_CFG_ALT_SIZE_32))
-
namespace mbed {
QSPI* QSPI::_owner = NULL;
SingletonPtr QSPI::_mutex;
-QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) :
- _qspi() {
+QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) : _qspi()
+{
_qspi_io0 = io0;
_qspi_io1 = io1;
_qspi_io2 = io2;
@@ -44,22 +40,18 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_data_width = QSPI_CFG_BUS_SINGLE;
_num_dummy_cycles = 0;
_mode = 0;
- _hz = ONE_MHZ;
+ _hz = ONE_MHZ;
+ _initialized = false;
+
+ //Go ahead init the device here with the default config
+ _initialize();
+
}
-qspi_status_t QSPI::configure_format(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, int mode ) {
- if(!IS_BUS_WIDTH_VALID(inst_width))
- return QSPI_STATUS_INVALID_PARAMETER;
- if(!IS_BUS_WIDTH_VALID(address_width))
- return QSPI_STATUS_INVALID_PARAMETER;
- if(!IS_SIZE_VALID(address_size))
- return QSPI_STATUS_INVALID_PARAMETER;
- if(!IS_BUS_WIDTH_VALID(alt_width))
- return QSPI_STATUS_INVALID_PARAMETER;
- if(!IS_ALT_SIZE_VALID(alt_size))
- return QSPI_STATUS_INVALID_PARAMETER;
- if(!IS_BUS_WIDTH_VALID(data_width))
- return QSPI_STATUS_INVALID_PARAMETER;
+qspi_status_t QSPI::configure_format(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, int mode )
+{
+ qspi_status_t ret_status = QSPI_STATUS_OK;
+
if(dummy_cycles < 0)
return QSPI_STATUS_INVALID_PARAMETER;
if(mode != 0 && mode != 1)
@@ -74,161 +66,195 @@ qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width
_data_width = data_width;
_num_dummy_cycles = dummy_cycles;
_mode = mode;
+
+ //Re-init the device, as the mode might have changed
+ if( !_initialize() ) {
+ ret_status = QSPI_STATUS_ERROR;
+ }
unlock();
- return QSPI_STATUS_OK;
+ return ret_status;
}
-qspi_status_t QSPI::set_frequency(int hz) {
+qspi_status_t QSPI::set_frequency(int hz)
+{
qspi_status_t ret_status = QSPI_STATUS_OK;
- lock();
- _hz = hz;
- //If the same owner, just change freq.
- //Otherwise we may have to change mode as well, so call _acquire
- if (_owner == this) {
- if(QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) {
- ret_status = QSPI_STATUS_ERROR;
+ if(_initialized) {
+ lock();
+ _hz = hz;
+ //If the same owner, just change freq.
+ //Otherwise we may have to change mode as well, so call _acquire
+ if (_owner == this) {
+ if(QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) {
+ ret_status = QSPI_STATUS_ERROR;
+ }
+ } else {
+ _acquire();
}
+ unlock();
} else {
- _acquire();
+ ret_status = QSPI_STATUS_ERROR;
}
- unlock();
return ret_status;
}
-qspi_status_t QSPI::initialize() {
- lock();
- qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
- unlock();
-
- return ( ret == QSPI_STATUS_OK )? QSPI_STATUS_OK : QSPI_STATUS_ERROR;
-}
-
-qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) {
+qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length)
+{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if( (rx_length != NULL) && (rx_buffer != NULL) ) {
- if(*rx_length != 0) {
- lock();
- if( true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
- if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
- ret_status = QSPI_STATUS_OK;
+ if(_initialized) {
+ if( (rx_length != NULL) && (rx_buffer != NULL) ) {
+ if(*rx_length != 0) {
+ lock();
+ if( true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
+ if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
+ ret_status = QSPI_STATUS_OK;
+ }
}
+ unlock();
}
- unlock();
+ } else {
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
- }
+ } //if(_initialized)
return ret_status;
}
-qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) {
+qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length)
+{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if( (tx_length != NULL) && (tx_buffer != NULL) ) {
- if(*tx_length != 0) {
- lock();
- if(true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
- if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
- ret_status = QSPI_STATUS_OK;
+ if(_initialized)
+ {
+ if( (tx_length != NULL) && (tx_buffer != NULL) ) {
+ if(*tx_length != 0) {
+ lock();
+ if(true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
+ if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
+ ret_status = QSPI_STATUS_OK;
+ }
}
+ unlock();
}
- unlock();
+ } else {
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
- }
+ } //if(_initialized)
return ret_status;
}
-qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length) {
+qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length)
+{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if( (rx_length != NULL) && (rx_buffer != NULL) ) {
- if(*rx_length != 0) {
- lock();
- if( true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
- if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
- ret_status = QSPI_STATUS_OK;
+ if(_initialized) {
+ if( (rx_length != NULL) && (rx_buffer != NULL) ) {
+ if(*rx_length != 0) {
+ lock();
+ if( true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
+ if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
+ ret_status = QSPI_STATUS_OK;
+ }
}
+ unlock();
}
- unlock();
+ } else {
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
- }
+ } //if(_initialized)
return ret_status;
}
-qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length) {
+qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length)
+{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if( (tx_length != NULL) && (tx_buffer != NULL) ) {
- if(*tx_length != 0) {
- lock();
- if(true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
- if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
- ret_status = QSPI_STATUS_OK;
+ if(_initialized)
+ {
+ if( (tx_length != NULL) && (tx_buffer != NULL) ) {
+ if(*tx_length != 0) {
+ lock();
+ if(true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
+ if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
+ ret_status = QSPI_STATUS_OK;
+ }
}
+ unlock();
}
- unlock();
+ } else {
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
- }
+ } //if(_initialized)
return ret_status;
}
-qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) {
+qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
+{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- lock();
- if(true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
- if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
- //We got error status, return 0
- ret_status = QSPI_STATUS_OK;
- }
- }
- unlock();
+ if(_initialized)
+ {
+ lock();
+ if(true == _acquire()) {
+ qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
+ if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
+ //We got error status, return 0
+ ret_status = QSPI_STATUS_OK;
+ }
+ }
+ unlock();
+ } //if(_initialized)
return ret_status;
}
-void QSPI::lock() {
+void QSPI::lock()
+{
_mutex->lock();
}
-void QSPI::unlock() {
+void QSPI::unlock()
+{
_mutex->unlock();
}
-// Note: Private function with no locking
-bool QSPI::_acquire() {
- qspi_status_t ret = QSPI_STATUS_OK;
+// Note: Private helper function to initialize qspi HAL
+bool QSPI::_initialize()
+{
+ qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
+ if(QSPI_STATUS_OK == ret) {
+ _initialized = true;
+ } else {
+ _initialized = false;
+ }
+ return _initialized;
+}
+
+// Note: Private function with no locking
+bool QSPI::_acquire()
+{
if (_owner != this) {
//This will set freq as well
- ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
+ _initialize();
_owner = this;
}
- return ( ret == QSPI_STATUS_OK )? true:false;
+ return _initialized;
}
-qspi_command_t *QSPI::_build_qspi_command(int instruction, int address, int alt) {
-
+qspi_command_t *QSPI::_build_qspi_command(int instruction, int address, int alt)
+{
memset( &_qspi_command, 0, sizeof(qspi_command_t) );
//Set up instruction phase parameters
_qspi_command.instruction.bus_width = _inst_width;
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 7bc8f5744c8..4eb838a3903 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -204,6 +204,7 @@ class QSPI : private NonCopyable {
int _num_dummy_cycles; //Number of dummy cycles to be used
int _hz; //Bus Frequency
int _mode; //SPI mode
+ bool _initialized;
PinName _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs; //IO lines, clock and chip select
private:
@@ -211,6 +212,7 @@ class QSPI : private NonCopyable {
* Implemented in order to avoid duplicate locking and boost performance
*/
bool _acquire(void);
+ bool _initialize();
/*
* This function builds the qspi command struct to be send to Hal
From 7dbcc193a435b63d861c916b57d030b6ad308946 Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Fri, 1 Dec 2017 15:20:45 -0600
Subject: [PATCH 15/61] Fix bracket placements
---
drivers/QSPI.cpp | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 1f4b37f2ee9..816861ceac7 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -128,8 +128,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized)
- {
+ if(_initialized) {
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
if(*tx_length != 0) {
lock();
@@ -177,8 +176,7 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsign
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized)
- {
+ if(_initialized) {
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
if(*tx_length != 0) {
lock();
@@ -202,8 +200,7 @@ qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_bu
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized)
- {
+ if(_initialized) {
lock();
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
From ea85bba7aa6fce60868ab1e6cf6ffbb0fb87564f Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Mon, 4 Dec 2017 13:05:54 -0600
Subject: [PATCH 16/61] Remove changes to Nordic SDK and modify HAL to track
qspi init
---
.../drivers_nrf/qspi/nrf_drv_qspi.c | 4 +-
targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c | 44 +++++++++++++------
2 files changed, 32 insertions(+), 16 deletions(-)
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c
index 6e8a6aae99d..83287313a54 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c
@@ -122,10 +122,10 @@ ret_code_t nrf_drv_qspi_init(nrf_drv_qspi_config_t const * p_config,
nrf_drv_qspi_handler_t handler,
void * p_context)
{
- /*if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
+ if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
{
return NRF_ERROR_INVALID_STATE;
- }*/
+ }
if (!qspi_pins_configure(&p_config->pins))
{
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
index 63f07e109b9..849970a0936 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
@@ -58,6 +58,9 @@ TODO
static nrf_drv_qspi_config_t config;
+// Private helper function to track initialization
+static ret_code_t _qspi_drv_init(void);
+
qspi_status_t qspi_prepare_command(qspi_t *obj, const qspi_command_t *command, bool write)
{
//Use custom command if provided by the caller
@@ -136,7 +139,7 @@ qspi_status_t qspi_prepare_command(qspi_t *obj, const qspi_command_t *command, b
//Configure QSPI with new command format
if(ret == QSPI_STATUS_OK) {
- ret_code_t ret_status = nrf_drv_qspi_init(&config, NULL , NULL);
+ ret_code_t ret_status = _qspi_drv_init();
if (ret_status != NRF_SUCCESS ) {
if (ret_status == NRF_ERROR_INVALID_PARAM) {
return QSPI_STATUS_INVALID_PARAMETER;
@@ -171,7 +174,8 @@ qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinN
config.phy_if.dpmen = false;
config.phy_if.spi_mode = mode == 0 ? NRF_QSPI_MODE_0 : NRF_QSPI_MODE_1;
- ret_code_t ret = nrf_drv_qspi_init(&config, NULL , NULL);
+ //Use _qspi_drv_init private function to initialize
+ ret_code_t ret = _qspi_drv_init();
if (ret == NRF_SUCCESS ) {
return QSPI_STATUS_OK;
} else if (ret == NRF_ERROR_INVALID_PARAM) {
@@ -191,8 +195,9 @@ qspi_status_t qspi_free(qspi_t *obj)
qspi_status_t qspi_frequency(qspi_t *obj, int hz)
{
config.phy_if.sck_freq = (nrf_qspi_frequency_t)MBED_HAL_QSPI_HZ_TO_CONFIG(hz);
+
// use sync version, no handler
- ret_code_t ret = nrf_drv_qspi_init(&config, NULL , NULL);
+ ret_code_t ret = _qspi_drv_init();
if (ret == NRF_SUCCESS ) {
return QSPI_STATUS_OK;
} else if (ret == NRF_ERROR_INVALID_PARAM) {
@@ -247,30 +252,24 @@ qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command,
qspi_cinstr_config.wipwait = false;
qspi_cinstr_config.wren = false;
- if (data_size < 9)
- {
+ if (data_size < 9) {
qspi_cinstr_config.length = (nrf_qspi_cinstr_len_t)(NRF_QSPI_CINSTR_LEN_1B + data_size);
- }
- else
- {
+ } else {
return QSPI_STATUS_ERROR;
}
// preparing data to send
- for (i = 0; i < tx_size; ++i)
- {
+ for (i = 0; i < tx_size; ++i) {
data[i] = ((uint8_t *)tx_data)[i];
}
ret_code = nrf_drv_qspi_cinstr_xfer(&qspi_cinstr_config, data, data);
- if (ret_code != NRF_SUCCESS)
- {
+ if (ret_code != NRF_SUCCESS) {
return QSPI_STATUS_ERROR;
}
// preparing received data
- for (i = 0; i < rx_size; ++i)
- {
+ for (i = 0; i < rx_size; ++i) {
// Data is sending as a normal SPI transmission so there is one buffer to send and receive data.
((uint8_t *)rx_data)[i] = data[i];
}
@@ -278,6 +277,23 @@ qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command,
return QSPI_STATUS_OK;
}
+// Private helper function to track initialization
+static ret_code_t _qspi_drv_init(void)
+{
+ static bool _initialized = false;
+ ret_code_t ret = NRF_ERROR_INVALID_STATE;
+
+ if(_initialized) {
+ //NRF implementation prevents calling init again. But we need to call init again to program the new command settings in the IFCONFIG registers.
+ //So, we have to uninit qspi first and call init again.
+ nrf_drv_qspi_uninit();
+ }
+ ret = nrf_drv_qspi_init(&config, NULL , NULL);
+ if( ret == NRF_SUCCESS )
+ _initialized = true;
+ return ret;
+}
+
#endif
From 55b13ca298e4947cabf19d349d79fa8e8c7b176c Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Mon, 4 Dec 2017 13:06:39 -0600
Subject: [PATCH 17/61] Minor optimizations and code style fixes
---
drivers/QSPI.cpp | 14 +++++---------
drivers/QSPI.h | 2 +-
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 816861ceac7..1d31d4365da 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -52,8 +52,6 @@ qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width
{
qspi_status_t ret_status = QSPI_STATUS_OK;
- if(dummy_cycles < 0)
- return QSPI_STATUS_INVALID_PARAMETER;
if(mode != 0 && mode != 1)
return QSPI_STATUS_INVALID_PARAMETER;
@@ -119,7 +117,7 @@ qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_lengt
} else {
ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } //if(_initialized)
+ }
return ret_status;
}
@@ -143,7 +141,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
} else {
ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } //if(_initialized)
+ }
return ret_status;
}
@@ -167,7 +165,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigne
} else {
ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } //if(_initialized)
+ }
return ret_status;
}
@@ -191,7 +189,7 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsign
} else {
ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
- } //if(_initialized)
+ }
return ret_status;
}
@@ -205,12 +203,11 @@ qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_bu
if(true == _acquire()) {
qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
- //We got error status, return 0
ret_status = QSPI_STATUS_OK;
}
}
unlock();
- } //if(_initialized)
+ }
return ret_status;
}
@@ -280,7 +277,6 @@ qspi_command_t *QSPI::_build_qspi_command(int instruction, int address, int alt)
_qspi_command.alt.value = 0;
}
- //Set up dummy cycle count
_qspi_command.dummy_count = _num_dummy_cycles;
//Set up bus width for data phase
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 4eb838a3903..e4b1b182560 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -201,7 +201,7 @@ class QSPI : private NonCopyable {
qspi_alt_size_t _alt_size;
qspi_bus_width_t _data_width; //Bus width for Data phase
qspi_command_t _qspi_command; //QSPI Hal command struct
- int _num_dummy_cycles; //Number of dummy cycles to be used
+ unsigned int _num_dummy_cycles; //Number of dummy cycles to be used
int _hz; //Bus Frequency
int _mode; //SPI mode
bool _initialized;
From fd8c3f706221ff7c6d1400cb0b333d4522d67254 Mon Sep 17 00:00:00 2001
From: Senthil Ramakrishnan
Date: Mon, 4 Dec 2017 14:12:01 -0600
Subject: [PATCH 18/61] Review fixes
---
drivers/QSPI.cpp | 24 +++++++++++-------------
drivers/QSPI.h | 2 +-
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 1d31d4365da..3d1eee970aa 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -107,8 +107,8 @@ qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_lengt
if(*rx_length != 0) {
lock();
if( true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
- if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
+ _build_qspi_command(-1, address, -1);
+ if(QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -131,8 +131,8 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
if(*tx_length != 0) {
lock();
if(true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(-1, address, -1);
- if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
+ _build_qspi_command(-1, address, -1);
+ if(QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -155,8 +155,8 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigne
if(*rx_length != 0) {
lock();
if( true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
- if(QSPI_STATUS_OK == qspi_read(&_qspi, qspi_cmd, rx_buffer, rx_length)) {
+ _build_qspi_command(instruction, address, alt);
+ if(QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -179,8 +179,8 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsign
if(*tx_length != 0) {
lock();
if(true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(instruction, address, alt);
- if(QSPI_STATUS_OK == qspi_write(&_qspi, qspi_cmd, tx_buffer, tx_length)) {
+ _build_qspi_command(instruction, address, alt);
+ if(QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -201,8 +201,8 @@ qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_bu
if(_initialized) {
lock();
if(true == _acquire()) {
- qspi_command_t *qspi_cmd = _build_qspi_command(instruction, -1, -1); //We just need the command
- if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, qspi_cmd, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
+ _build_qspi_command(instruction, -1, -1); //We just need the command
+ if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -247,7 +247,7 @@ bool QSPI::_acquire()
return _initialized;
}
-qspi_command_t *QSPI::_build_qspi_command(int instruction, int address, int alt)
+void QSPI::_build_qspi_command(int instruction, int address, int alt)
{
memset( &_qspi_command, 0, sizeof(qspi_command_t) );
//Set up instruction phase parameters
@@ -281,8 +281,6 @@ qspi_command_t *QSPI::_build_qspi_command(int instruction, int address, int alt)
//Set up bus width for data phase
_qspi_command.data.bus_width = _data_width;
-
- return &_qspi_command;
}
} // namespace mbed
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index e4b1b182560..5962f2ed1e3 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -217,7 +217,7 @@ class QSPI : private NonCopyable {
/*
* This function builds the qspi command struct to be send to Hal
*/
- inline qspi_command_t *_build_qspi_command(int instruction, int address, int alt);
+ inline void _build_qspi_command(int instruction, int address, int alt);
};
} // namespace mbed
From 75a4479b7730c6149c6571080e13ccf63a2716a3 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Dec 2017 14:17:29 +0000
Subject: [PATCH 19/61] QSPI: fix address size for build qspi command
if address is skipped, used size NONE
---
drivers/QSPI.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 3d1eee970aa..df4bbca2a5d 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -264,7 +264,7 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
if(address != -1) {
_qspi_command.address.value = address;
} else {
- _qspi_command.address.value = 0;
+ _qspi_command.address.size = QSPI_CFG_ADDR_SIZE_NONE;
}
//Set up alt phase parameters
From 35149aff1084c10e1a987fd53c45e693667fdc40 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Dec 2017 14:18:12 +0000
Subject: [PATCH 20/61] QSPI: remove initialize method
Not used anymore, not defined. ctor default initializes the object
---
drivers/QSPI.h | 7 -------
1 file changed, 7 deletions(-)
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 5962f2ed1e3..182ec45f0e9 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -100,13 +100,6 @@ class QSPI : private NonCopyable {
int dummy_cycles,
int mode);
- /** Initialize QSPI interface
- *
- * This function must be called before doing any operation on the QSPI bus to initialize the interface
- */
- qspi_status_t initialize();
-
-
/** Set the qspi bus clock frequency
*
* @param hz SCLK frequency in hz (default = 1MHz)
From 395119030e0be7f31a9ad9c6e0855f4ed855f960 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Dec 2017 14:21:22 +0000
Subject: [PATCH 21/61] QSPI: remove spaces on empty lines
---
drivers/QSPI.cpp | 86 +++++++++++++++++++++++-------------------------
drivers/QSPI.h | 18 +++++-----
2 files changed, 51 insertions(+), 53 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index df4bbca2a5d..3c5adcc587c 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -22,7 +22,7 @@
namespace mbed {
QSPI* QSPI::_owner = NULL;
-SingletonPtr QSPI::_mutex;
+SingletonPtr QSPI::_mutex;
QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) : _qspi()
{
@@ -42,42 +42,40 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_mode = 0;
_hz = ONE_MHZ;
_initialized = false;
-
+
//Go ahead init the device here with the default config
_initialize();
-
}
-
+
qspi_status_t QSPI::configure_format(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, int mode )
-{
- qspi_status_t ret_status = QSPI_STATUS_OK;
-
+{ qspi_status_t ret_status = QSPI_STATUS_OK;
+
if(mode != 0 && mode != 1)
- return QSPI_STATUS_INVALID_PARAMETER;
-
+ return QSPI_STATUS_INVALID_PARAMETER;
+
lock();
_inst_width = inst_width;
_address_width = address_width;
_address_size = address_size;
_alt_width = alt_width;
_alt_size = alt_size;
- _data_width = data_width;
+ _data_width = data_width;
_num_dummy_cycles = dummy_cycles;
_mode = mode;
-
+
//Re-init the device, as the mode might have changed
if( !_initialize() ) {
ret_status = QSPI_STATUS_ERROR;
}
unlock();
-
+
return ret_status;
}
qspi_status_t QSPI::set_frequency(int hz)
{
- qspi_status_t ret_status = QSPI_STATUS_OK;
-
+ qspi_status_t ret_status = QSPI_STATUS_OK;
+
if(_initialized) {
lock();
_hz = hz;
@@ -92,16 +90,16 @@ qspi_status_t QSPI::set_frequency(int hz)
}
unlock();
} else {
- ret_status = QSPI_STATUS_ERROR;
+ ret_status = QSPI_STATUS_ERROR;
}
-
+
return ret_status;
}
qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length)
{
- qspi_status_t ret_status = QSPI_STATUS_ERROR;
-
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
+
if(_initialized) {
if( (rx_length != NULL) && (rx_buffer != NULL) ) {
if(*rx_length != 0) {
@@ -109,22 +107,22 @@ qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_lengt
if( true == _acquire()) {
_build_qspi_command(-1, address, -1);
if(QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
- ret_status = QSPI_STATUS_OK;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
}
-
+
return ret_status;
}
qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length)
{
- qspi_status_t ret_status = QSPI_STATUS_ERROR;
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
if(_initialized) {
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
@@ -133,23 +131,23 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
if(true == _acquire()) {
_build_qspi_command(-1, address, -1);
if(QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
- ret_status = QSPI_STATUS_OK;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
}
-
+
return ret_status;
}
qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length)
{
- qspi_status_t ret_status = QSPI_STATUS_ERROR;
-
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
+
if(_initialized) {
if( (rx_length != NULL) && (rx_buffer != NULL) ) {
if(*rx_length != 0) {
@@ -157,13 +155,13 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigne
if( true == _acquire()) {
_build_qspi_command(instruction, address, alt);
if(QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
- ret_status = QSPI_STATUS_OK;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
}
@@ -172,7 +170,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigne
qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length)
{
- qspi_status_t ret_status = QSPI_STATUS_ERROR;
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
if(_initialized) {
if( (tx_length != NULL) && (tx_buffer != NULL) ) {
@@ -181,13 +179,13 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsign
if(true == _acquire()) {
_build_qspi_command(instruction, address, alt);
if(QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
- ret_status = QSPI_STATUS_OK;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
}
} else {
- ret_status = QSPI_STATUS_INVALID_PARAMETER;
+ ret_status = QSPI_STATUS_INVALID_PARAMETER;
}
}
@@ -196,14 +194,14 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsign
qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
{
- qspi_status_t ret_status = QSPI_STATUS_ERROR;
+ qspi_status_t ret_status = QSPI_STATUS_ERROR;
if(_initialized) {
lock();
if(true == _acquire()) {
_build_qspi_command(instruction, -1, -1); //We just need the command
if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
- ret_status = QSPI_STATUS_OK;
+ ret_status = QSPI_STATUS_OK;
}
}
unlock();
@@ -251,34 +249,34 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
{
memset( &_qspi_command, 0, sizeof(qspi_command_t) );
//Set up instruction phase parameters
- _qspi_command.instruction.bus_width = _inst_width;
+ _qspi_command.instruction.bus_width = _inst_width;
if(instruction != -1) {
- _qspi_command.instruction.value = instruction;
+ _qspi_command.instruction.value = instruction;
} else {
- _qspi_command.instruction.value = 0;
+ _qspi_command.instruction.value = 0;
}
-
+
//Set up address phase parameters
_qspi_command.address.bus_width = _address_width;
_qspi_command.address.size = _address_size;
if(address != -1) {
- _qspi_command.address.value = address;
+ _qspi_command.address.value = address;
} else {
_qspi_command.address.size = QSPI_CFG_ADDR_SIZE_NONE;
}
-
+
//Set up alt phase parameters
- _qspi_command.alt.bus_width = _alt_width;
+ _qspi_command.alt.bus_width = _alt_width;
_qspi_command.alt.size = _alt_size;
if(alt != -1) {
- _qspi_command.alt.value = alt;
+ _qspi_command.alt.value = alt;
} else {
//In the case alt phase is absent, set the alt size to be NONE
- _qspi_command.alt.value = 0;
+ _qspi_command.alt.value = 0;
}
_qspi_command.dummy_count = _num_dummy_cycles;
-
+
//Set up bus width for data phase
_qspi_command.data.bus_width = _data_width;
}
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 182ec45f0e9..ecc2cbb8e30 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -65,7 +65,7 @@ namespace mbed {
class QSPI : private NonCopyable {
public:
-
+
/** Create a QSPI master connected to the specified pins
*
* io0-io3 is used to specify the Pins used for Quad SPI mode
@@ -96,7 +96,7 @@ class QSPI : private NonCopyable {
qspi_address_size_t address_size,
qspi_bus_width_t alt_width,
qspi_alt_size_t alt_size,
- qspi_bus_width_t data_width,
+ qspi_bus_width_t data_width,
int dummy_cycles,
int mode);
@@ -117,8 +117,8 @@ class QSPI : private NonCopyable {
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length);
-
+ qspi_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length);
+
/** Write to QSPI peripheral with the preset write_instruction and alt_value
*
* @param address Address to be accessed in QSPI peripheral
@@ -129,7 +129,7 @@ class QSPI : private NonCopyable {
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
qspi_status_t write(unsigned int address, const char *tx_buffer, size_t *tx_length);
-
+
/** Read from QSPI peripheral using custom read instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase
@@ -142,7 +142,7 @@ class QSPI : private NonCopyable {
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
qspi_status_t read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length);
-
+
/** Write to QSPI peripheral using custom write instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase
@@ -155,7 +155,7 @@ class QSPI : private NonCopyable {
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
qspi_status_t write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length);
-
+
/** Perform a transaction to write to an address(a control register) and get the status results
*
* @param instruction Instruction value to be used in instruction phase
@@ -168,7 +168,7 @@ class QSPI : private NonCopyable {
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
qspi_status_t command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
-
+
/** Acquire exclusive access to this SPI bus
*/
virtual void lock(void);
@@ -199,7 +199,7 @@ class QSPI : private NonCopyable {
int _mode; //SPI mode
bool _initialized;
PinName _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs; //IO lines, clock and chip select
-
+
private:
/* Private acquire function without locking/unlocking
* Implemented in order to avoid duplicate locking and boost performance
From dafe6a38307bf839d1e7a843ffd5283f20f447c9 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Dec 2017 14:47:53 +0000
Subject: [PATCH 22/61] QSPI HAL: fix alternative comment
---
hal/qspi_api.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 8982aea5023..80c1ff0ceb4 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -83,7 +83,7 @@ typedef struct qspi_command {
struct {
qspi_bus_width_t bus_width; /**< Bus width for alternative >*/
qspi_alt_size_t size; /**< Alternative size >*/
- uint32_t value; /**< Alternative, 0 - disabled, non-zero defined value used >*/
+ uint32_t value; /**< Alternative value >*/
} alt;
uint8_t dummy_count; /**< Dummy cycles count >*/
struct {
From 0f87633dc1f208272c6fe4c160b3bf09f4fd6ee6 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Wed, 6 Dec 2017 13:12:59 +0000
Subject: [PATCH 23/61] QSPI: fix arguments for write/read when alt is defined
Should be: instr, alt, address or inst, addr or just addr
---
drivers/QSPI.cpp | 4 ++--
drivers/QSPI.h | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 3c5adcc587c..2f111e27ebc 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -144,7 +144,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
return ret_status;
}
-qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length)
+qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length)
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
@@ -168,7 +168,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int address, unsigne
return ret_status;
}
-qspi_status_t QSPI::write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length)
+qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length)
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index ecc2cbb8e30..33039475fbe 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -119,7 +119,7 @@ class QSPI : private NonCopyable {
*/
qspi_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length);
- /** Write to QSPI peripheral with the preset write_instruction and alt_value
+ /** Write to QSPI peripheral using custom write instruction
*
* @param address Address to be accessed in QSPI peripheral
* @param tx_buffer Buffer containing data to be sent to peripheral
@@ -133,28 +133,28 @@ class QSPI : private NonCopyable {
/** Read from QSPI peripheral using custom read instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase
- * @param address Address to be accessed in QSPI peripheral
* @param alt Alt value to be used in instruction phase
+ * @param address Address to be accessed in QSPI peripheral
* @param rx_buffer Buffer for data to be read from the peripheral
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t read(unsigned int instruction, unsigned int address, unsigned int alt, char *rx_buffer, size_t *rx_length);
+ qspi_status_t read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length);
/** Write to QSPI peripheral using custom write instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase
- * @param address Address to be accessed in QSPI peripheral
* @param alt Alt value to be used in instruction phase
+ * @param address Address to be accessed in QSPI peripheral
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
*
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t write(unsigned int instruction, unsigned int address, unsigned int alt, const char *tx_buffer, size_t *tx_length);
+ qspi_status_t write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length);
/** Perform a transaction to write to an address(a control register) and get the status results
*
From 2820ca452f93958f008b00561767abe1b117012d Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Wed, 6 Dec 2017 13:15:24 +0000
Subject: [PATCH 24/61] QSPI: fix driver style issues
---
drivers/QSPI.cpp | 67 ++++++++++++++++++++++++------------------------
1 file changed, 34 insertions(+), 33 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 2f111e27ebc..c30dea57abb 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -23,7 +23,7 @@ namespace mbed {
QSPI* QSPI::_owner = NULL;
SingletonPtr QSPI::_mutex;
-
+
QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) : _qspi()
{
_qspi_io0 = io0;
@@ -48,9 +48,10 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
}
qspi_status_t QSPI::configure_format(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, int mode )
-{ qspi_status_t ret_status = QSPI_STATUS_OK;
+{
+ qspi_status_t ret_status = QSPI_STATUS_OK;
- if(mode != 0 && mode != 1)
+ if (mode != 0 && mode != 1)
return QSPI_STATUS_INVALID_PARAMETER;
lock();
@@ -64,7 +65,7 @@ qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width
_mode = mode;
//Re-init the device, as the mode might have changed
- if( !_initialize() ) {
+ if ( !_initialize() ) {
ret_status = QSPI_STATUS_ERROR;
}
unlock();
@@ -76,13 +77,13 @@ qspi_status_t QSPI::set_frequency(int hz)
{
qspi_status_t ret_status = QSPI_STATUS_OK;
- if(_initialized) {
+ if (_initialized) {
lock();
_hz = hz;
//If the same owner, just change freq.
//Otherwise we may have to change mode as well, so call _acquire
if (_owner == this) {
- if(QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) {
+ if (QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) {
ret_status = QSPI_STATUS_ERROR;
}
} else {
@@ -100,13 +101,13 @@ qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_lengt
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized) {
- if( (rx_length != NULL) && (rx_buffer != NULL) ) {
- if(*rx_length != 0) {
+ if (_initialized) {
+ if ((rx_length != NULL) && (rx_buffer != NULL)) {
+ if (*rx_length != 0) {
lock();
- if( true == _acquire()) {
+ if (true == _acquire()) {
_build_qspi_command(-1, address, -1);
- if(QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
+ if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -124,13 +125,13 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized) {
- if( (tx_length != NULL) && (tx_buffer != NULL) ) {
- if(*tx_length != 0) {
+ if (_initialized) {
+ if ((tx_length != NULL) && (tx_buffer != NULL)) {
+ if (*tx_length != 0) {
lock();
- if(true == _acquire()) {
+ if (true == _acquire()) {
_build_qspi_command(-1, address, -1);
- if(QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
+ if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -148,13 +149,13 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned in
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized) {
- if( (rx_length != NULL) && (rx_buffer != NULL) ) {
- if(*rx_length != 0) {
+ if (_initialized) {
+ if ( (rx_length != NULL) && (rx_buffer != NULL) ) {
+ if (*rx_length != 0) {
lock();
- if( true == _acquire()) {
+ if ( true == _acquire()) {
_build_qspi_command(instruction, address, alt);
- if(QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
+ if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -172,13 +173,13 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned i
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized) {
- if( (tx_length != NULL) && (tx_buffer != NULL) ) {
- if(*tx_length != 0) {
+ if (_initialized) {
+ if ( (tx_length != NULL) && (tx_buffer != NULL) ) {
+ if (*tx_length != 0) {
lock();
- if(true == _acquire()) {
+ if (true == _acquire()) {
_build_qspi_command(instruction, address, alt);
- if(QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
+ if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -196,11 +197,11 @@ qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_bu
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
- if(_initialized) {
+ if (_initialized) {
lock();
- if(true == _acquire()) {
+ if (true == _acquire()) {
_build_qspi_command(instruction, -1, -1); //We just need the command
- if(QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
+ if (QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
}
@@ -224,7 +225,7 @@ void QSPI::unlock()
bool QSPI::_initialize()
{
qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
- if(QSPI_STATUS_OK == ret) {
+ if (QSPI_STATUS_OK == ret) {
_initialized = true;
} else {
_initialized = false;
@@ -250,7 +251,7 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
memset( &_qspi_command, 0, sizeof(qspi_command_t) );
//Set up instruction phase parameters
_qspi_command.instruction.bus_width = _inst_width;
- if(instruction != -1) {
+ if (instruction != -1) {
_qspi_command.instruction.value = instruction;
} else {
_qspi_command.instruction.value = 0;
@@ -259,7 +260,7 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
//Set up address phase parameters
_qspi_command.address.bus_width = _address_width;
_qspi_command.address.size = _address_size;
- if(address != -1) {
+ if (address != -1) {
_qspi_command.address.value = address;
} else {
_qspi_command.address.size = QSPI_CFG_ADDR_SIZE_NONE;
@@ -268,7 +269,7 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
//Set up alt phase parameters
_qspi_command.alt.bus_width = _alt_width;
_qspi_command.alt.size = _alt_size;
- if(alt != -1) {
+ if (alt != -1) {
_qspi_command.alt.value = alt;
} else {
//In the case alt phase is absent, set the alt size to be NONE
From ff9442c09639737f679780dc5d0dee74214c26f2 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Wed, 6 Dec 2017 13:16:09 +0000
Subject: [PATCH 25/61] QSPI: fix alt size NONE instead 0
---
drivers/QSPI.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index c30dea57abb..a4a11a1ec36 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -273,7 +273,7 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
_qspi_command.alt.value = alt;
} else {
//In the case alt phase is absent, set the alt size to be NONE
- _qspi_command.alt.value = 0;
+ _qspi_command.alt.size = QSPI_CFG_ALT_SIZE_NONE;
}
_qspi_command.dummy_count = _num_dummy_cycles;
From 50b70eb4abbd964833779854cb7bb68bfec6380b Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Thu, 23 Nov 2017 09:24:31 +0000
Subject: [PATCH 26/61] QSPI HAL: add disabled flag to format phase
If phase is being skipped, set disabled to true, otherwise false.
---
drivers/QSPI.cpp | 12 +++++++-----
drivers/QSPI.h | 4 ++--
hal/qspi_api.h | 6 ++++--
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index a4a11a1ec36..f2e19b8af8f 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -36,7 +36,7 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_address_width = QSPI_CFG_BUS_SINGLE;
_address_size = QSPI_CFG_ADDR_SIZE_24;
_alt_width = QSPI_CFG_BUS_SINGLE;
- _alt_size = QSPI_CFG_ALT_SIZE_NONE;
+ _alt_size = QSPI_CFG_ALT_SIZE_8;
_data_width = QSPI_CFG_BUS_SINGLE;
_num_dummy_cycles = 0;
_mode = 0;
@@ -253,8 +253,9 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
_qspi_command.instruction.bus_width = _inst_width;
if (instruction != -1) {
_qspi_command.instruction.value = instruction;
+ _qspi_command.instruction.disabled = false;
} else {
- _qspi_command.instruction.value = 0;
+ _qspi_command.instruction.disabled = true;
}
//Set up address phase parameters
@@ -262,8 +263,9 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
_qspi_command.address.size = _address_size;
if (address != -1) {
_qspi_command.address.value = address;
+ _qspi_command.address.disabled = false;
} else {
- _qspi_command.address.size = QSPI_CFG_ADDR_SIZE_NONE;
+ _qspi_command.address.disabled = true;
}
//Set up alt phase parameters
@@ -271,9 +273,9 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
_qspi_command.alt.size = _alt_size;
if (alt != -1) {
_qspi_command.alt.value = alt;
+ _qspi_command.alt.disabled = false;
} else {
- //In the case alt phase is absent, set the alt size to be NONE
- _qspi_command.alt.size = QSPI_CFG_ALT_SIZE_NONE;
+ _qspi_command.alt.disabled = true;
}
_qspi_command.dummy_count = _num_dummy_cycles;
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 33039475fbe..817dbfc421e 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -83,9 +83,9 @@ class QSPI : private NonCopyable {
*
* @param inst_width Bus width used by instruction phase(Valid values are 1,2,4)
* @param address_width Bus width used by address phase(Valid values are 1,2,4)
- * @param address_size Size in bits used by address phase(Valid values are NONE,8,16,24,32)
+ * @param address_size Size in bits used by address phase(Valid values are 8,16,24,32)
* @param alt_width Bus width used by alt phase(Valid values are 1,2,4)
- * @param alt_size Size in bits used by alt phase(Valid values are NONE,8,16,24,32)
+ * @param alt_size Size in bits used by alt phase(Valid values are 8,16,24,32)
* @param data_width Bus width used by data phase(Valid values are 1,2,4)
* @param dummy_cycles Number of dummy clock cycles to be used after alt phase
* @param mode Mode specifies the SPI mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 80c1ff0ceb4..525ff431229 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -20,6 +20,7 @@
#define MBED_QSPI_API_H
#include "device.h"
+#include
#if DEVICE_QSPI
@@ -49,7 +50,6 @@ typedef enum qspi_bus_width {
/** Address size
*/
typedef enum qspi_address_size {
- QSPI_CFG_ADDR_SIZE_NONE,
QSPI_CFG_ADDR_SIZE_8,
QSPI_CFG_ADDR_SIZE_16,
QSPI_CFG_ADDR_SIZE_24,
@@ -59,7 +59,6 @@ typedef enum qspi_address_size {
/** Alternative size
*/
typedef enum qspi_alt_size {
- QSPI_CFG_ALT_SIZE_NONE,
QSPI_CFG_ALT_SIZE_8,
QSPI_CFG_ALT_SIZE_16,
QSPI_CFG_ALT_SIZE_24,
@@ -74,16 +73,19 @@ typedef struct qspi_command {
struct {
qspi_bus_width_t bus_width; /**< Bus width for the instruction >*/
uint8_t value; /**< Instruction value >*/
+ bool disabled; /**< Instruction phase skipped if disabled is set to true >*/
} instruction;
struct {
qspi_bus_width_t bus_width; /**< Bus width for the address >*/
qspi_address_size_t size; /**< Address size >*/
uint32_t value; /**< Address value >*/
+ bool disabled; /**< Address phase skipped if disabled is set to true >*/
} address;
struct {
qspi_bus_width_t bus_width; /**< Bus width for alternative >*/
qspi_alt_size_t size; /**< Alternative size >*/
uint32_t value; /**< Alternative value >*/
+ bool disabled; /**< Alternative phase skipped if disabled is set to true >*/
} alt;
uint8_t dummy_count; /**< Dummy cycles count >*/
struct {
From 2fd5ec6ba5964eaab839ded7118fe5e912a5e5bd Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Wed, 15 Nov 2017 13:58:37 +0000
Subject: [PATCH 27/61] QSPI: add STM32 implementation
---
targets/TARGET_STM/PeripheralPins.h | 6 +
.../TARGET_DISCO_F469NI/PeripheralPins.c | 21 ++
.../TARGET_STM32F469xI/objects.h | 4 +
targets/TARGET_STM/qspi_api.c | 245 ++++++++++++++++++
targets/targets.json | 2 +-
5 files changed, 277 insertions(+), 1 deletion(-)
create mode 100644 targets/TARGET_STM/qspi_api.c
diff --git a/targets/TARGET_STM/PeripheralPins.h b/targets/TARGET_STM/PeripheralPins.h
index f96b84890ba..d1d5f2ea846 100644
--- a/targets/TARGET_STM/PeripheralPins.h
+++ b/targets/TARGET_STM/PeripheralPins.h
@@ -80,4 +80,10 @@ extern const PinMap PinMap_CAN_RD[];
extern const PinMap PinMap_CAN_TD[];
#endif
+#ifdef DEVICE_QSPI
+extern const PinMap PinMap_QSPI_DATA[];
+extern const PinMap PinMap_QSPI_SCLK[];
+extern const PinMap PinMap_QSPI_SSEL[];
+#endif
+
#endif
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
index 1f3690e4d0d..6b1c6bd1924 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
@@ -388,3 +388,24 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = {
{PH_13, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to D21
{NC, NC, 0}
};
+
+
+const PinMap PinMap_QSPI_DATA[] = {
+ {PF_6, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {PF_7, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {PF_8, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
+ {PF_9, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
+
+ {NC, NC, 0}
+};
+
+const PinMap PinMap_QSPI_SCLK[] = {
+ {PF_10, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {NC, NC, 0}
+};
+
+const PinMap PinMap_QSPI_SSEL[] = {
+ {PB_6, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
+ {NC, NC, 0}
+};
+
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h
index bea7fef5477..1702826fdb4 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h
@@ -58,6 +58,10 @@ struct trng_s {
RNG_HandleTypeDef handle;
};
+struct qspi_s {
+ QSPI_HandleTypeDef handle;
+};
+
#include "common_objects.h"
#ifdef __cplusplus
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
new file mode 100644
index 00000000000..bbdd238554d
--- /dev/null
+++ b/targets/TARGET_STM/qspi_api.c
@@ -0,0 +1,245 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2017, ARM Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if DEVICE_QSPI
+
+#include "qspi_api.h"
+#include "mbed_error.h"
+#include "cmsis.h"
+#include "pinmap.h"
+#include "PeripheralPins.h"
+
+#define QSPI_FLASH_SIZE_DEFAULT 32
+
+void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st_command)
+{
+ // TODO: shift these around to get more dynamic mapping
+ switch (command->instruction.bus_width) {
+ case QSPI_CFG_BUS_SINGLE:
+ st_command->InstructionMode = QSPI_INSTRUCTION_1_LINE;
+ break;
+ case QSPI_CFG_BUS_DUAL:
+ st_command->InstructionMode = QSPI_INSTRUCTION_2_LINES;
+ break;
+ case QSPI_CFG_BUS_QUAD:
+ st_command->InstructionMode = QSPI_INSTRUCTION_4_LINES;
+ break;
+ }
+
+ st_command->Instruction = command->instruction.value;
+ st_command->DummyCycles = command->dummy_count,
+ // these are target specific settings, use default values
+ st_command->SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+ st_command->DdrMode = QSPI_DDR_MODE_DISABLE;
+ st_command->DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+
+ switch (command->address.bus_width) {
+ case QSPI_CFG_BUS_SINGLE:
+ st_command->AddressMode = QSPI_ADDRESS_1_LINE;
+ break;
+ case QSPI_CFG_BUS_DUAL:
+ st_command->AddressMode = QSPI_ADDRESS_2_LINES;
+ break;
+ case QSPI_CFG_BUS_QUAD:
+ st_command->AddressMode = QSPI_ADDRESS_4_LINES;
+ break;
+ default:
+ st_command->AddressMode = QSPI_ADDRESS_1_LINE;
+ break;
+ }
+
+ if (command->address.size == QSPI_CFG_ADDR_SIZE_NONE) {
+ st_command->AddressMode = QSPI_ADDRESS_NONE;
+ }
+
+ switch (command->alt.bus_width) {
+ case QSPI_CFG_BUS_SINGLE:
+ st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_1_LINE;
+ break;
+ case QSPI_CFG_BUS_DUAL:
+ st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_2_LINES;
+ break;
+ case QSPI_CFG_BUS_QUAD:
+ st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES;
+ break;
+ default:
+ st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_1_LINE;
+ break;
+ }
+
+ if (command->alt.size == QSPI_CFG_ALT_SIZE_NONE) {
+ st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ }
+
+ switch (command->data.bus_width) {
+ case QSPI_CFG_BUS_SINGLE:
+ st_command->DataMode = QSPI_DATA_1_LINE;
+ break;
+ case QSPI_CFG_BUS_DUAL:
+ st_command->DataMode = QSPI_DATA_2_LINES;
+ break;
+ case QSPI_CFG_BUS_QUAD:
+ st_command->DataMode = QSPI_DATA_4_LINES;
+ break;
+ default:
+ st_command->DataMode = QSPI_DATA_1_LINE;
+ break;
+ }
+}
+
+
+qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, uint32_t hz, uint8_t mode)
+{
+ // Enable interface clock for QSPI
+ __HAL_RCC_QSPI_CLK_ENABLE();
+
+ // Reset QSPI
+ __HAL_RCC_QSPI_FORCE_RESET();
+ __HAL_RCC_QSPI_RELEASE_RESET();
+
+ // Set default QSPI handle values
+ obj->handle.Init.ClockPrescaler = 1;
+ obj->handle.Init.FifoThreshold = 4;
+ obj->handle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
+ obj->handle.Init.FlashSize = POSITION_VAL(QSPI_FLASH_SIZE_DEFAULT) - 1;
+ obj->handle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE;
+ obj->handle.Init.ClockMode = QSPI_CLOCK_MODE_0;
+ obj->handle.Init.FlashID = QSPI_FLASH_ID_1;
+ obj->handle.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
+
+ obj->handle.Init.ClockMode = mode == 0 ? QSPI_CLOCK_MODE_0 : QSPI_CLOCK_MODE_3;
+
+ obj->handle.Instance = QUADSPI;
+
+ // TODO pinmap here for pins (enable clock)
+ pinmap_pinout(io0, PinMap_QSPI_DATA);
+ pinmap_pinout(io1, PinMap_QSPI_DATA);
+ pinmap_pinout(io2, PinMap_QSPI_DATA);
+ pinmap_pinout(io3, PinMap_QSPI_DATA);
+
+ pinmap_pinout(sclk, PinMap_QSPI_SCLK);
+ pinmap_pinout(ssel, PinMap_QSPI_SSEL);
+
+ if (HAL_QSPI_Init(&obj->handle) != HAL_OK) {
+ error("Cannot initialize QSPI");
+ }
+ qspi_frequency(obj, hz);
+ return QSPI_STATUS_OK;
+}
+
+qspi_status_t qspi_free(qspi_t *obj)
+{
+ // TODO
+ return QSPI_STATUS_ERROR;
+}
+
+qspi_status_t qspi_frequency(qspi_t *obj, int hz)
+{
+ qspi_status_t status = QSPI_STATUS_OK;
+
+ // TODO calculate prescalers properly, needs some work
+
+ // HCLK drives QSPI
+ int div = HAL_RCC_GetHCLKFreq() / hz;
+ if (div > 256 || div < 1) {
+ status = QSPI_STATUS_INVALID_PARAMETER;
+ return status;
+ }
+
+ obj->handle.Init.ClockPrescaler = div - 1;
+
+ if (HAL_QSPI_Init(&obj->handle) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ }
+ return QSPI_STATUS_OK;
+}
+
+qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length)
+{
+ QSPI_CommandTypeDef st_command;
+ qspi_prepare_command(command, &st_command);
+
+ st_command.NbData = *length;
+ qspi_status_t status = QSPI_STATUS_OK;
+
+ if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ return status;
+ }
+
+ if (HAL_QSPI_Transmit(&obj->handle, (uint8_t *)data, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ }
+
+ if (QSPI_AutoPollingMemReady(&obj->handle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ }
+
+ return status;
+}
+
+qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length)
+{
+ QSPI_CommandTypeDef st_command;
+ qspi_prepare_command(command, &st_command);
+
+ st_command.NbData = *length;
+ qspi_status_t status = QSPI_STATUS_OK;
+
+ if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ return status;
+ }
+
+ if (HAL_QSPI_Receive(&obj->handle, data, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ }
+
+ if (QSPI_AutoPollingMemReady(&obj->handle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ }
+
+ return status;
+}
+
+qspi_status_t qspi_write_command(qspi_t *obj, const qspi_command_t *command)
+{
+
+ QSPI_CommandTypeDef st_command;
+ qspi_prepare_command(command, &st_command);
+
+ qspi_status_t status = QSPI_STATUS_OK;
+ if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ }
+ return status;
+}
+
+#endif
+
+/** @}*/
diff --git a/targets/targets.json b/targets/targets.json
index 50adc78d8ee..6a3896445fa 100755
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -1877,7 +1877,7 @@
},
"detect_code": ["0788"],
"macros_add": ["USB_STM_HAL", "USBHOST_OTHER"],
- "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"],
+ "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH", "QSPI"],
"release_versions": ["2", "5"],
"device_name": "STM32F469NI"
},
From 778e776e9b71ce89291f9db13819690796eb7e76 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Thu, 23 Nov 2017 14:08:21 +0000
Subject: [PATCH 28/61] QSPI STM32: fix ssel af selection
---
.../TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
index 6b1c6bd1924..905fff55407 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
@@ -405,7 +405,7 @@ const PinMap PinMap_QSPI_SCLK[] = {
};
const PinMap PinMap_QSPI_SSEL[] = {
- {PB_6, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
+ {PB_6, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
{NC, NC, 0}
};
From f6ddff6002bf23ea6d821ae6479e8bfa9284acf9 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Thu, 23 Nov 2017 14:34:11 +0000
Subject: [PATCH 29/61] QSPI STM32: fix return value in frequency
---
targets/TARGET_STM/qspi_api.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index bbdd238554d..a412e679d64 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -176,7 +176,7 @@ qspi_status_t qspi_frequency(qspi_t *obj, int hz)
if (HAL_QSPI_Init(&obj->handle) != HAL_OK) {
status = QSPI_STATUS_ERROR;
}
- return QSPI_STATUS_OK;
+ return status;
}
qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length)
From e30b670b565ca0d7ebe75e74a2ba7b39f4368386 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Thu, 23 Nov 2017 14:54:32 +0000
Subject: [PATCH 30/61] QSPI STM32: set default command values to none
---
targets/TARGET_STM/qspi_api.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index a412e679d64..37eab642c1d 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -49,6 +49,9 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
case QSPI_CFG_BUS_QUAD:
st_command->InstructionMode = QSPI_INSTRUCTION_4_LINES;
break;
+ default:
+ st_command->InstructionMode = QSPI_INSTRUCTION_NONE;
+ break;
}
st_command->Instruction = command->instruction.value;
@@ -69,7 +72,7 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
st_command->AddressMode = QSPI_ADDRESS_4_LINES;
break;
default:
- st_command->AddressMode = QSPI_ADDRESS_1_LINE;
+ st_command->AddressMode = QSPI_ADDRESS_NONE;
break;
}
@@ -88,7 +91,7 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES;
break;
default:
- st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_1_LINE;
+ st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
break;
}
@@ -107,7 +110,7 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
st_command->DataMode = QSPI_DATA_4_LINES;
break;
default:
- st_command->DataMode = QSPI_DATA_1_LINE;
+ st_command->DataMode = QSPI_DATA_NONE;
break;
}
}
@@ -162,8 +165,6 @@ qspi_status_t qspi_frequency(qspi_t *obj, int hz)
{
qspi_status_t status = QSPI_STATUS_OK;
- // TODO calculate prescalers properly, needs some work
-
// HCLK drives QSPI
int div = HAL_RCC_GetHCLKFreq() / hz;
if (div > 256 || div < 1) {
From 281eb87837c34808cbacf6b3f57c2c3311f4b1c3 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Fri, 24 Nov 2017 09:29:22 +0000
Subject: [PATCH 31/61] QSPI STM32: remove polling from write/read
This will be part of custom instruction transfer, the flow will be:
1. write data
2. wait for transfer to complete (poll status register from the memory device)
---
targets/TARGET_STM/qspi_api.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 37eab642c1d..1254b8213e6 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -197,10 +197,6 @@ qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void
status = QSPI_STATUS_ERROR;
}
- if (QSPI_AutoPollingMemReady(&obj->handle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
- status = QSPI_STATUS_ERROR;
- }
-
return status;
}
@@ -221,10 +217,6 @@ qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data,
status = QSPI_STATUS_ERROR;
}
- if (QSPI_AutoPollingMemReady(&obj->handle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
- status = QSPI_STATUS_ERROR;
- }
-
return status;
}
From 827314cb2e01c1fa82fa8bd13142db14abe7e02c Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Dec 2017 11:13:43 +0000
Subject: [PATCH 32/61] QSPI STM32: add qspi_command_transfer implementation
---
targets/TARGET_STM/qspi_api.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 1254b8213e6..52734859e66 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -220,15 +220,27 @@ qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data,
return status;
}
-qspi_status_t qspi_write_command(qspi_t *obj, const qspi_command_t *command)
+qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size)
{
+ qspi_status_t status = QSPI_STATUS_OK;
- QSPI_CommandTypeDef st_command;
- qspi_prepare_command(command, &st_command);
+ if (rx_size > 4) {
+ return QSPI_STATUS_INVALID_PARAMETER;
+ }
- qspi_status_t status = QSPI_STATUS_OK;
- if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
- status = QSPI_STATUS_ERROR;
+ QSPI_CommandTypeDef st_command;
+ qspi_prepare_command(command, &st_command);
+
+ QSPI_AutoPollingTypeDef s_config;
+ s_config.Match = 0;
+ s_config.Mask = 0;
+ s_config.MatchMode = QSPI_MATCH_MODE_OR;
+ s_config.StatusBytesSize = rx_size;
+ s_config.Interval = 0x10;
+ s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; // or QSPI_AUTOMATIC_STOP_DISABLE ?
+
+ if (HAL_QSPI_AutoPolling(&obj->handle, &st_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
}
return status;
}
From 412c7c59cc1d3287495c48addd9c772545e8cd5d Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Dec 2017 11:15:30 +0000
Subject: [PATCH 33/61] QSPI STM32: init returns error if failed to init
---
targets/TARGET_STM/qspi_api.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 52734859e66..af82283f73e 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -149,7 +149,7 @@ qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinN
pinmap_pinout(ssel, PinMap_QSPI_SSEL);
if (HAL_QSPI_Init(&obj->handle) != HAL_OK) {
- error("Cannot initialize QSPI");
+ return QSPI_STATUS_ERROR;
}
qspi_frequency(obj, hz);
return QSPI_STATUS_OK;
From cb38c94e7d7fd74189a96135b2d11a54744d71bf Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Dec 2017 11:38:47 +0000
Subject: [PATCH 34/61] QSPI STM32: add QSPI_x support to pinnames
---
.../TARGET_DISCO_F469NI/PeripheralNames.h | 4 ++++
.../TARGET_DISCO_F469NI/PeripheralPins.c | 12 ++++++------
targets/TARGET_STM/qspi_api.c | 12 +++++++++++-
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h
index ce3afd56588..39455e98e60 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h
@@ -92,6 +92,10 @@ typedef enum {
CAN_2 = (int)CAN2_BASE
} CANName;
+typedef enum {
+ QSPI_1 = (int)QSPI_R_BASE,
+} QSPIName;
+
#ifdef __cplusplus
}
#endif
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
index 905fff55407..81fbb3f231b 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
@@ -391,21 +391,21 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = {
const PinMap PinMap_QSPI_DATA[] = {
- {PF_6, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
- {PF_7, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
- {PF_8, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
- {PF_9, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
+ {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
+ {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
{NC, NC, 0}
};
const PinMap PinMap_QSPI_SCLK[] = {
- {PF_10, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {PF_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
{NC, NC, 0}
};
const PinMap PinMap_QSPI_SSEL[] = {
- {PB_6, 0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
+ {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
{NC, NC, 0}
};
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index af82283f73e..76f12218241 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -137,7 +137,17 @@ qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinN
obj->handle.Init.ClockMode = mode == 0 ? QSPI_CLOCK_MODE_0 : QSPI_CLOCK_MODE_3;
- obj->handle.Instance = QUADSPI;
+ QSPIName qspi_data_first = (SPIName)pinmap_merge(io0, io1);
+ QSPIName qspi_data_second = (SPIName)pinmap_merge(io1, io2);
+ QSPIName qspi_data_third = (SPIName)pinmap_merge(io2, io3);
+
+ if (qspi_data_first != qspi_data_second || qspi_data_second != qspi_data_third ||
+ qspi_data_first != qspi_data_third) {
+ return QSPI_STATUS_INVALID_PARAMETER;
+ }
+
+ // tested all combinations, take first
+ obj->handle.Instance = (QUADSPI_TypeDef *)qspi_data_first;
// TODO pinmap here for pins (enable clock)
pinmap_pinout(io0, PinMap_QSPI_DATA);
From f344e5a99a29dee9263637f27034e2cfdde23873 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Mon, 11 Dec 2017 13:01:13 +0000
Subject: [PATCH 35/61] QSPI STM32: fix disabled format phase
---
targets/TARGET_STM/qspi_api.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 76f12218241..fd6b4a9319f 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -76,7 +76,7 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
break;
}
- if (command->address.size == QSPI_CFG_ADDR_SIZE_NONE) {
+ if (command->address.disabled == true) {
st_command->AddressMode = QSPI_ADDRESS_NONE;
}
@@ -95,7 +95,7 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
break;
}
- if (command->alt.size == QSPI_CFG_ALT_SIZE_NONE) {
+ if (command->alt.disabled == true) {
st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
}
From 5bf67f97296a6a222ce61b184e9f2f8514f2079d Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 12 Dec 2017 14:44:37 +0000
Subject: [PATCH 36/61] QSPI STM32: fix pin merging
hw name as input
---
targets/TARGET_STM/qspi_api.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index fd6b4a9319f..657bfaa5e11 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -137,9 +137,16 @@ qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinN
obj->handle.Init.ClockMode = mode == 0 ? QSPI_CLOCK_MODE_0 : QSPI_CLOCK_MODE_3;
- QSPIName qspi_data_first = (SPIName)pinmap_merge(io0, io1);
- QSPIName qspi_data_second = (SPIName)pinmap_merge(io1, io2);
- QSPIName qspi_data_third = (SPIName)pinmap_merge(io2, io3);
+ QSPIName qspiio0name = (QSPIName)pinmap_peripheral(io0, PinMap_QSPI_DATA);
+ QSPIName qspiio1name = (QSPIName)pinmap_peripheral(io1, PinMap_QSPI_DATA);
+ QSPIName qspiio2name = (QSPIName)pinmap_peripheral(io2, PinMap_QSPI_DATA);
+ QSPIName qspiio3name = (QSPIName)pinmap_peripheral(io3, PinMap_QSPI_DATA);
+ QSPIName qspiclkname = (QSPIName)pinmap_peripheral(sclk, PinMap_QSPI_SCLK);
+ QSPIName qspisselname = (QSPIName)pinmap_peripheral(ssel, PinMap_QSPI_SSEL);
+
+ QSPIName qspi_data_first = (QSPIName)pinmap_merge(qspiio0name, qspiio1name);
+ QSPIName qspi_data_second = (QSPIName)pinmap_merge(qspiio2name, qspiio3name);
+ QSPIName qspi_data_third = (QSPIName)pinmap_merge(qspiclkname, qspisselname);
if (qspi_data_first != qspi_data_second || qspi_data_second != qspi_data_third ||
qspi_data_first != qspi_data_third) {
From 9e6ea891b0abd1b724644c5458c83ba76a4786e0 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 12 Dec 2017 16:31:38 +0000
Subject: [PATCH 37/61] QSPI STM32: fix command transfer
use write/read from STM32 driver
---
targets/TARGET_STM/qspi_api.c | 41 ++++++++++++++++++++---------------
1 file changed, 24 insertions(+), 17 deletions(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 657bfaa5e11..67ef6c2bc86 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -241,23 +241,30 @@ qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command,
{
qspi_status_t status = QSPI_STATUS_OK;
- if (rx_size > 4) {
- return QSPI_STATUS_INVALID_PARAMETER;
- }
-
- QSPI_CommandTypeDef st_command;
- qspi_prepare_command(command, &st_command);
-
- QSPI_AutoPollingTypeDef s_config;
- s_config.Match = 0;
- s_config.Mask = 0;
- s_config.MatchMode = QSPI_MATCH_MODE_OR;
- s_config.StatusBytesSize = rx_size;
- s_config.Interval = 0x10;
- s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; // or QSPI_AUTOMATIC_STOP_DISABLE ?
-
- if (HAL_QSPI_AutoPolling(&obj->handle, &st_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
- status = QSPI_STATUS_ERROR;
+ if ((tx_data == NULL || tx_size == 0) && (rx_data == NULL || rx_size == 0)) {
+ // only command, no rx or tx
+ QSPI_CommandTypeDef st_command;
+ qspi_prepare_command(command, &st_command);
+
+ st_command.NbData = 1;
+ if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
+ status = QSPI_STATUS_ERROR;
+ return status;
+ }
+ } else {
+ // often just read a register, check if we need to transmit anything prior reading
+ if (tx_data != NULL && tx_size) {
+ size_t tx_length = tx_size;
+ status = qspi_write(obj, command, tx_data, &tx_length);
+ if (status != QSPI_STATUS_OK) {
+ return status;
+ }
+ }
+
+ if (rx_data != NULL && rx_size) {
+ size_t rx_length = rx_size;
+ status = qspi_read(obj, command, rx_data, &rx_length);
+ }
}
return status;
}
From 6a9716182e4659b452a3869719b9a2a5a286025f Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 12 Dec 2017 16:34:55 +0000
Subject: [PATCH 38/61] QSPI STM32: fix prepare comman - alt/address
---
targets/TARGET_STM/qspi_api.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 67ef6c2bc86..c586a2712b6 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -78,6 +78,10 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
if (command->address.disabled == true) {
st_command->AddressMode = QSPI_ADDRESS_NONE;
+ st_command->AddressSize = 0;
+ } else {
+ st_command->Address = command->address.value;
+ st_command->AddressSize = command->address.size;
}
switch (command->alt.bus_width) {
@@ -97,6 +101,10 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
if (command->alt.disabled == true) {
st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ st_command->AlternateBytesSize = 0;
+ } else {
+ st_command->AlternateBytes = command->alt.value;
+ st_command->AlternateBytesSize = command->alt.size;
}
switch (command->data.bus_width) {
@@ -113,6 +121,8 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
st_command->DataMode = QSPI_DATA_NONE;
break;
}
+
+ st_command->NbData = 0;
}
From 52608106b89d58000f35d40c4effd5e1b2da4a04 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 12 Dec 2017 16:38:58 +0000
Subject: [PATCH 39/61] QSPI STM32: fix default fifo and cycle
As example for DISCO F469NI defines them
---
targets/TARGET_STM/qspi_api.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index c586a2712b6..a08420e577d 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -137,10 +137,10 @@ qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinN
// Set default QSPI handle values
obj->handle.Init.ClockPrescaler = 1;
- obj->handle.Init.FifoThreshold = 4;
+ obj->handle.Init.FifoThreshold = 1;
obj->handle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
obj->handle.Init.FlashSize = POSITION_VAL(QSPI_FLASH_SIZE_DEFAULT) - 1;
- obj->handle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE;
+ obj->handle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_5_CYCLE;
obj->handle.Init.ClockMode = QSPI_CLOCK_MODE_0;
obj->handle.Init.FlashID = QSPI_FLASH_ID_1;
obj->handle.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
From 1e8df28c5618c59a68cdf21532c16c4094662dae Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 9 Jan 2018 13:47:56 +0000
Subject: [PATCH 40/61] QSPI: hal doxygen fixes
Small corrections, fixing typos in the documentation
---
hal/qspi_api.h | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 525ff431229..144f4f43d42 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -33,7 +33,7 @@ extern "C" {
* @{
*/
-/** QSPI HAL object declaration
+/** QSPI HAL object
*/
typedef struct qspi_s qspi_t;
@@ -47,7 +47,7 @@ typedef enum qspi_bus_width {
QSPI_CFG_BUS_QUAD,
} qspi_bus_width_t;
-/** Address size
+/** Address size in bits
*/
typedef enum qspi_address_size {
QSPI_CFG_ADDR_SIZE_8,
@@ -56,7 +56,7 @@ typedef enum qspi_address_size {
QSPI_CFG_ADDR_SIZE_32,
} qspi_address_size_t;
-/** Alternative size
+/** Alternative size in bits
*/
typedef enum qspi_alt_size {
QSPI_CFG_ALT_SIZE_8,
@@ -65,9 +65,9 @@ typedef enum qspi_alt_size {
QSPI_CFG_ALT_SIZE_32,
} qspi_alt_size_t;
-/** QSPI command declaration
+/** QSPI command
*
- * Defines a frame format
+ * Defines a frame format. It consists of instruction, address, alternative, dummy count and data
*/
typedef struct qspi_command {
struct {
@@ -148,35 +148,33 @@ qspi_status_t qspi_frequency(qspi_t *obj, int hz);
* @param obj QSPI object
* @param command QSPI command
* @param data TX buffer
- * @param[in,out] in - length TX buffer length in bytes, out - number of bytes written
+ * @param[in,out] length in - TX buffer length in bytes, out - number of bytes written
* @return QSPI_STATUS_OK if the data has been succesfully sent
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
*/
qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length);
-/** Send a command (and optionally data) and get the response. Can be used to send/receive device specific commands.
+/** Send a command (and optionally data) and get the response. Can be used to send/receive device specific commands
*
* @param obj QSPI object
* @param command QSPI command
* @param tx_data TX buffer
- * @param tx_length pointer to variable holding TX buffer length
- * @param rx_data TX buffer
- * @param rx_length pointer to variable holding TX buffer length
+ * @param tx_length TX buffer length in bytes
+ * @param rx_data RX buffer
+ * @param rx_length RX buffer length in bytes
* @return QSPI_STATUS_OK if the data has been succesfully sent
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
*/
-
qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size);
-
/** Receive a command and block of data
*
* @param obj QSPI object
* @param command QSPI command
* @param data RX buffer
- * @param[in,out] in - length RX buffer length in bytes, out - number of bytes read
+ * @param[in,out] length in - RX buffer length in bytes, out - number of bytes read
* @return QSPI_STATUS_OK if data has been succesfully received
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
From b695d39b5b198e708beb2a7609e561119b9363c8 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Mon, 8 Jan 2018 15:25:05 +0000
Subject: [PATCH 41/61] QSPI: add flash pins for F469 disco board
---
.../TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h
index 5d8187d616d..58ebf4e8f63 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h
@@ -406,6 +406,13 @@ typedef enum {
SYS_TRACED3_ALT0 = PE_6,
SYS_WKUP = PA_0,
+ QSPI_FLASH_IO0 = PF_8,
+ QSPI_FLASH_IO1 = PF_9,
+ QSPI_FLASH_IO2 = PF_7,
+ QSPI_FLASH_IO3 = PF_6,
+ QSPI_FLASH_SCK = PF_10,
+ QSPI_FLASH_CSN = PB_6,
+
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
From 0847a97f6abbc5a0233f1acdfd52f1e309187b1c Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Mon, 8 Jan 2018 15:31:05 +0000
Subject: [PATCH 42/61] QSPI: add flash pins for nrf52480_dk board
---
.../TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h
index 2a5f319abdb..4241cdcf479 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h
@@ -227,6 +227,13 @@ typedef enum {
A4 = p30,
A5 = p31,
+ QSPI_FLASH_IO0 = P0_20,
+ QSPI_FLASH_IO1 = P0_21,
+ QSPI_FLASH_IO2 = P0_22,
+ QSPI_FLASH_IO3 = P0_23,
+ QSPI_FLASH_SCK = P0_19,
+ QSPI_FLASH_CSN = P0_17,
+
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
From d4d38513ce0a695a76e75185e234883236a41380 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Wed, 10 Jan 2018 10:13:47 +0000
Subject: [PATCH 43/61] QSPI: add STM32L4 support
Disco IoT board support for QSPI. As it does not have dual flash support in QSPI,
we need to fix qspi hal implementation.
---
.../PeripheralNames.h | 4 ++++
.../PeripheralPins.c | 24 +++++++++++++++++++
.../TARGET_STM32L475xG/objects.h | 4 ++++
targets/TARGET_STM/qspi_api.c | 2 ++
targets/targets.json | 2 +-
5 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h
index 2a66882a1c0..04b09f65395 100644
--- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h
+++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h
@@ -83,6 +83,10 @@ typedef enum {
CAN_1 = (int)CAN1_BASE
} CANName;
+typedef enum {
+ QSPI_1 = (int)QSPI_R_BASE,
+} QSPIName;
+
#ifdef __cplusplus
}
#endif
diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c
index a21e78ce22d..502b176fa29 100644
--- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c
@@ -340,3 +340,27 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = {
{PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to PMOD_SPI2_SCK
{NC, NC, 0}
};
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA[] = {
+ {PE_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PE_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PE_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PE_15, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = {
+ {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = {
+ {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {NC, NC, 0}
+};
diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h
index e68c4eb6194..249e162543f 100644
--- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h
+++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h
@@ -58,6 +58,10 @@ struct trng_s {
RNG_HandleTypeDef handle;
};
+struct qspi_s {
+ QSPI_HandleTypeDef handle;
+};
+
#include "common_objects.h"
#ifdef __cplusplus
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index a08420e577d..26ed1d3bf01 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -142,8 +142,10 @@ qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinN
obj->handle.Init.FlashSize = POSITION_VAL(QSPI_FLASH_SIZE_DEFAULT) - 1;
obj->handle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_5_CYCLE;
obj->handle.Init.ClockMode = QSPI_CLOCK_MODE_0;
+#ifdef QSPI_DUALFLASH_ENABLE
obj->handle.Init.FlashID = QSPI_FLASH_ID_1;
obj->handle.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
+#endif
obj->handle.Init.ClockMode = mode == 0 ? QSPI_CLOCK_MODE_0 : QSPI_CLOCK_MODE_3;
diff --git a/targets/targets.json b/targets/targets.json
index 6a3896445fa..e1d5e51ad64 100755
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -2010,7 +2010,7 @@
"supported_form_factors": ["ARDUINO"],
"detect_code": ["0764"],
"macros_add": ["USBHOST_OTHER"],
- "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"],
+ "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH", "QSPI"],
"release_versions": ["2", "5"],
"device_name": "STM32L475VG",
"bootloader_supported": true
From a00ee5dc27e166dc6827ac9af1fc093ec8347e27 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Fri, 16 Feb 2018 14:19:51 +0000
Subject: [PATCH 44/61] QSPI: fix memset header file missing
---
drivers/QSPI.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index f2e19b8af8f..ceebcd3aa3f 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -16,6 +16,7 @@
#include "drivers/QSPI.h"
#include "platform/mbed_critical.h"
+#include
#if DEVICE_QSPI
From a44518696cbf146ae93c733f8c712e38ca42d3f4 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 13 Feb 2018 16:48:02 +0000
Subject: [PATCH 45/61] QSPI: add address to command transfer
---
drivers/QSPI.cpp | 4 ++--
drivers/QSPI.h | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index ceebcd3aa3f..1cfd372de20 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -194,14 +194,14 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned i
return ret_status;
}
-qspi_status_t QSPI::command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
+qspi_status_t QSPI::command_transfer(unsigned int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
if (_initialized) {
lock();
if (true == _acquire()) {
- _build_qspi_command(instruction, -1, -1); //We just need the command
+ _build_qspi_command(instruction, address, -1); //We just need the command
if (QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 817dbfc421e..e499ee80476 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -159,6 +159,7 @@ class QSPI : private NonCopyable {
/** Perform a transaction to write to an address(a control register) and get the status results
*
* @param instruction Instruction value to be used in instruction phase
+ * @param address Some instruction might require address. Use -1 for ignoring the address value
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
* @param rx_buffer Buffer for data to be read from the peripheral
@@ -167,7 +168,7 @@ class QSPI : private NonCopyable {
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t command_transfer(unsigned int instruction, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
+ qspi_status_t command_transfer(unsigned int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
/** Acquire exclusive access to this SPI bus
*/
From 8e3c981a3a409b6c350d4b8b891613d931bc009a Mon Sep 17 00:00:00 2001
From: adustm
Date: Thu, 22 Mar 2018 18:19:39 +0100
Subject: [PATCH 46/61] Fix Address.Size and AlternateByes.Size by shifting
them
The ST HAL code is waiting for the correctly shifted vlue
(for a direct write into the HW register)
---
targets/TARGET_STM/qspi_api.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 26ed1d3bf01..729a1d0f310 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -81,7 +81,8 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
st_command->AddressSize = 0;
} else {
st_command->Address = command->address.value;
- st_command->AddressSize = command->address.size;
+ /* command->address.size needs to be shifted by QUADSPI_CCR_ADSIZE_Pos */
+ st_command->AddressSize = (command->address.size << QUADSPI_CCR_ADSIZE_Pos) & QUADSPI_CCR_ADSIZE_Msk;
}
switch (command->alt.bus_width) {
@@ -104,6 +105,8 @@ void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st
st_command->AlternateBytesSize = 0;
} else {
st_command->AlternateBytes = command->alt.value;
+ /* command->AlternateBytesSize needs to be shifted by QUADSPI_CCR_ABSIZE_Pos */
+ st_command->AlternateBytesSize = (command->alt.size << QUADSPI_CCR_ABSIZE_Pos) & QUADSPI_CCR_ABSIZE_Msk;
st_command->AlternateBytesSize = command->alt.size;
}
From 99ae9796e498130cf1673b9b5cdee8971c5f4e83 Mon Sep 17 00:00:00 2001
From: adustm
Date: Thu, 22 Mar 2018 18:26:39 +0100
Subject: [PATCH 47/61] Fix Instruction with no data command Adding
QSPI_DATA_NONE activates the transfer of the command inside HAL_QSPI_COMMAND
function
---
targets/TARGET_STM/qspi_api.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 729a1d0f310..7764c98b93c 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -262,6 +262,7 @@ qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command,
qspi_prepare_command(command, &st_command);
st_command.NbData = 1;
+ st_command.DataMode = QSPI_DATA_NONE; /* Instruction only */
if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
status = QSPI_STATUS_ERROR;
return status;
From b0898f7b35f0e0d32635b04e5e5a7b87d8d8e7f2 Mon Sep 17 00:00:00 2001
From: adustm
Date: Tue, 20 Mar 2018 18:50:43 +0100
Subject: [PATCH 48/61] Dummy cycles count is not an init parameter, but a
command parameter. It can change depending on the chosen command, not only at
start. This way we avoid to launch init function and break the internal
status variables.
---
drivers/QSPI.cpp | 22 ++++++++++------------
drivers/QSPI.h | 9 +++++----
2 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index 1cfd372de20..ba9c9d19408 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -39,7 +39,6 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_alt_width = QSPI_CFG_BUS_SINGLE;
_alt_size = QSPI_CFG_ALT_SIZE_8;
_data_width = QSPI_CFG_BUS_SINGLE;
- _num_dummy_cycles = 0;
_mode = 0;
_hz = ONE_MHZ;
_initialized = false;
@@ -62,7 +61,6 @@ qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width
_alt_width = alt_width;
_alt_size = alt_size;
_data_width = data_width;
- _num_dummy_cycles = dummy_cycles;
_mode = mode;
//Re-init the device, as the mode might have changed
@@ -107,7 +105,7 @@ qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_lengt
if (*rx_length != 0) {
lock();
if (true == _acquire()) {
- _build_qspi_command(-1, address, -1);
+ _build_qspi_command(-1, address, -1, 0);
if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -131,7 +129,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
if (*tx_length != 0) {
lock();
if (true == _acquire()) {
- _build_qspi_command(-1, address, -1);
+ _build_qspi_command(-1, address, -1, 0);
if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -146,7 +144,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
return ret_status;
}
-qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length)
+qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, char *rx_buffer, size_t *rx_length)
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
@@ -155,7 +153,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned in
if (*rx_length != 0) {
lock();
if ( true == _acquire()) {
- _build_qspi_command(instruction, address, alt);
+ _build_qspi_command(instruction, address, alt, dummy_cnt);
if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -170,7 +168,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned in
return ret_status;
}
-qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length)
+qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, const char *tx_buffer, size_t *tx_length)
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
@@ -179,7 +177,7 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned i
if (*tx_length != 0) {
lock();
if (true == _acquire()) {
- _build_qspi_command(instruction, address, alt);
+ _build_qspi_command(instruction, address, alt, dummy_cnt);
if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -201,7 +199,7 @@ qspi_status_t QSPI::command_transfer(unsigned int instruction, int address, cons
if (_initialized) {
lock();
if (true == _acquire()) {
- _build_qspi_command(instruction, address, -1); //We just need the command
+ _build_qspi_command(instruction, address, -1, 0); //We just need the command
if (QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -247,7 +245,7 @@ bool QSPI::_acquire()
return _initialized;
}
-void QSPI::_build_qspi_command(int instruction, int address, int alt)
+void QSPI::_build_qspi_command(int instruction, int address, int alt, int dummy_cnt)
{
memset( &_qspi_command, 0, sizeof(qspi_command_t) );
//Set up instruction phase parameters
@@ -278,8 +276,8 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt)
} else {
_qspi_command.alt.disabled = true;
}
-
- _qspi_command.dummy_count = _num_dummy_cycles;
+
+ _qspi_command.dummy_count = dummy_cnt;
//Set up bus width for data phase
_qspi_command.data.bus_width = _data_width;
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index e499ee80476..2575af1c125 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -134,6 +134,7 @@ class QSPI : private NonCopyable {
*
* @param instruction Instruction value to be used in instruction phase
* @param alt Alt value to be used in instruction phase
+ * @param dummy_cnt Amount of dummy cycles to be sent after instruction phase
* @param address Address to be accessed in QSPI peripheral
* @param rx_buffer Buffer for data to be read from the peripheral
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
@@ -141,12 +142,13 @@ class QSPI : private NonCopyable {
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length);
+ qspi_status_t read(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, char *rx_buffer, size_t *rx_length);
/** Write to QSPI peripheral using custom write instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase
* @param alt Alt value to be used in instruction phase
+ * @param dummy_cnt Amount of dummy cycles to be sent after instruction phase
* @param address Address to be accessed in QSPI peripheral
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
@@ -154,7 +156,7 @@ class QSPI : private NonCopyable {
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length);
+ qspi_status_t write(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, const char *tx_buffer, size_t *tx_length);
/** Perform a transaction to write to an address(a control register) and get the status results
*
@@ -195,7 +197,6 @@ class QSPI : private NonCopyable {
qspi_alt_size_t _alt_size;
qspi_bus_width_t _data_width; //Bus width for Data phase
qspi_command_t _qspi_command; //QSPI Hal command struct
- unsigned int _num_dummy_cycles; //Number of dummy cycles to be used
int _hz; //Bus Frequency
int _mode; //SPI mode
bool _initialized;
@@ -211,7 +212,7 @@ class QSPI : private NonCopyable {
/*
* This function builds the qspi command struct to be send to Hal
*/
- inline void _build_qspi_command(int instruction, int address, int alt);
+ inline void _build_qspi_command(int instruction, int address, int alt, int dummy_cnt);
};
} // namespace mbed
From 6121e240ae148852f561de050af8c08fc9026f11 Mon Sep 17 00:00:00 2001
From: adustm
Date: Mon, 19 Mar 2018 16:56:42 +0100
Subject: [PATCH 49/61] Change default FlashSize to 64Mbit = 8Mbytes = 0x800000
---
targets/TARGET_STM/qspi_api.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 7764c98b93c..1b1c6af9f90 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -34,7 +34,7 @@
#include "pinmap.h"
#include "PeripheralPins.h"
-#define QSPI_FLASH_SIZE_DEFAULT 32
+#define QSPI_FLASH_SIZE_DEFAULT 0x800000
void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st_command)
{
From cab6eda92e0c8d1cda16220c775a22fe4a5326ac Mon Sep 17 00:00:00 2001
From: adustm
Date: Fri, 30 Mar 2018 11:50:11 +0200
Subject: [PATCH 50/61] Move _mode from QSPI::configure_format to QSPI::QSPI
QSPI::configure_format shall not call initialize function. This way,
QSPI::configure_format can be called any time, only to change the format of
commands. It must contain only parameters for the commands, not for the Init
function
---
drivers/QSPI.cpp | 17 ++++++-----------
drivers/QSPI.h | 9 +++++----
2 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index ba9c9d19408..b13453ffd33 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -25,7 +25,7 @@ namespace mbed {
QSPI* QSPI::_owner = NULL;
SingletonPtr QSPI::_mutex;
-QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel) : _qspi()
+QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, int mode) : _qspi()
{
_qspi_io0 = io0;
_qspi_io1 = io1;
@@ -39,7 +39,7 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_alt_width = QSPI_CFG_BUS_SINGLE;
_alt_size = QSPI_CFG_ALT_SIZE_8;
_data_width = QSPI_CFG_BUS_SINGLE;
- _mode = 0;
+ _mode = mode;
_hz = ONE_MHZ;
_initialized = false;
@@ -47,13 +47,10 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_initialize();
}
-qspi_status_t QSPI::configure_format(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, int mode )
+qspi_status_t QSPI::configure_format(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)
{
qspi_status_t ret_status = QSPI_STATUS_OK;
- if (mode != 0 && mode != 1)
- return QSPI_STATUS_INVALID_PARAMETER;
-
lock();
_inst_width = inst_width;
_address_width = address_width;
@@ -61,12 +58,7 @@ qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width
_alt_width = alt_width;
_alt_size = alt_size;
_data_width = data_width;
- _mode = mode;
- //Re-init the device, as the mode might have changed
- if ( !_initialize() ) {
- ret_status = QSPI_STATUS_ERROR;
- }
unlock();
return ret_status;
@@ -223,6 +215,9 @@ void QSPI::unlock()
// Note: Private helper function to initialize qspi HAL
bool QSPI::_initialize()
{
+ if (_mode != 0 && _mode != 1)
+ return QSPI_STATUS_INVALID_PARAMETER;
+
qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode );
if (QSPI_STATUS_OK == ret) {
_initialized = true;
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 2575af1c125..09a7549db15 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -76,8 +76,11 @@ class QSPI : private NonCopyable {
* @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
* @param sclk QSPI Clock pin
* @param ssel QSPI chip select pin
+ * @param mode Mode specifies the SPI mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
+ * default value = 0
+ *
*/
- QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel=NC);
+ QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel=NC, int mode=0);
/** Configure the data transmission format
*
@@ -88,7 +91,6 @@ class QSPI : private NonCopyable {
* @param alt_size Size in bits used by alt phase(Valid values are 8,16,24,32)
* @param data_width Bus width used by data phase(Valid values are 1,2,4)
* @param dummy_cycles Number of dummy clock cycles to be used after alt phase
- * @param mode Mode specifies the SPI mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
*
*/
qspi_status_t configure_format(qspi_bus_width_t inst_width,
@@ -97,8 +99,7 @@ class QSPI : private NonCopyable {
qspi_bus_width_t alt_width,
qspi_alt_size_t alt_size,
qspi_bus_width_t data_width,
- int dummy_cycles,
- int mode);
+ int dummy_cycles);
/** Set the qspi bus clock frequency
*
From 842b8596e91ff679b20fa9368c2c785a007ddcef Mon Sep 17 00:00:00 2001
From: adustm
Date: Fri, 30 Mar 2018 14:55:33 +0200
Subject: [PATCH 51/61] Revert "Dummy cycles count is not an init parameter,
but a command parameter."
This reverts commit f1ad089660ac59eb81cfe5d76d7af394d471c30d.
---
drivers/QSPI.cpp | 20 +++++++++++---------
drivers/QSPI.h | 9 ++++-----
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp
index b13453ffd33..36cad333e1c 100644
--- a/drivers/QSPI.cpp
+++ b/drivers/QSPI.cpp
@@ -39,6 +39,7 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
_alt_width = QSPI_CFG_BUS_SINGLE;
_alt_size = QSPI_CFG_ALT_SIZE_8;
_data_width = QSPI_CFG_BUS_SINGLE;
+ _num_dummy_cycles = 0;
_mode = mode;
_hz = ONE_MHZ;
_initialized = false;
@@ -58,6 +59,7 @@ qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width
_alt_width = alt_width;
_alt_size = alt_size;
_data_width = data_width;
+ _num_dummy_cycles = dummy_cycles;
unlock();
@@ -97,7 +99,7 @@ qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_lengt
if (*rx_length != 0) {
lock();
if (true == _acquire()) {
- _build_qspi_command(-1, address, -1, 0);
+ _build_qspi_command(-1, address, -1);
if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -121,7 +123,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
if (*tx_length != 0) {
lock();
if (true == _acquire()) {
- _build_qspi_command(-1, address, -1, 0);
+ _build_qspi_command(-1, address, -1);
if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -136,7 +138,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t
return ret_status;
}
-qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, char *rx_buffer, size_t *rx_length)
+qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length)
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
@@ -145,7 +147,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned in
if (*rx_length != 0) {
lock();
if ( true == _acquire()) {
- _build_qspi_command(instruction, address, alt, dummy_cnt);
+ _build_qspi_command(instruction, address, alt);
if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -160,7 +162,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned in
return ret_status;
}
-qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, const char *tx_buffer, size_t *tx_length)
+qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length)
{
qspi_status_t ret_status = QSPI_STATUS_ERROR;
@@ -169,7 +171,7 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned i
if (*tx_length != 0) {
lock();
if (true == _acquire()) {
- _build_qspi_command(instruction, address, alt, dummy_cnt);
+ _build_qspi_command(instruction, address, alt);
if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -191,7 +193,7 @@ qspi_status_t QSPI::command_transfer(unsigned int instruction, int address, cons
if (_initialized) {
lock();
if (true == _acquire()) {
- _build_qspi_command(instruction, address, -1, 0); //We just need the command
+ _build_qspi_command(instruction, address, -1); //We just need the command
if (QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
ret_status = QSPI_STATUS_OK;
}
@@ -240,7 +242,7 @@ bool QSPI::_acquire()
return _initialized;
}
-void QSPI::_build_qspi_command(int instruction, int address, int alt, int dummy_cnt)
+void QSPI::_build_qspi_command(int instruction, int address, int alt)
{
memset( &_qspi_command, 0, sizeof(qspi_command_t) );
//Set up instruction phase parameters
@@ -272,7 +274,7 @@ void QSPI::_build_qspi_command(int instruction, int address, int alt, int dummy_
_qspi_command.alt.disabled = true;
}
- _qspi_command.dummy_count = dummy_cnt;
+ _qspi_command.dummy_count = _num_dummy_cycles;
//Set up bus width for data phase
_qspi_command.data.bus_width = _data_width;
diff --git a/drivers/QSPI.h b/drivers/QSPI.h
index 09a7549db15..ecf2d43e121 100644
--- a/drivers/QSPI.h
+++ b/drivers/QSPI.h
@@ -135,7 +135,6 @@ class QSPI : private NonCopyable {
*
* @param instruction Instruction value to be used in instruction phase
* @param alt Alt value to be used in instruction phase
- * @param dummy_cnt Amount of dummy cycles to be sent after instruction phase
* @param address Address to be accessed in QSPI peripheral
* @param rx_buffer Buffer for data to be read from the peripheral
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
@@ -143,13 +142,12 @@ class QSPI : private NonCopyable {
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t read(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, char *rx_buffer, size_t *rx_length);
+ qspi_status_t read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length);
/** Write to QSPI peripheral using custom write instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase
* @param alt Alt value to be used in instruction phase
- * @param dummy_cnt Amount of dummy cycles to be sent after instruction phase
* @param address Address to be accessed in QSPI peripheral
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
@@ -157,7 +155,7 @@ class QSPI : private NonCopyable {
* @returns
* Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
*/
- qspi_status_t write(unsigned int instruction, unsigned int alt, unsigned int dummy_cnt, unsigned int address, const char *tx_buffer, size_t *tx_length);
+ qspi_status_t write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length);
/** Perform a transaction to write to an address(a control register) and get the status results
*
@@ -198,6 +196,7 @@ class QSPI : private NonCopyable {
qspi_alt_size_t _alt_size;
qspi_bus_width_t _data_width; //Bus width for Data phase
qspi_command_t _qspi_command; //QSPI Hal command struct
+ unsigned int _num_dummy_cycles; //Number of dummy cycles to be used
int _hz; //Bus Frequency
int _mode; //SPI mode
bool _initialized;
@@ -213,7 +212,7 @@ class QSPI : private NonCopyable {
/*
* This function builds the qspi command struct to be send to Hal
*/
- inline void _build_qspi_command(int instruction, int address, int alt, int dummy_cnt);
+ inline void _build_qspi_command(int instruction, int address, int alt);
};
} // namespace mbed
From 43fa141f62a8c262c7bd582f721d09c57957459a Mon Sep 17 00:00:00 2001
From: adustm
Date: Mon, 9 Apr 2018 11:41:02 +0200
Subject: [PATCH 52/61] Enable QSPI feature for DISCO_F413ZH platform
---
.../TARGET_DISCO_F413ZH/PeripheralNames.h | 4 ++
.../TARGET_DISCO_F413ZH/PeripheralPins.c | 40 +++++++++++++++++++
.../TARGET_STM32F413xH/objects.h | 4 ++
targets/targets.json | 2 +-
4 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h
index 22ad0b3f55a..3493e2cd25e 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h
@@ -79,6 +79,10 @@ typedef enum {
CAN_3 = (int)CAN3_BASE
} CANName;
+typedef enum {
+ QSPI_1 = (int)QSPI_R_BASE,
+} QSPIName;
+
#ifdef __cplusplus
}
#endif
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c
index 3f5be127388..cf3b81ab5f9 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c
@@ -399,3 +399,43 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = {
{PG_12, CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)}, // Connected to WIFI_DRDY
{NC, NC, 0}
};
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA[] = {
+ {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3
+ {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0
+ {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1
+ {PC_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2
+ {PC_5, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3
+ {PC_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO2
+ {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO0
+ {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO1
+ {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0
+ {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1
+ {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3, N25Q128A13EF840F
+ {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2, N25Q128A13EF840F
+ {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0
+ {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1
+ {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2
+ {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3
+ {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3
+ {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2
+ {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO0, N25Q128A13EF840F
+ {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO1, N25Q128A13EF840F
+ {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO2
+ {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO3
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = {
+ {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // N25Q128A13EF840F
+ {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = {
+ {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS
+ {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_NCS
+ {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS, N25Q128A13EF840F
+ {NC, NC, 0}
+};
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h
index 9b3aa0b3f9a..85d6d2667b0 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h
@@ -44,6 +44,10 @@ struct trng_s {
RNG_HandleTypeDef handle;
};
+struct qspi_s {
+ QSPI_HandleTypeDef handle;
+};
+
#include "common_objects.h"
#ifdef __cplusplus
diff --git a/targets/targets.json b/targets/targets.json
index e1d5e51ad64..840d96bf33c 100755
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -1216,7 +1216,7 @@
},
"detect_code": ["0743"],
"macros_add": ["USB_STM_HAL", "USBHOST_OTHER"],
- "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"],
+ "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH", "QSPI"],
"release_versions": ["2", "5"],
"device_name": "STM32F413ZH"
},
From c727e5c6b24beb185243e5c91ba12162c7900d27 Mon Sep 17 00:00:00 2001
From: adustm
Date: Mon, 9 Apr 2018 17:20:53 +0200
Subject: [PATCH 53/61] Support maximum flash size : 4Gbytes
---
targets/TARGET_STM/qspi_api.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c
index 1b1c6af9f90..2069e7805c6 100644
--- a/targets/TARGET_STM/qspi_api.c
+++ b/targets/TARGET_STM/qspi_api.c
@@ -34,7 +34,9 @@
#include "pinmap.h"
#include "PeripheralPins.h"
-#define QSPI_FLASH_SIZE_DEFAULT 0x800000
+/* Max amount of flash size is 4Gbytes */
+/* hence 2^(31+1), then FLASH_SIZE_DEFAULT = 31<<20 */
+#define QSPI_FLASH_SIZE_DEFAULT 0x1F00000
void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st_command)
{
From e2b5c2791333183c72ee61c8f3430beeb27bd53e Mon Sep 17 00:00:00 2001
From: adustm
Date: Tue, 10 Apr 2018 11:41:49 +0200
Subject: [PATCH 54/61] Add MBED_WEAK for pins
---
.../TARGET_DISCO_F469NI/PeripheralPins.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
index 81fbb3f231b..1e2970c0963 100644
--- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c
@@ -390,21 +390,20 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = {
};
-const PinMap PinMap_QSPI_DATA[] = {
+MBED_WEAK const PinMap PinMap_QSPI_DATA[] = {
{PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
{PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
- {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
+ {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
{PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
-
{NC, NC, 0}
};
-const PinMap PinMap_QSPI_SCLK[] = {
+MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = {
{PF_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)},
{NC, NC, 0}
};
-const PinMap PinMap_QSPI_SSEL[] = {
+MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = {
{PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)},
{NC, NC, 0}
};
From e0b7afb6b8eb4aade5fa17ef3073c3bb0ba18404 Mon Sep 17 00:00:00 2001
From: adustm
Date: Tue, 10 Apr 2018 17:18:40 +0200
Subject: [PATCH 55/61] Enable QSPI for DISCO_F746NG
---
.../TARGET_DISCO_F746NG/PeripheralNames.h | 4 ++
.../TARGET_DISCO_F746NG/PeripheralPins.c | 37 +++++++++++++++++++
.../TARGET_STM32F746xG/objects.h | 4 ++
targets/targets.json | 2 +-
4 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h
index 0c00d43bf56..771553bb535 100644
--- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h
+++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h
@@ -93,6 +93,10 @@ typedef enum {
CAN_2 = (int)CAN2_BASE
} CANName;
+typedef enum {
+ QSPI_1 = (int)QSPI_R_BASE,
+} QSPIName;
+
#ifdef __cplusplus
}
#endif
diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c
index 6c9c3bec71e..e5420655109 100644
--- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c
@@ -406,3 +406,40 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = {
{PH_13, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to DCMI_PWR_EN
{NC, NC, 0}
};
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA[] = {
+// {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+// {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+// {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+// {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+// {PC_11, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+ {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // IO0 connected to N25Q128
+ {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // IO1 connected to N25Q128
+ {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // IO3 connected to N25Q128
+ {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // IO2 connected to N25Q128
+// {PE_7, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+// {PE_8, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+// {PE_9, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+// {PE_10, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // IO3 connected to pin A5
+ {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // IO2 connected to pin A4
+ {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO0 connected to pin A3
+ {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO1 connected to pin A2
+// {PG_9, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+// {PG_14, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+// {PH_2, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+// {PH_3, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = {
+ {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // connected to N25Q128 flash
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = {
+ {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // connected to N25Q128 flash
+// {PC_11, QSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},
+ {NC, NC, 0}
+};
+
diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h
index 28946911189..9ccc1c28d4c 100644
--- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h
+++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h
@@ -58,6 +58,10 @@ struct trng_s {
RNG_HandleTypeDef handle;
};
+struct qspi_s {
+ QSPI_HandleTypeDef handle;
+};
+
#include "common_objects.h"
#ifdef __cplusplus
diff --git a/targets/targets.json b/targets/targets.json
index 840d96bf33c..87d2aa57af2 100755
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -1956,7 +1956,7 @@
},
"detect_code": ["0815"],
"macros_add": ["USB_STM_HAL", "USBHOST_OTHER"],
- "device_has_add": ["LPTICKER", "ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH"],
+ "device_has_add": ["LPTICKER", "ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH", "QSPI"],
"release_versions": ["2", "5"],
"device_name": "STM32F746NG",
"overrides": {
From 9b466ca7baf81d08852fd062c6725188c28d5191 Mon Sep 17 00:00:00 2001
From: adustm
Date: Tue, 10 Apr 2018 18:42:35 +0200
Subject: [PATCH 56/61] Add support for QSPI on DISCO_L476VG
---
.../TARGET_DISCO_L476VG/PeripheralNames.h | 4 +++
.../TARGET_DISCO_L476VG/PeripheralPins.c | 26 +++++++++++++++++++
.../TARGET_STM32L476xG/objects.h | 4 +++
targets/targets.json | 2 +-
4 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h
index bc8f43ffa84..553aab47cf0 100644
--- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h
+++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h
@@ -83,6 +83,10 @@ typedef enum {
CAN_1 = (int)CAN1_BASE
} CANName;
+typedef enum {
+ QSPI_1 = (int)QSPI_R_BASE,
+} QSPIName;
+
#ifdef __cplusplus
}
#endif
diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c
index 1207a190951..bafe58975e8 100644
--- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c
+++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c
@@ -340,3 +340,29 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = {
{PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to MEMS_SCK [L3GD20_SCL/SPC]
{NC, NC, 0}
};
+
+//*** QUADSPI ***
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA[] = {
+ {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO3 not connected
+ {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO2 not connected
+ {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO1 not connected
+ {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO0 not connected
+ {PE_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO0 connected to N25Q128
+ {PE_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO1 connected to N25Q128
+ {PE_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO2 connected to N25Q128
+ {PE_15, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // IO3 connected to N25Q128
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = {
+// {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // connected to N25Q128
+ {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = {
+// {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},
+ {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // connected to N25Q128
+ {NC, NC, 0}
+};
diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h
index ece5f1679fa..95148ef88d0 100644
--- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h
+++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h
@@ -58,6 +58,10 @@ struct trng_s {
RNG_HandleTypeDef handle;
};
+struct qspi_s {
+ QSPI_HandleTypeDef handle;
+};
+
#include "common_objects.h"
#ifdef __cplusplus
diff --git a/targets/targets.json b/targets/targets.json
index 87d2aa57af2..52571aa9438 100755
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -2032,7 +2032,7 @@
},
"detect_code": ["0820"],
"macros_add": ["USBHOST_OTHER"],
- "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"],
+ "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH", "QSPI"],
"release_versions": ["2", "5"],
"device_name": "STM32L476VG",
"bootloader_supported": true
From 629eacd3c89f6b3a7f4f45193ae3950d5d42f442 Mon Sep 17 00:00:00 2001
From: Martin Kojtal
Date: Tue, 24 Apr 2018 12:11:43 +0100
Subject: [PATCH 57/61] QSPI: add doxygen options
---
doxyfile_options | 1 +
doxygen_options.json | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/doxyfile_options b/doxyfile_options
index fb8d1f7bca6..b3d9e2bfea6 100644
--- a/doxyfile_options
+++ b/doxyfile_options
@@ -2093,6 +2093,7 @@ PREDEFINED = DOXYGEN_ONLY \
DEVICE_SPI \
DEVICE_SPI_ASYNCH \
DEVICE_SPISLAVE \
+ DEVICE_QSPI \
DEVICE_STORAGE \
"MBED_DEPRECATED_SINCE(d, m)=" \
"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=" \
diff --git a/doxygen_options.json b/doxygen_options.json
index 6884a64883c..971748f3338 100644
--- a/doxygen_options.json
+++ b/doxygen_options.json
@@ -6,7 +6,7 @@
"SEARCH_INCLUDES": "YES",
"INCLUDE_PATH": "",
"INCLUDE_FILE_PATTERNS": "",
- "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
+ "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
"EXPAND_AS_DEFINED": "",
"SKIP_FUNCTION_MACROS": "NO",
"STRIP_CODE_COMMENTS": "NO",
From 64b289c9fe62820ee276dc55c2489df245dd73c6 Mon Sep 17 00:00:00 2001
From: Martin Kojtal
Date: Tue, 24 Apr 2018 13:26:12 +0100
Subject: [PATCH 58/61] QSPI: fix doxy hal documentation
---
hal/qspi_api.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hal/qspi_api.h b/hal/qspi_api.h
index 144f4f43d42..10bd77130be 100644
--- a/hal/qspi_api.h
+++ b/hal/qspi_api.h
@@ -160,9 +160,9 @@ qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void
* @param obj QSPI object
* @param command QSPI command
* @param tx_data TX buffer
- * @param tx_length TX buffer length in bytes
+ * @param tx_size TX buffer length in bytes
* @param rx_data RX buffer
- * @param rx_length RX buffer length in bytes
+ * @param rx_size RX buffer length in bytes
* @return QSPI_STATUS_OK if the data has been succesfully sent
QSPI_STATUS_INVALID_PARAMETER if invalid parameter found
QSPI_STATUS_ERROR otherwise
From 1eb51cf53aef9b58e86f7b46ecf806c60369413f Mon Sep 17 00:00:00 2001
From: Maciej Bocianski
Date: Fri, 22 Jun 2018 11:29:56 +0200
Subject: [PATCH 59/61] fix qspi command transfer for NORDIC
Add address unpacking support.
Only used in erase commands
---
targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c | 26 +++++++++++++------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
index 849970a0936..317cb029df8 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
+++ b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c
@@ -241,7 +241,6 @@ qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data,
qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size)
{
ret_code_t ret_code;
- uint32_t i;
uint8_t data[8];
uint32_t data_size = tx_size + rx_size;
@@ -252,24 +251,35 @@ qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command,
qspi_cinstr_config.wipwait = false;
qspi_cinstr_config.wren = false;
- if (data_size < 9) {
+ if(!command->address.disabled && data_size == 0) {
+ // erase command with address
+ if (command->address.size == QSPI_CFG_ADDR_SIZE_24) {
+ qspi_cinstr_config.length = NRF_QSPI_CINSTR_LEN_4B;
+ } else if (command->address.size == QSPI_CFG_ADDR_SIZE_32) {
+ qspi_cinstr_config.length = NRF_QSPI_CINSTR_LEN_5B;
+ } else {
+ return QSPI_STATUS_INVALID_PARAMETER;
+ }
+ for (uint32_t i = 0; i < (uint32_t)qspi_cinstr_config.length - 1; ++i) {
+ data[i] = ((uint8_t *)&command->address.value)[i];
+ }
+ } else if (data_size < 9) {
qspi_cinstr_config.length = (nrf_qspi_cinstr_len_t)(NRF_QSPI_CINSTR_LEN_1B + data_size);
+ // preparing data to send
+ for (uint32_t i = 0; i < tx_size; ++i) {
+ data[i] = ((uint8_t *)tx_data)[i];
+ }
} else {
return QSPI_STATUS_ERROR;
}
- // preparing data to send
- for (i = 0; i < tx_size; ++i) {
- data[i] = ((uint8_t *)tx_data)[i];
- }
-
ret_code = nrf_drv_qspi_cinstr_xfer(&qspi_cinstr_config, data, data);
if (ret_code != NRF_SUCCESS) {
return QSPI_STATUS_ERROR;
}
// preparing received data
- for (i = 0; i < rx_size; ++i) {
+ for (uint32_t i = 0; i < rx_size; ++i) {
// Data is sending as a normal SPI transmission so there is one buffer to send and receive data.
((uint8_t *)rx_data)[i] = data[i];
}
From 1cd69e154b814270832dec81a6abf53c185a371d Mon Sep 17 00:00:00 2001
From: Offir Kochalsky
Date: Tue, 10 Jul 2018 11:56:34 +0300
Subject: [PATCH 60/61] QSPIF SFDP Block Device
---
features/filesystem/bd/QSPIFBlockDevice.cpp | 1297 +++++++++++++++++++
features/filesystem/bd/QSPIFBlockDevice.h | 225 ++++
2 files changed, 1522 insertions(+)
create mode 100755 features/filesystem/bd/QSPIFBlockDevice.cpp
create mode 100755 features/filesystem/bd/QSPIFBlockDevice.h
diff --git a/features/filesystem/bd/QSPIFBlockDevice.cpp b/features/filesystem/bd/QSPIFBlockDevice.cpp
new file mode 100755
index 00000000000..105cb684126
--- /dev/null
+++ b/features/filesystem/bd/QSPIFBlockDevice.cpp
@@ -0,0 +1,1297 @@
+
+/* 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.
+ */
+
+//#include "./mbed-os/drivers/qspi.h"
+
+#define DEVICE_QSPI 1
+
+#include "QSPIFBlockDevice.h"
+
+/* Default QSPIF Parameters */
+/****************************/
+#define QSPIF_DEFAULT_READ_SIZE 1
+#define QSPIF_DEFAULT_PROG_SIZE 1
+#define QSPIF_DEFAULT_SE_SIZE 4096
+#define QSPI_MAX_STATUS_REGISTER_SIZE 2
+#define QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC 50
+#define QSPIF_DEFAULT_TIMEOUT_MSEC 1
+
+
+/* SFDP Header Parsing */
+/***********************/
+#define QSPIF_SFDP_HEADER_SIZE 8
+#define QSPIF_PARAM_HEADER_SIZE 8
+
+/* Basic Parameters Table Parsing */
+/**********************************/
+#define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */
+//READ Instruction support according to BUS Configuration
+#define QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2
+#define QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE 16
+#define QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE 27
+#define QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE 9
+#define QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE 11
+#define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
+#define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
+#define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
+#define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
+// Quad Enable Params
+#define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58
+#define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56
+// Erase Types Params
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34
+#define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
+
+// Debug Printouts
+#define QSPIF_DEBUG_ERROR 1
+#define QSPIF_DEBUG_WARNING 2
+#define QSPIF_DEBUG_INFO 3
+#define QSPIF_DEBUG_DEBUG 4
+#define QSPIF_DEBUG_TRACE 5
+#define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_INFO
+
+
+
+enum qspif_default_instructions {
+ QSPIF_NOP = 0x00, // No operation
+ QSPIF_PP = 0x02, // Page Program data
+ QSPIF_READ = 0x03, // Read data
+ QSPIF_SE = 0x20, // 4KB Sector Erase
+ QSPIF_SFDP = 0x5a, // Read SFDP
+
+ QSPIF_WRSR = 0x01, // Write Status/Configuration Register
+ QSPIF_WRDI = 0x04, // Write Disable
+ QSPIF_RDSR = 0x05, // Read Status Register
+ QSPIF_WREN = 0x06, // Write Enable
+
+ QSPIF_RSTEN = 0x66, // Reset Enable
+ QSPIF_RST = 0x99, // Reset
+ QSPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID
+};
+
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+#define QSPIF_LOG(level,...) {\
+ if (level <= QSPIF_DEFAULT_DEBUG_LEVEL) {\
+ char str[100];\
+ sprintf(str, "\n[%s][%s:%d], ", __FILENAME__, __FUNCTION__, __LINE__);\
+ sprintf(str+strlen(str),__VA_ARGS__);\
+ printf(str);\
+ }\
+ }
+
+// Mutex is used for some QSPI Driver commands that must be done sequentially with no other commands in between
+// e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
+SingletonPtr QSPIFBlockDevice::_mutex;
+
+
+/********* Public API Functions *********/
+/****************************************/
+
+QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, int clock_mode, int freq)
+ : _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _deviceSizeBytes(0)
+{
+ //_cs = 1;
+ is_initialized = false;
+ _minCommonEraseSize = 0;
+ _regions_count = 1;
+ _region_erase_types[0] = 0;
+
+ //Default Bus Setup 1_1_1 with 0 dummy and mode cycles
+ _inst_width = QSPI_CFG_BUS_SINGLE;
+ _address_width = QSPI_CFG_BUS_SINGLE;
+ _address_size = QSPI_CFG_ADDR_SIZE_24;
+ _alt_width = QSPI_CFG_BUS_SINGLE;
+ _alt_size = QSPI_CFG_ALT_SIZE_8;
+ _data_width = QSPI_CFG_BUS_SINGLE;
+ _dummy_and_mode_cycles = 0;
+
+ if (QSPI_STATUS_OK != _qspiSetFrequency(freq))
+ {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Set Frequency Failed");
+ }
+}
+
+
+int QSPIFBlockDevice::init()
+{
+
+ uint8_t vendor_device_ids[4];
+ size_t data_length = 3;
+
+ _mutex->lock();
+ if (is_initialized == true)
+ {
+ _mutex->unlock();
+ return 0;
+ }
+
+ // Soft Reset
+ if( -1 == _resetFlashMem()) {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
+ return -1;
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
+ }
+
+
+
+ /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
+ int status = _qspiSendReadCommand(QSPIF_RDID, (char *)vendor_device_ids, 0x0 /*address*/, data_length);
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read Vendor ID Failed");
+ return status;
+ }
+
+ switch (vendor_device_ids[0]) {
+ case 0xbf:
+ // SST devices come preset with block protection
+ // enabled for some regions, issue write disable instruction to clear
+ _setWriteEnable();
+ //_cmdwrite(0x98, 0, 0, 0x0, NULL);
+ _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
+
+ break;
+ }
+
+ //Synchronize Device
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - _isMemReady Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
+
+
+ /**************************** Parse SFDP Header ***********************************/
+ uint32_t basic_table_addr = NULL;
+ size_t basic_table_size = 0;
+ uint32_t sector_map_table_addr = NULL;
+ size_t sector_map_table_size = 0;
+ if ( 0 != _sfdpParseSFDPHeaders(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse SFDP Headers Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
+
+
+ /**************************** Parse Basic Parameters Table ***********************************/
+ if ( 0 != _sfdpParseBasicParamTable(basic_table_addr, basic_table_size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse Basic Param Table Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
+
+
+ /**************************** Parse Sector Map Table ***********************************/
+ _region_size_bytes[0] = _deviceSizeBytes; // If there's no region map, we have a single region sized the entire device size
+ _region_high_boundary[0] = _deviceSizeBytes - 1;
+
+ if ( (sector_map_table_addr != NULL) && (0 != sector_map_table_size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Parsing Sector Map Table - addr: 0x%xh, Size: %d", sector_map_table_addr, sector_map_table_size);
+ if ( 0 != _sfdpParseSectorMapTable(sector_map_table_addr, sector_map_table_size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse Sector Map Table Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
+ }
+
+
+ // Configure BUS Mode to 1_1_1 for all commands other than Read
+ _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
+ /*// Soft Reset
+ if( -1 == _resetFlashMem()) {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
+ return -1;
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
+ }*/
+
+ is_initialized = true;
+ _mutex->unlock();
+
+ return 0;
+}
+
+int QSPIFBlockDevice::deinit()
+{
+ _mutex->lock();
+ if (is_initialized == false)
+ {
+ _mutex->unlock();
+ return 0;
+ }
+ qspi_status_t status = _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
+ int result = 0;
+
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Disable failed");
+ result = -1;
+ }
+ is_initialized = false;
+ _mutex->unlock();
+
+ return result;
+}
+
+
+int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
+{
+
+
+ int status = 0;
+
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO Inst: 0x%xh", _readInstruction);
+
+ _mutex->lock();
+
+ _qspiConfiureFormat(
+ _inst_width, //Bus width for Instruction phase
+ _address_width, //Bus width for Address phase
+ _address_size,
+ _alt_width, //Bus width for Alt phase
+ _alt_size,
+ _data_width, //Bus width for Data phase
+ _dummy_and_mode_cycles);
+ //_qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
+
+ if (QSPI_STATUS_OK != _qspiSendReadCommand(_readInstruction, buffer, addr, size)) {
+ status = -1;
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Read failed\n");
+ }
+
+ // All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus)
+ _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
+
+ _mutex->unlock();
+ return status;
+
+}
+
+
+
+
+int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
+{
+ qspi_status_t result = QSPI_STATUS_OK;
+ bool program_failed = false;
+ int status = 0;
+ uint32_t offset = 0;
+ uint32_t chunk = 0;
+ bd_size_t writtenBytes = 0;
+
+ while (size > 0) {
+
+ // Write on _pageSizeBytes boundaries (Default 256 bytes a page)
+ offset = addr % _pageSizeBytes;
+ chunk = (offset + size < _pageSizeBytes) ? size : (_pageSizeBytes);
+ writtenBytes = chunk;
+
+ _mutex->lock();
+
+ //Send WREN
+ if (_setWriteEnable() != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Enabe failed\n");
+ program_failed = true;
+ goto Exit_Point;
+ }
+
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready, write failed\n");
+ program_failed = true;
+ goto Exit_Point;
+ }
+
+ result = _qspiSendProgramCommand(_progInstruction, buffer, addr, &writtenBytes);
+ if( (result != QSPI_STATUS_OK) || (chunk != writtenBytes) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write failed");
+ program_failed = true;
+ goto Exit_Point;
+ }
+
+ buffer = static_cast(buffer) + chunk;
+ addr += chunk;
+ size -= chunk;
+
+ wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
+
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready after write, failed\n");
+ program_failed = true;
+ goto Exit_Point;
+ }
+ _mutex->unlock();
+
+
+ }
+
+ Exit_Point:
+ if (program_failed) {
+ _mutex->unlock();
+ status = -1;
+ }
+
+ return status;
+}
+
+
+int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t inSize)
+{
+
+ int type = 0;
+ uint32_t chunk = 4096;
+ unsigned int curEraseInst = _eraseInstruction;
+ int size = (int)inSize;
+ bool erase_failed = false;
+ int status = 0;
+ // Find region of erased address
+ int region = _utilsFindAddrRegion((int)addr);
+ // Erase Types of selected region
+ uint8_t bitfield = _region_erase_types[region];
+
+
+ while (size > 0) {
+
+ // iterate to find next Largest erase type (1) supported by region, 2) smaller than size)
+ // find the matching instruction and erase size chunk for that type.
+ type = _utilsIterateNextLargestEraseType(bitfield, (int)size, (int)addr, _region_high_boundary[region]);
+ curEraseInst = _eraseTypeInstArr[type];
+ chunk = _eraseTypeSizeArr[type];
+
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG," Debug: addr: 0x%xh, size:%d, Inst: 0x%xh, chunk: %d , ",
+ (int)addr, (int)size, curEraseInst, chunk);
+
+ _mutex->lock();
+
+ if (_setWriteEnable() != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase - Write Enable failed");
+ erase_failed = true;
+ goto Exit_Point;
+ }
+
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase Device not ready - failed");
+ erase_failed = true;
+ goto Exit_Point;
+ }
+
+ if (QSPI_STATUS_OK != _qspiSendEraseCommand(curEraseInst, addr, size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase command failed!");
+ erase_failed = true;
+ goto Exit_Point;
+ }
+
+ addr += chunk;
+ size -= chunk;
+
+ if ( (size > 0) && (addr > _region_high_boundary[region]) ) {
+ // erase crossed to next region
+ region++;
+ bitfield = _region_erase_types[region];
+ }
+ wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI After Erase Device not ready - failed\n");
+ erase_failed = true;
+ goto Exit_Point;
+ }
+ _mutex->unlock();
+
+ }
+
+
+Exit_Point:
+ if (erase_failed) {
+ _mutex->unlock();
+ status = -1;
+ }
+
+ return status;
+}
+
+
+
+bd_size_t QSPIFBlockDevice::get_read_size() const
+{
+ return QSPIF_DEFAULT_READ_SIZE;
+}
+
+bd_size_t QSPIFBlockDevice::get_program_size() const
+{
+ return QSPIF_DEFAULT_PROG_SIZE;
+}
+
+bd_size_t QSPIFBlockDevice::get_erase_size() const
+{
+ return _minCommonEraseSize;
+}
+
+
+// Find minimal erase size supported by address region
+bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
+{
+ // Find region of current address
+ int region = _utilsFindAddrRegion((int)addr);
+
+ int minRegionEraseSize = _minCommonEraseSize;
+ int8_t type_mask = 0x01;
+ int i_ind = 0;
+
+ if (region != -1) {
+ type_mask = 0x01;
+
+ for (i_ind = 0; i_ind < 4; i_ind++) {
+ // loop through erase types supported by region
+ if (_region_erase_types[region] & type_mask) {
+
+ minRegionEraseSize = _eraseTypeSizeArr[i_ind];
+ break;
+ }
+ type_mask = type_mask << 1;
+ }
+
+ if (i_ind == 4) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: no erase type was found for region addr");
+ }
+ }
+
+ return (bd_size_t)minRegionEraseSize;
+
+}
+
+bd_size_t QSPIFBlockDevice::size() const
+{
+ return _deviceSizeBytes;
+}
+
+
+/*********************************************************/
+/********** SFDP Parsing and Detection Functions *********/
+/*********************************************************/
+
+int QSPIFBlockDevice::_sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size)
+{
+ uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
+ uint32_t tmpRegionSize = 0;
+ int i_ind = 0;
+ int prevBoundary = 0;
+ // Default set to all type bits 1-4 are common
+ _minCommonEraseType = 0x0F;
+
+ qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/, sector_map_table_size);
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP First Table Failed");
+ return -1;
+ }
+
+ //QSPIF_LOG(QSPIF_DEBUG_DEBUG,\nDEBUG: "Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",sector_map_table[0],
+ // sector_map_table[1],
+ // sector_map_table[2],
+ // sector_map_table[3],
+ // sector_map_table[4],
+ // sector_map_table[5],
+ // sector_map_table[6],
+ // sector_map_table[7], sector_map_table[56], sector_map_table[57], sector_map_table[58], sector_map_table[59], sector_map_table[52]);
+
+ // Currently we support only Single Map Descriptor
+ if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
+ return -1;
+ }
+
+ _regions_count = sector_map_table[2] + 1;
+ if (_regions_count > QSPIF_MAX_REGIONS) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Supporting up to %d regions, current setup to %d regions - fail", QSPIF_MAX_REGIONS, _regions_count);
+ return -1;
+ }
+
+ // Loop through Regions and set for each one: size, supported erase types, high boundary offset
+ // Calculate minimum Common Erase Type for all Regions
+ for (i_ind = 0; i_ind < _regions_count; i_ind++) {
+ tmpRegionSize = ((*((uint32_t *)§or_map_table[(i_ind+1)*4])) >> 8) & 0x00FFFFFF; // bits 9-32
+ _region_size_bytes[i_ind] = (tmpRegionSize +1) * 256; // Region size is 0 based multiple of 256 bytes;
+ _region_erase_types[i_ind] = sector_map_table[(i_ind+1)*4] & 0x0F; // bits 1-4
+ _minCommonEraseType &= _region_erase_types[i_ind];
+ _region_high_boundary[i_ind] = (_region_size_bytes[i_ind]-1) + prevBoundary;
+ prevBoundary = _region_high_boundary[i_ind]+1;
+ }
+
+ // Calc minimum Common Erase Size from _minCommonEraseType
+ uint8_t type_mask = 0x01;
+ for (i_ind = 0; i_ind < 4; i_ind++) {
+ if (_minCommonEraseType & type_mask) {
+ _minCommonEraseType = i_ind;
+ _minCommonEraseSize = _eraseTypeSizeArr[i_ind];
+ break;
+ }
+ type_mask = type_mask << 1;
+ }
+
+ if (i_ind == 4) {
+ // No common erase type was found between regions
+ _minCommonEraseType = 0;
+ _minCommonEraseSize = -1;
+ }
+
+ return 0;
+}
+
+
+int QSPIFBlockDevice::_sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size)
+{
+ uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
+
+ qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/, basic_table_size);
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP First Table Failed");
+ return -1;
+ }
+
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",param_table[0],
+ param_table[1],
+ param_table[2],
+ param_table[3],
+ param_table[4],
+ param_table[5],
+ param_table[6],
+ param_table[7], param_table[56], param_table[57], param_table[58], param_table[59], param_table[52]);
+
+
+ // Check address size, currently only supports 3byte addresses
+ if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - verify 3byte addressing Failed");
+ return -1;
+ }
+
+ // Get device density (stored in bits - 1)
+ uint32_t density_bits = (
+ (param_table[7] << 24) |
+ (param_table[6] << 16) |
+ (param_table[5] << 8 ) |
+ param_table[4] );
+ _deviceSizeBytes = (density_bits + 1) / 8;
+
+ // Set Default read/program/erase Instructions
+ _readInstruction = QSPIF_READ;
+ _progInstruction = QSPIF_PP;
+ _eraseInstruction = QSPIF_SE;
+
+ // Set Page Size (QSPI write must be done on Page limits)
+ _pageSizeBytes = _sfdpDetectPageSize(param_table);
+
+ // Detect and Set Erase Types
+ bool shouldSetQuadEnable = false;
+ bool isQPIMode = false;
+ _sfdpDetectEraseTypesInstAndSize(param_table, _erase4KInst, _eraseTypeInstArr, _eraseTypeSizeArr);
+ _eraseInstruction = _erase4KInst;
+
+
+ // Detect and Set fastest Bus mode (default 1-1-1)
+ _sfdpDetectBestBusReadMode(param_table, shouldSetQuadEnable, isQPIMode, _readInstruction);
+
+ if (true == shouldSetQuadEnable) {
+ // Set Quad Enable and QPI Bus modes if Supported
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Setting Quad Enable");
+ _sfdpSetQuadEnabled(param_table);
+ if (true == isQPIMode) {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Setting QPI mode");
+ _sfdpSetQPIEnabled(param_table);
+ }
+ }
+ return 0;
+}
+
+int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t &basic_table_addr, size_t &basic_table_size,
+ uint32_t §or_map_table_addr, size_t §or_map_table_size)
+{
+ uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE];
+ uint8_t param_header[QSPIF_PARAM_HEADER_SIZE];
+ size_t data_length = QSPIF_SFDP_HEADER_SIZE;
+ bd_addr_t addr = 0x0;
+
+ // Set 1-1-1 bus mode for SFDP header parsing
+ _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
+
+ qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length);
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP Failed");
+ return -1;
+ }
+
+
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG11: Read SFDP Header: %x %x %x %x %x %x %x %x\n",sfdp_header[0],
+ sfdp_header[1],
+ sfdp_header[2],
+ sfdp_header[3],
+ sfdp_header[4],
+ sfdp_header[5],
+ sfdp_header[6],
+ sfdp_header[7]);
+
+
+ // Verify SFDP signature for sanity
+ // Also check that major/minor version is acceptable
+ if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - _verify SFDP signature and version Failed");
+ return -1;
+ }
+ else
+ {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - verified SFDP Signature and version Successfully");
+ }
+
+ // Discover Number of Parameter Headers
+ int number_of_param_headers = (int)(sfdp_header[6]) + 1;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: number of Param Headers: %d", number_of_param_headers);
+
+
+ addr += QSPIF_SFDP_HEADER_SIZE;
+ data_length = QSPIF_PARAM_HEADER_SIZE;
+
+ // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table)
+ for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
+
+ status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_header, addr, data_length);
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read Param Table %d Failed", i_ind+1);
+ return -1;
+ }
+ // The SFDP spec indicates the standard table is always at offset 0
+ // in the parameter headers, we check just to be safe
+ if (param_header[2] != 1) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Param Table %d - Major Version should be 1!", i_ind+1);
+ return -1;
+ }
+
+ if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
+ // Found Basic Params Table: LSB=0x00, MSB=0xFF
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Found Basic Param Table at Table: %d", i_ind+1);
+ basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
+ // Supporting up to 64 Bytes Table (16 DWORDS)
+ basic_table_size = ((param_header[3]*4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[11]*4) : 64;
+
+ }
+ else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
+ // Found Sector Map Table: LSB=0x81, MSB=0xFF
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Found Sector Map Table at Table: %d", i_ind+1);
+ sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
+
+ sector_map_table_size = param_header[3] * 4;
+
+ }
+ addr += QSPIF_PARAM_HEADER_SIZE;
+
+ }
+ return 0;
+}
+
+
+
+int QSPIFBlockDevice::_sfdpSetQPIEnabled(uint8_t *basicParamTablePtr)
+{
+ uint8_t config_reg[1];
+
+ // QPI 4-4-4 Enable Procedure is specified in 5 Bits
+ uint8_t en_seq_444_value = ( ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE+1] & 0x01) << 4 ));
+
+ switch (en_seq_444_value) {
+ case 1:
+ case 2:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - send command 38h");
+ /*if (_setWriteEnable() != 0) {
+ printf("ERROR: Write Enabe failed\n");
+ return -1;
+ }
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready, write failed\n");
+ return -1;
+ }*/
+
+ _qspiSendGeneralCommand(0x38, -1, NULL, 0, NULL, 0);
+ /*wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready after write, failed\n");
+ return -1;
+ }*/
+
+
+ break;
+
+ case 4:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - send command 35h");
+ _qspiSendGeneralCommand(0x35, -1, NULL, 0, NULL, 0);
+ break;
+
+ case 8:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - set config bit 6 and send command 71h");
+ _qspiSendGeneralCommand(0x65, 0x800003, NULL, 0, (char *)config_reg, 1);
+ config_reg[1] |= 0x40; //Set Bit 6
+ _qspiSendGeneralCommand(0x71, 0x800003, NULL, 0, (char *)config_reg, 1);
+ break;
+
+ case 16:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - reset config bits 0-7 and send command 61h");
+ _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
+ config_reg[1] &= 0x7F; //Reset Bit 7 of CR
+
+
+
+
+ /*
+ if (_setWriteEnable() != 0) {
+ printf("ERROR: Write Enabe failed\n");
+ return -1;
+ }
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready, write failed\n");
+ return -1;
+ }*/
+
+ _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
+
+
+ /* wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready after write, failed\n");
+ return -1;
+ }
+
+
+
+ _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
+
+ if (_setWriteEnable() != 0) {
+ printf("ERROR: Write Enabe failed\n");
+ return -1;
+ }
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready, write failed\n");
+ return -1;
+ }
+ config_reg[1] = 0x00; //Reset Bits 0-7
+ _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
+ wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);*/
+ /* if( false == _isMemReady()) {
+ printf("ERROR: Device not ready after write, failed\n");
+ return -1;
+ }*/
+
+ break;
+
+ default:
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _setQPIEnabled - Unsuported En Seq 444 configuration");
+ break;
+
+
+ }
+
+ return 0;
+}
+
+
+
+int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr)
+{
+
+ int sr_read_size = QSPI_MAX_STATUS_REGISTER_SIZE;
+ int sr_write_size = QSPI_MAX_STATUS_REGISTER_SIZE;
+
+ int status_reg_setup[QSPI_MAX_STATUS_REGISTER_SIZE];
+ uint8_t status_reg[QSPI_MAX_STATUS_REGISTER_SIZE];
+ unsigned int writeRegisterInst = QSPIF_WRSR;
+ unsigned int readRegisterInst = QSPIF_RDSR;
+
+ uint8_t qer_value = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4;
+
+
+
+ switch (qer_value) {
+ case 0:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Device Does not Have a QE Bit, continue based on Read Inst");
+ return 0;
+
+ case 1:
+ case 4:
+ status_reg_setup[0] = 0;
+ status_reg_setup[1] = 0x02;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 1 of Status Reg 2");
+ break;
+
+ case 2:
+ status_reg_setup[0] = 0x40;
+ status_reg_setup[1] = 0;
+ sr_write_size = 1;
+ sr_read_size = 1;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 6 of Status Reg 1");
+ break;
+
+ case 3:
+ status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1
+ status_reg_setup[1] = 0;
+ sr_write_size = 1;
+ sr_read_size = 1;
+ writeRegisterInst = 0x3E;
+ readRegisterInst = 0x3F;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 7 of Status Reg 1");
+ break;
+ case 5:
+ status_reg_setup[0] = 0;
+ status_reg_setup[1] = 0x02;
+ readRegisterInst = 0x35;
+ sr_read_size = 1;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 1 of Status Reg 2 -special read command");
+ break;
+ default:
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _setQuadEnable - Unsuported QER configuration");
+ break;
+
+
+ }
+
+ // Read Status Register
+ if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, sr_read_size) ){ // store received values in status_value
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed");
+ return -1;
+ }
+
+ // Set Bits for Quad Enable
+ status_reg[0] |= status_reg_setup[0];
+ status_reg[1] |= status_reg_setup[1];
+
+
+ // Write new Status Register Setup
+ if (_setWriteEnable() != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Enabe failed\n");
+ return -1;
+ }
+
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready, write failed");
+ return -1;
+ }
+
+ if (QSPI_STATUS_OK == _qspiSendGeneralCommand(writeRegisterInst, -1, (char *)status_reg, sr_write_size, NULL, 0) ){ // Write QE to status_register
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQuadEnable - Writing Status Register Success: value = 0x%x", (int)status_reg[0]);
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: _setQuadEnable - Writing Status Register failed");
+ return -1;
+ }
+
+ wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready after write, failed");
+ return -1;
+ }
+
+
+ // For Debug
+ memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE);
+ if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, sr_read_size) ){ // store received values in status_value
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed");
+ return -1;
+ }
+
+
+ return 0;//((status_reg[0] & QSPI_STATUS_BIT_QE) != 0 ? 0 : -1);
+}
+
+
+int QSPIFBlockDevice::_sfdpDetectPageSize(uint8_t *basicParamTablePtr)
+{
+ int page2PowerSize = ( (int)basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
+ int pageSize = _utilsMathPower(2, page2PowerSize);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _detectPageSize - Page Size: %d", pageSize);
+ return pageSize;
+}
+
+
+
+int QSPIFBlockDevice::_sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int &erase4KInst, unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr)
+{
+ erase4KInst = 0xff;
+ bool found4KEraseType = false;
+ uint8_t bitfield = 0x01;
+
+ // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
+ erase4KInst = basicParamTablePtr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
+
+ // Loop Erase Types 1-4
+ for (int i_ind=0; i_ind < 4; i_ind++) {
+ eraseTypeInstArr[i_ind] = 0xff; //0xFF default for unsupported type
+ eraseTypeSizeArr[i_ind] = _utilsMathPower(2, basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE+2*i_ind]);
+ if (eraseTypeSizeArr[i_ind] > 1) {
+ // if size==1 type is not supported
+ eraseTypeInstArr[i_ind] = basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE+2*i_ind];
+
+ if ((eraseTypeSizeArr[i_ind] < _minCommonEraseSize) || (_minCommonEraseSize == 0) ) {
+ //Set default minimal common erase for singal region
+ _minCommonEraseSize = eraseTypeSizeArr[i_ind];
+ }
+
+ if (eraseTypeSizeArr[i_ind] == 4096) {
+ found4KEraseType = true;
+ if (erase4KInst != eraseTypeInstArr[i_ind]) {
+ //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
+ erase4KInst = eraseTypeInstArr[i_ind];
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
+
+ }
+ }
+ _region_erase_types[0] |= bitfield; // If there's no region map, set region "0" types as defualt;
+ }
+
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind+1), eraseTypeInstArr[i_ind], eraseTypeSizeArr[i_ind]);
+ bitfield = bitfield << 1;
+ }
+
+ if (false == found4KEraseType) {
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: Couldn't find Erase Type for 4KB size");
+ }
+ return 0;
+}
+
+
+int QSPIFBlockDevice::_sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool &setQuadEnable, bool &isQPIMode, unsigned int &readInst) {
+
+ bool isDone = false;
+
+ setQuadEnable = false;
+ isQPIMode = false;
+ int dummyCycles = 0;
+ uint8_t examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
+
+ do { // compound statement is the loop body
+
+
+
+ if (examinedByte & 0x10) {
+ // QPI 4-4-4 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE];
+ setQuadEnable = true;
+ isQPIMode = true;
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE-1] & 0x1F);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 4-4-4, Instruction: 0x%xh",_readInstruction);
+ //_inst_width = QSPI_CFG_BUS_QUAD;
+ _address_width = QSPI_CFG_BUS_QUAD;
+ _data_width = QSPI_CFG_BUS_QUAD;
+
+ break;
+ }
+
+
+ examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
+ if (examinedByte & 0x40) {
+ // Fast Read 1-4-4 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE];
+ setQuadEnable = true;
+ // dummy cycles + mode cycles = Dummy Cycles
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE-1] & 0x1F);
+ _address_width = QSPI_CFG_BUS_QUAD;
+ _data_width = QSPI_CFG_BUS_QUAD;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-4-4, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ if (examinedByte & 0x80) {
+ // Fast Read 1-1-4 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE];
+ setQuadEnable = true;
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE-1] & 0x1F);
+ _data_width = QSPI_CFG_BUS_QUAD;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-4, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
+ if (examinedByte & 0x01) {
+ // Fast Read 2-2-2 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE];
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE-1] & 0x1F);
+ _address_width = QSPI_CFG_BUS_DUAL;
+ _data_width = QSPI_CFG_BUS_DUAL;
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"/nINFO: Read Bus Mode set to 2-2-2, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+
+ examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
+ if (examinedByte & 0x20) {
+ // Fast Read 1-2-2 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE];
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE-1] & 0x1F);
+ _address_width = QSPI_CFG_BUS_DUAL;
+ _data_width = QSPI_CFG_BUS_DUAL;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ if (examinedByte & 0x01) {
+ // Fast Read 1-1-2 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE];
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE-1] & 0x1F);
+ _data_width = QSPI_CFG_BUS_DUAL;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh",_readInstruction);
+ isDone = true;
+ }
+ while (isDone == false);
+
+ return 0;
+}
+
+
+int QSPIFBlockDevice::_resetFlashMem()
+{
+ int status = 0;
+ char status_value[2] = {0};
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"INFO: _resetFlashMem:\n");
+ //Read the Status Register from device
+ if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, 1) ){ // store received values in status_value
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]);
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed\n");
+ status = -1;
+ }
+
+ if(0 == status)
+ {
+ //Send Reset Enable
+ if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RSTEN, -1, NULL, 0, NULL, 0) ) { // store received values in status_value
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Sending RSTEN Success\n");
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sending RSTEN failed\n");
+ status = -1;
+ }
+
+
+ if(0 == status)
+ {
+ //Send Reset
+ if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RST, -1, NULL, 0, NULL, 0)) { // store received values in status_value
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Sending RST Success\n");
+ } else {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sending RST failed\n");
+ status = -1;
+ }
+
+ _isMemReady();
+ }
+ }
+
+ return status;
+}
+
+
+bool QSPIFBlockDevice::_isMemReady()
+{
+ char status_value[2];
+ int retries = 0;
+ bool memReady = true;
+
+ do
+ {
+ retries++;
+ //Read the Status Register from device
+ if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, 2)) { // store received values in status_value
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed\n");
+ }
+ } while( (status_value[0] & 0x1) != 0 && retries <10000 );
+
+ if((status_value[0] & 0x1) != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"ERROR: _isMemReady FALSE\n");
+ memReady = false;
+ }
+ return memReady;
+}
+
+
+int QSPIFBlockDevice::_setWriteEnable()
+{
+ int status = 0;
+ if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_WREN, -1, NULL, 0, NULL, 0)) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR:Sending WREN command FAILED\n");
+ status = -1;
+ }
+ return status;
+}
+
+
+
+/*********************************************/
+/************* Utility Functions *************/
+/*********************************************/
+int QSPIFBlockDevice::_utilsMathPower(int base, int exp)
+{
+ int result = 1;
+ while(exp) {
+ result *= base;
+ exp--;
+ }
+ return result;
+}
+
+
+int QSPIFBlockDevice::_utilsFindAddrRegion(int offset)
+{
+ if ((offset > (int)_deviceSizeBytes) || (_regions_count == 0)){
+ return -1;
+ }
+
+ if (_regions_count == 1) {
+ return 0;
+ }
+
+ for (int i_ind = _regions_count-2; i_ind >= 0; i_ind--) {
+
+ if (offset > _region_high_boundary[i_ind]) {
+ return (i_ind+1);
+ }
+ }
+ return -1;
+
+}
+
+
+int QSPIFBlockDevice::_utilsIterateNextLargestEraseType(uint8_t &bitfield, int size, int offset, int boundry)
+{
+ uint8_t type_mask = 0x08;
+ int i_ind = 0;
+ int largestEraseType = 0;
+ for (i_ind = 3; i_ind >= 0; i_ind--) {
+ if (bitfield & type_mask) {
+ largestEraseType = i_ind;
+ if ( (size > _eraseTypeSizeArr[largestEraseType]) &&
+ ((boundry - offset) > _eraseTypeSizeArr[largestEraseType]) ) {
+ break;
+ }
+ else {
+ bitfield &= ~type_mask;
+ }
+ }
+ type_mask = type_mask >> 1;
+ }
+
+ if (i_ind == 4) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: no erase type was found for current region addr");
+ }
+ return largestEraseType;
+
+}
+
+
+/***************************************************/
+/*********** QSPI Driver API Functions *************/
+/***************************************************/
+
+qspi_status_t QSPIFBlockDevice::_qspiSetFrequency(int freq)
+{
+ return _qspi.set_frequency(freq);
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendReadCommand(unsigned int readInst, void *buffer, bd_addr_t addr, bd_size_t size)
+{
+ // Check the address and size fit onto the chip.
+
+ /* OFR_DBG */
+ //MBED_ASSERT(is_valid_read(addr, size));
+
+ size_t bufLen = size;
+
+ if(_qspi.read( readInst, -1, (unsigned int )addr, (char *)buffer, &bufLen) != QSPI_STATUS_OK ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Read failed");
+ return QSPI_STATUS_ERROR;
+ }
+
+ return QSPI_STATUS_OK;
+
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendProgramCommand(unsigned int progInst, const void *buffer, bd_addr_t addr, bd_size_t *size)
+{
+ // Check the address and size fit onto the chip.
+ //MBED_ASSERT(is_valid_program(addr, (*size)));
+ qspi_status_t result = QSPI_STATUS_OK;
+
+ result = _qspi.write( progInst, -1, addr/*(((unsigned int)addr) & 0x00FFFF00)*/, (char *)buffer, (size_t *)size);
+ if(result != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Write failed");
+ }
+
+ return result;
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendEraseCommand(unsigned int eraseInst, bd_addr_t addr, bd_size_t size)
+{
+ // Check the address and size fit onto the chip.
+ //MBED_ASSERT(is_valid_erase(addr, size));
+
+ qspi_status_t result = QSPI_STATUS_OK;
+
+ result = _qspi.command_transfer(eraseInst, // command to send
+ (((int)addr) & 0x00FFF000), // Align addr to 4096
+ NULL, // do not transmit
+ 0, // do not transmit
+ NULL, // just receive two bytes of data
+ 0); // store received values in status_value
+ if (QSPI_STATUS_OK != result) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase failed");
+ }
+
+ return result;
+
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendGeneralCommand(unsigned int instruction, bd_addr_t addr, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
+{
+
+
+ qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length);
+
+ if (QSPI_STATUS_OK != status) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR:Sending Generic command: %x", instruction);
+ }
+
+ return status;
+}
+
+
+qspi_status_t QSPIFBlockDevice::_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)
+{
+ _qspi.configure_format( inst_width, address_width, address_size, alt_width, alt_size, data_width, dummy_cycles);
+
+ return QSPI_STATUS_OK;
+}
+
+
+
+
+
diff --git a/features/filesystem/bd/QSPIFBlockDevice.h b/features/filesystem/bd/QSPIFBlockDevice.h
new file mode 100755
index 00000000000..2bcf8fab1a5
--- /dev/null
+++ b/features/filesystem/bd/QSPIFBlockDevice.h
@@ -0,0 +1,225 @@
+/* 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
+#include "BlockDevice.h"
+//#include "./mbed-os/drivers/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 §or_map_table_addr, size_t §or_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 _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
From 509025c31a719dffd852e8cb84f5349af39f59ed Mon Sep 17 00:00:00 2001
From: Offir Kochalsky
Date: Tue, 10 Jul 2018 12:05:03 +0300
Subject: [PATCH 61/61] tab to spaces
---
features/filesystem/bd/QSPIFBlockDevice.cpp | 1358 +++++++++----------
1 file changed, 679 insertions(+), 679 deletions(-)
diff --git a/features/filesystem/bd/QSPIFBlockDevice.cpp b/features/filesystem/bd/QSPIFBlockDevice.cpp
index 105cb684126..e69f4e5d9f9 100755
--- a/features/filesystem/bd/QSPIFBlockDevice.cpp
+++ b/features/filesystem/bd/QSPIFBlockDevice.cpp
@@ -64,11 +64,11 @@
#define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
// Debug Printouts
-#define QSPIF_DEBUG_ERROR 1
+#define QSPIF_DEBUG_ERROR 1
#define QSPIF_DEBUG_WARNING 2
-#define QSPIF_DEBUG_INFO 3
-#define QSPIF_DEBUG_DEBUG 4
-#define QSPIF_DEBUG_TRACE 5
+#define QSPIF_DEBUG_INFO 3
+#define QSPIF_DEBUG_DEBUG 4
+#define QSPIF_DEBUG_TRACE 5
#define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_INFO
@@ -76,29 +76,29 @@
enum qspif_default_instructions {
QSPIF_NOP = 0x00, // No operation
QSPIF_PP = 0x02, // Page Program data
- QSPIF_READ = 0x03, // Read data
+ QSPIF_READ = 0x03, // Read data
QSPIF_SE = 0x20, // 4KB Sector Erase
QSPIF_SFDP = 0x5a, // Read SFDP
- QSPIF_WRSR = 0x01, // Write Status/Configuration Register
+ QSPIF_WRSR = 0x01, // Write Status/Configuration Register
QSPIF_WRDI = 0x04, // Write Disable
- QSPIF_RDSR = 0x05, // Read Status Register
+ QSPIF_RDSR = 0x05, // Read Status Register
QSPIF_WREN = 0x06, // Write Enable
- QSPIF_RSTEN = 0x66, // Reset Enable
- QSPIF_RST = 0x99, // Reset
+ QSPIF_RSTEN = 0x66, // Reset Enable
+ QSPIF_RST = 0x99, // Reset
QSPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID
};
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#define QSPIF_LOG(level,...) {\
- if (level <= QSPIF_DEFAULT_DEBUG_LEVEL) {\
- char str[100];\
- sprintf(str, "\n[%s][%s:%d], ", __FILENAME__, __FUNCTION__, __LINE__);\
- sprintf(str+strlen(str),__VA_ARGS__);\
- printf(str);\
- }\
+ if (level <= QSPIF_DEFAULT_DEBUG_LEVEL) {\
+ char str[100];\
+ sprintf(str, "\n[%s][%s:%d], ", __FILENAME__, __FUNCTION__, __LINE__);\
+ sprintf(str+strlen(str),__VA_ARGS__);\
+ printf(str);\
+ }\
}
// Mutex is used for some QSPI Driver commands that must be done sequentially with no other commands in between
@@ -113,12 +113,12 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
: _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _deviceSizeBytes(0)
{
//_cs = 1;
- is_initialized = false;
- _minCommonEraseSize = 0;
- _regions_count = 1;
- _region_erase_types[0] = 0;
+ is_initialized = false;
+ _minCommonEraseSize = 0;
+ _regions_count = 1;
+ _region_erase_types[0] = 0;
- //Default Bus Setup 1_1_1 with 0 dummy and mode cycles
+ //Default Bus Setup 1_1_1 with 0 dummy and mode cycles
_inst_width = QSPI_CFG_BUS_SINGLE;
_address_width = QSPI_CFG_BUS_SINGLE;
_address_size = QSPI_CFG_ADDR_SIZE_24;
@@ -129,7 +129,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
if (QSPI_STATUS_OK != _qspiSetFrequency(freq))
{
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Set Frequency Failed");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Set Frequency Failed");
}
}
@@ -143,84 +143,84 @@ int QSPIFBlockDevice::init()
_mutex->lock();
if (is_initialized == true)
{
- _mutex->unlock();
- return 0;
+ _mutex->unlock();
+ return 0;
}
// Soft Reset
if( -1 == _resetFlashMem()) {
- QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
return -1;
} else {
- QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
}
-
- /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
- int status = _qspiSendReadCommand(QSPIF_RDID, (char *)vendor_device_ids, 0x0 /*address*/, data_length);
+
+ /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
+ int status = _qspiSendReadCommand(QSPIF_RDID, (char *)vendor_device_ids, 0x0 /*address*/, data_length);
if (status != QSPI_STATUS_OK) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read Vendor ID Failed");
- return status;
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read Vendor ID Failed");
+ return status;
}
-
+
switch (vendor_device_ids[0]) {
case 0xbf:
// SST devices come preset with block protection
// enabled for some regions, issue write disable instruction to clear
- _setWriteEnable();
+ _setWriteEnable();
//_cmdwrite(0x98, 0, 0, 0x0, NULL);
_qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
-
+
break;
}
//Synchronize Device
- if( false == _isMemReady()) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - _isMemReady Failed");
- return BD_ERROR_DEVICE_ERROR;
- }
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - _isMemReady Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
- /**************************** Parse SFDP Header ***********************************/
- uint32_t basic_table_addr = NULL;
- size_t basic_table_size = 0;
+ /**************************** Parse SFDP Header ***********************************/
+ uint32_t basic_table_addr = NULL;
+ size_t basic_table_size = 0;
uint32_t sector_map_table_addr = NULL;
- size_t sector_map_table_size = 0;
- if ( 0 != _sfdpParseSFDPHeaders(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse SFDP Headers Failed");
- return BD_ERROR_DEVICE_ERROR;
- }
+ size_t sector_map_table_size = 0;
+ if ( 0 != _sfdpParseSFDPHeaders(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse SFDP Headers Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
- /**************************** Parse Basic Parameters Table ***********************************/
- if ( 0 != _sfdpParseBasicParamTable(basic_table_addr, basic_table_size) ) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse Basic Param Table Failed");
- return BD_ERROR_DEVICE_ERROR;
- }
+ /**************************** Parse Basic Parameters Table ***********************************/
+ if ( 0 != _sfdpParseBasicParamTable(basic_table_addr, basic_table_size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse Basic Param Table Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
- /**************************** Parse Sector Map Table ***********************************/
- _region_size_bytes[0] = _deviceSizeBytes; // If there's no region map, we have a single region sized the entire device size
- _region_high_boundary[0] = _deviceSizeBytes - 1;
+ /**************************** Parse Sector Map Table ***********************************/
+ _region_size_bytes[0] = _deviceSizeBytes; // If there's no region map, we have a single region sized the entire device size
+ _region_high_boundary[0] = _deviceSizeBytes - 1;
- if ( (sector_map_table_addr != NULL) && (0 != sector_map_table_size) ) {
- QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Parsing Sector Map Table - addr: 0x%xh, Size: %d", sector_map_table_addr, sector_map_table_size);
- if ( 0 != _sfdpParseSectorMapTable(sector_map_table_addr, sector_map_table_size) ) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse Sector Map Table Failed");
- return BD_ERROR_DEVICE_ERROR;
- }
- }
+ if ( (sector_map_table_addr != NULL) && (0 != sector_map_table_size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Parsing Sector Map Table - addr: 0x%xh, Size: %d", sector_map_table_addr, sector_map_table_size);
+ if ( 0 != _sfdpParseSectorMapTable(sector_map_table_addr, sector_map_table_size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Parse Sector Map Table Failed");
+ return BD_ERROR_DEVICE_ERROR;
+ }
+ }
- // Configure BUS Mode to 1_1_1 for all commands other than Read
- _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
- /*// Soft Reset
+ // Configure BUS Mode to 1_1_1 for all commands other than Read
+ _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
+ /*// Soft Reset
if( -1 == _resetFlashMem()) {
- QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
return -1;
} else {
- QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
}*/
is_initialized = true;
@@ -232,20 +232,20 @@ int QSPIFBlockDevice::init()
int QSPIFBlockDevice::deinit()
{
_mutex->lock();
- if (is_initialized == false)
- {
- _mutex->unlock();
- return 0;
- }
- qspi_status_t status = _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
- int result = 0;
-
- if (status != QSPI_STATUS_OK) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Disable failed");
- result = -1;
- }
- is_initialized = false;
- _mutex->unlock();
+ if (is_initialized == false)
+ {
+ _mutex->unlock();
+ return 0;
+ }
+ qspi_status_t status = _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
+ int result = 0;
+
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Disable failed");
+ result = -1;
+ }
+ is_initialized = false;
+ _mutex->unlock();
return result;
}
@@ -255,31 +255,31 @@ int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
{
- int status = 0;
-
- QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO Inst: 0x%xh", _readInstruction);
+ int status = 0;
- _mutex->lock();
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO Inst: 0x%xh", _readInstruction);
- _qspiConfiureFormat(
- _inst_width, //Bus width for Instruction phase
- _address_width, //Bus width for Address phase
- _address_size,
- _alt_width, //Bus width for Alt phase
- _alt_size,
- _data_width, //Bus width for Data phase
- _dummy_and_mode_cycles);
- //_qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
+ _mutex->lock();
- if (QSPI_STATUS_OK != _qspiSendReadCommand(_readInstruction, buffer, addr, size)) {
- status = -1;
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Read failed\n");
- }
+ _qspiConfiureFormat(
+ _inst_width, //Bus width for Instruction phase
+ _address_width, //Bus width for Address phase
+ _address_size,
+ _alt_width, //Bus width for Alt phase
+ _alt_size,
+ _data_width, //Bus width for Data phase
+ _dummy_and_mode_cycles);
+ //_qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
+
+ if (QSPI_STATUS_OK != _qspiSendReadCommand(_readInstruction, buffer, addr, size)) {
+ status = -1;
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Read failed\n");
+ }
- // All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus)
- _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
+ // All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus)
+ _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
- _mutex->unlock();
+ _mutex->unlock();
return status;
}
@@ -289,63 +289,63 @@ int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
{
- qspi_status_t result = QSPI_STATUS_OK;
- bool program_failed = false;
- int status = 0;
- uint32_t offset = 0;
- uint32_t chunk = 0;
- bd_size_t writtenBytes = 0;
+ qspi_status_t result = QSPI_STATUS_OK;
+ bool program_failed = false;
+ int status = 0;
+ uint32_t offset = 0;
+ uint32_t chunk = 0;
+ bd_size_t writtenBytes = 0;
while (size > 0) {
- // Write on _pageSizeBytes boundaries (Default 256 bytes a page)
- offset = addr % _pageSizeBytes;
- chunk = (offset + size < _pageSizeBytes) ? size : (_pageSizeBytes);
- writtenBytes = chunk;
-
- _mutex->lock();
-
- //Send WREN
- if (_setWriteEnable() != 0) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Enabe failed\n");
- program_failed = true;
- goto Exit_Point;
- }
-
- if( false == _isMemReady()) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready, write failed\n");
- program_failed = true;
- goto Exit_Point;
- }
-
- result = _qspiSendProgramCommand(_progInstruction, buffer, addr, &writtenBytes);
- if( (result != QSPI_STATUS_OK) || (chunk != writtenBytes) ) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write failed");
- program_failed = true;
- goto Exit_Point;
- }
+ // Write on _pageSizeBytes boundaries (Default 256 bytes a page)
+ offset = addr % _pageSizeBytes;
+ chunk = (offset + size < _pageSizeBytes) ? size : (_pageSizeBytes);
+ writtenBytes = chunk;
- buffer = static_cast(buffer) + chunk;
- addr += chunk;
- size -= chunk;
+ _mutex->lock();
- wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
+ //Send WREN
+ if (_setWriteEnable() != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Enabe failed\n");
+ program_failed = true;
+ goto Exit_Point;
+ }
if( false == _isMemReady()) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready after write, failed\n");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready, write failed\n");
program_failed = true;
goto Exit_Point;
}
- _mutex->unlock();
+
+ result = _qspiSendProgramCommand(_progInstruction, buffer, addr, &writtenBytes);
+ if( (result != QSPI_STATUS_OK) || (chunk != writtenBytes) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write failed");
+ program_failed = true;
+ goto Exit_Point;
+ }
+
+ buffer = static_cast(buffer) + chunk;
+ addr += chunk;
+ size -= chunk;
+
+ wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
+
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready after write, failed\n");
+ program_failed = true;
+ goto Exit_Point;
+ }
+ _mutex->unlock();
}
Exit_Point:
- if (program_failed) {
- _mutex->unlock();
- status = -1;
- }
+ if (program_failed) {
+ _mutex->unlock();
+ status = -1;
+ }
return status;
}
@@ -354,72 +354,72 @@ int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size
int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t inSize)
{
- int type = 0;
- uint32_t chunk = 4096;
- unsigned int curEraseInst = _eraseInstruction;
- int size = (int)inSize;
- bool erase_failed = false;
- int status = 0;
- // Find region of erased address
- int region = _utilsFindAddrRegion((int)addr);
- // Erase Types of selected region
- uint8_t bitfield = _region_erase_types[region];
+ int type = 0;
+ uint32_t chunk = 4096;
+ unsigned int curEraseInst = _eraseInstruction;
+ int size = (int)inSize;
+ bool erase_failed = false;
+ int status = 0;
+ // Find region of erased address
+ int region = _utilsFindAddrRegion((int)addr);
+ // Erase Types of selected region
+ uint8_t bitfield = _region_erase_types[region];
while (size > 0) {
- // iterate to find next Largest erase type (1) supported by region, 2) smaller than size)
- // find the matching instruction and erase size chunk for that type.
- type = _utilsIterateNextLargestEraseType(bitfield, (int)size, (int)addr, _region_high_boundary[region]);
- curEraseInst = _eraseTypeInstArr[type];
- chunk = _eraseTypeSizeArr[type];
+ // iterate to find next Largest erase type (1) supported by region, 2) smaller than size)
+ // find the matching instruction and erase size chunk for that type.
+ type = _utilsIterateNextLargestEraseType(bitfield, (int)size, (int)addr, _region_high_boundary[region]);
+ curEraseInst = _eraseTypeInstArr[type];
+ chunk = _eraseTypeSizeArr[type];
- QSPIF_LOG(QSPIF_DEBUG_DEBUG," Debug: addr: 0x%xh, size:%d, Inst: 0x%xh, chunk: %d , ",
- (int)addr, (int)size, curEraseInst, chunk);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG," Debug: addr: 0x%xh, size:%d, Inst: 0x%xh, chunk: %d , ",
+ (int)addr, (int)size, curEraseInst, chunk);
- _mutex->lock();
+ _mutex->lock();
- if (_setWriteEnable() != 0) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase - Write Enable failed");
- erase_failed = true;
- goto Exit_Point;
- }
+ if (_setWriteEnable() != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase - Write Enable failed");
+ erase_failed = true;
+ goto Exit_Point;
+ }
- if( false == _isMemReady()) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase Device not ready - failed");
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase Device not ready - failed");
+ erase_failed = true;
+ goto Exit_Point;
+ }
+
+ if (QSPI_STATUS_OK != _qspiSendEraseCommand(curEraseInst, addr, size) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase command failed!");
erase_failed = true;
- goto Exit_Point;
+ goto Exit_Point;
}
- if (QSPI_STATUS_OK != _qspiSendEraseCommand(curEraseInst, addr, size) ) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase command failed!");
- erase_failed = true;
- goto Exit_Point;
- }
-
addr += chunk;
size -= chunk;
if ( (size > 0) && (addr > _region_high_boundary[region]) ) {
- // erase crossed to next region
- region++;
- bitfield = _region_erase_types[region];
+ // erase crossed to next region
+ region++;
+ bitfield = _region_erase_types[region];
}
wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
- if( false == _isMemReady()) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI After Erase Device not ready - failed\n");
- erase_failed = true;
- goto Exit_Point;
- }
- _mutex->unlock();
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI After Erase Device not ready - failed\n");
+ erase_failed = true;
+ goto Exit_Point;
+ }
+ _mutex->unlock();
}
Exit_Point:
if (erase_failed) {
- _mutex->unlock();
- status = -1;
+ _mutex->unlock();
+ status = -1;
}
return status;
@@ -446,32 +446,32 @@ bd_size_t QSPIFBlockDevice::get_erase_size() const
// Find minimal erase size supported by address region
bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
{
- // Find region of current address
- int region = _utilsFindAddrRegion((int)addr);
+ // Find region of current address
+ int region = _utilsFindAddrRegion((int)addr);
- int minRegionEraseSize = _minCommonEraseSize;
- int8_t type_mask = 0x01;
- int i_ind = 0;
+ int minRegionEraseSize = _minCommonEraseSize;
+ int8_t type_mask = 0x01;
+ int i_ind = 0;
- if (region != -1) {
- type_mask = 0x01;
+ if (region != -1) {
+ type_mask = 0x01;
- for (i_ind = 0; i_ind < 4; i_ind++) {
- // loop through erase types supported by region
- if (_region_erase_types[region] & type_mask) {
+ for (i_ind = 0; i_ind < 4; i_ind++) {
+ // loop through erase types supported by region
+ if (_region_erase_types[region] & type_mask) {
- minRegionEraseSize = _eraseTypeSizeArr[i_ind];
- break;
- }
- type_mask = type_mask << 1;
- }
+ minRegionEraseSize = _eraseTypeSizeArr[i_ind];
+ break;
+ }
+ type_mask = type_mask << 1;
+ }
- if (i_ind == 4) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: no erase type was found for region addr");
- }
- }
+ if (i_ind == 4) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: no erase type was found for region addr");
+ }
+ }
- return (bd_size_t)minRegionEraseSize;
+ return (bd_size_t)minRegionEraseSize;
}
@@ -487,138 +487,138 @@ bd_size_t QSPIFBlockDevice::size() const
int QSPIFBlockDevice::_sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size)
{
- uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
+ uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
uint32_t tmpRegionSize = 0;
- int i_ind = 0;
- int prevBoundary = 0;
+ int i_ind = 0;
+ int prevBoundary = 0;
// Default set to all type bits 1-4 are common
_minCommonEraseType = 0x0F;
- qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/, sector_map_table_size);
- if (status != QSPI_STATUS_OK) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP First Table Failed");
- return -1;
- }
-
- //QSPIF_LOG(QSPIF_DEBUG_DEBUG,\nDEBUG: "Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",sector_map_table[0],
- // sector_map_table[1],
- // sector_map_table[2],
- // sector_map_table[3],
- // sector_map_table[4],
- // sector_map_table[5],
- // sector_map_table[6],
- // sector_map_table[7], sector_map_table[56], sector_map_table[57], sector_map_table[58], sector_map_table[59], sector_map_table[52]);
-
- // Currently we support only Single Map Descriptor
- if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
- return -1;
- }
-
- _regions_count = sector_map_table[2] + 1;
- if (_regions_count > QSPIF_MAX_REGIONS) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Supporting up to %d regions, current setup to %d regions - fail", QSPIF_MAX_REGIONS, _regions_count);
- return -1;
- }
-
- // Loop through Regions and set for each one: size, supported erase types, high boundary offset
- // Calculate minimum Common Erase Type for all Regions
- for (i_ind = 0; i_ind < _regions_count; i_ind++) {
- tmpRegionSize = ((*((uint32_t *)§or_map_table[(i_ind+1)*4])) >> 8) & 0x00FFFFFF; // bits 9-32
- _region_size_bytes[i_ind] = (tmpRegionSize +1) * 256; // Region size is 0 based multiple of 256 bytes;
- _region_erase_types[i_ind] = sector_map_table[(i_ind+1)*4] & 0x0F; // bits 1-4
- _minCommonEraseType &= _region_erase_types[i_ind];
- _region_high_boundary[i_ind] = (_region_size_bytes[i_ind]-1) + prevBoundary;
- prevBoundary = _region_high_boundary[i_ind]+1;
- }
-
- // Calc minimum Common Erase Size from _minCommonEraseType
+ qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/, sector_map_table_size);
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP First Table Failed");
+ return -1;
+ }
+
+ //QSPIF_LOG(QSPIF_DEBUG_DEBUG,\nDEBUG: "Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",sector_map_table[0],
+ // sector_map_table[1],
+ // sector_map_table[2],
+ // sector_map_table[3],
+ // sector_map_table[4],
+ // sector_map_table[5],
+ // sector_map_table[6],
+ // sector_map_table[7], sector_map_table[56], sector_map_table[57], sector_map_table[58], sector_map_table[59], sector_map_table[52]);
+
+ // Currently we support only Single Map Descriptor
+ if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
+ return -1;
+ }
+
+ _regions_count = sector_map_table[2] + 1;
+ if (_regions_count > QSPIF_MAX_REGIONS) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Supporting up to %d regions, current setup to %d regions - fail", QSPIF_MAX_REGIONS, _regions_count);
+ return -1;
+ }
+
+ // Loop through Regions and set for each one: size, supported erase types, high boundary offset
+ // Calculate minimum Common Erase Type for all Regions
+ for (i_ind = 0; i_ind < _regions_count; i_ind++) {
+ tmpRegionSize = ((*((uint32_t *)§or_map_table[(i_ind+1)*4])) >> 8) & 0x00FFFFFF; // bits 9-32
+ _region_size_bytes[i_ind] = (tmpRegionSize +1) * 256; // Region size is 0 based multiple of 256 bytes;
+ _region_erase_types[i_ind] = sector_map_table[(i_ind+1)*4] & 0x0F; // bits 1-4
+ _minCommonEraseType &= _region_erase_types[i_ind];
+ _region_high_boundary[i_ind] = (_region_size_bytes[i_ind]-1) + prevBoundary;
+ prevBoundary = _region_high_boundary[i_ind]+1;
+ }
+
+ // Calc minimum Common Erase Size from _minCommonEraseType
uint8_t type_mask = 0x01;
- for (i_ind = 0; i_ind < 4; i_ind++) {
- if (_minCommonEraseType & type_mask) {
- _minCommonEraseType = i_ind;
- _minCommonEraseSize = _eraseTypeSizeArr[i_ind];
- break;
- }
- type_mask = type_mask << 1;
- }
-
- if (i_ind == 4) {
- // No common erase type was found between regions
- _minCommonEraseType = 0;
- _minCommonEraseSize = -1;
- }
-
- return 0;
+ for (i_ind = 0; i_ind < 4; i_ind++) {
+ if (_minCommonEraseType & type_mask) {
+ _minCommonEraseType = i_ind;
+ _minCommonEraseSize = _eraseTypeSizeArr[i_ind];
+ break;
+ }
+ type_mask = type_mask << 1;
+ }
+
+ if (i_ind == 4) {
+ // No common erase type was found between regions
+ _minCommonEraseType = 0;
+ _minCommonEraseSize = -1;
+ }
+
+ return 0;
}
int QSPIFBlockDevice::_sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size)
{
- uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
-
- qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/, basic_table_size);
- if (status != QSPI_STATUS_OK) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP First Table Failed");
- return -1;
- }
-
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",param_table[0],
- param_table[1],
- param_table[2],
- param_table[3],
- param_table[4],
- param_table[5],
- param_table[6],
- param_table[7], param_table[56], param_table[57], param_table[58], param_table[59], param_table[52]);
-
-
- // Check address size, currently only supports 3byte addresses
- if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - verify 3byte addressing Failed");
- return -1;
- }
-
- // Get device density (stored in bits - 1)
- uint32_t density_bits = (
- (param_table[7] << 24) |
- (param_table[6] << 16) |
- (param_table[5] << 8 ) |
- param_table[4] );
- _deviceSizeBytes = (density_bits + 1) / 8;
-
- // Set Default read/program/erase Instructions
- _readInstruction = QSPIF_READ;
- _progInstruction = QSPIF_PP;
- _eraseInstruction = QSPIF_SE;
-
- // Set Page Size (QSPI write must be done on Page limits)
- _pageSizeBytes = _sfdpDetectPageSize(param_table);
-
- // Detect and Set Erase Types
- bool shouldSetQuadEnable = false;
- bool isQPIMode = false;
- _sfdpDetectEraseTypesInstAndSize(param_table, _erase4KInst, _eraseTypeInstArr, _eraseTypeSizeArr);
- _eraseInstruction = _erase4KInst;
-
-
- // Detect and Set fastest Bus mode (default 1-1-1)
- _sfdpDetectBestBusReadMode(param_table, shouldSetQuadEnable, isQPIMode, _readInstruction);
-
- if (true == shouldSetQuadEnable) {
- // Set Quad Enable and QPI Bus modes if Supported
- QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Setting Quad Enable");
- _sfdpSetQuadEnabled(param_table);
- if (true == isQPIMode) {
- QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Setting QPI mode");
- _sfdpSetQPIEnabled(param_table);
- }
- }
- return 0;
+ uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
+
+ qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/, basic_table_size);
+ if (status != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP First Table Failed");
+ return -1;
+ }
+
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",param_table[0],
+ param_table[1],
+ param_table[2],
+ param_table[3],
+ param_table[4],
+ param_table[5],
+ param_table[6],
+ param_table[7], param_table[56], param_table[57], param_table[58], param_table[59], param_table[52]);
+
+
+ // Check address size, currently only supports 3byte addresses
+ if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - verify 3byte addressing Failed");
+ return -1;
+ }
+
+ // Get device density (stored in bits - 1)
+ uint32_t density_bits = (
+ (param_table[7] << 24) |
+ (param_table[6] << 16) |
+ (param_table[5] << 8 ) |
+ param_table[4] );
+ _deviceSizeBytes = (density_bits + 1) / 8;
+
+ // Set Default read/program/erase Instructions
+ _readInstruction = QSPIF_READ;
+ _progInstruction = QSPIF_PP;
+ _eraseInstruction = QSPIF_SE;
+
+ // Set Page Size (QSPI write must be done on Page limits)
+ _pageSizeBytes = _sfdpDetectPageSize(param_table);
+
+ // Detect and Set Erase Types
+ bool shouldSetQuadEnable = false;
+ bool isQPIMode = false;
+ _sfdpDetectEraseTypesInstAndSize(param_table, _erase4KInst, _eraseTypeInstArr, _eraseTypeSizeArr);
+ _eraseInstruction = _erase4KInst;
+
+
+ // Detect and Set fastest Bus mode (default 1-1-1)
+ _sfdpDetectBestBusReadMode(param_table, shouldSetQuadEnable, isQPIMode, _readInstruction);
+
+ if (true == shouldSetQuadEnable) {
+ // Set Quad Enable and QPI Bus modes if Supported
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Setting Quad Enable");
+ _sfdpSetQuadEnabled(param_table);
+ if (true == isQPIMode) {
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - Setting QPI mode");
+ _sfdpSetQPIEnabled(param_table);
+ }
+ }
+ return 0;
}
int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t &basic_table_addr, size_t &basic_table_size,
- uint32_t §or_map_table_addr, size_t §or_map_table_size)
+ uint32_t §or_map_table_addr, size_t §or_map_table_size)
{
uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE];
uint8_t param_header[QSPIF_PARAM_HEADER_SIZE];
@@ -630,30 +630,30 @@ int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t &basic_table_addr, size_t &
qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length);
if (status != QSPI_STATUS_OK) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP Failed");
- return -1;
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read SFDP Failed");
+ return -1;
}
QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG11: Read SFDP Header: %x %x %x %x %x %x %x %x\n",sfdp_header[0],
- sfdp_header[1],
- sfdp_header[2],
- sfdp_header[3],
- sfdp_header[4],
- sfdp_header[5],
- sfdp_header[6],
- sfdp_header[7]);
+ sfdp_header[1],
+ sfdp_header[2],
+ sfdp_header[3],
+ sfdp_header[4],
+ sfdp_header[5],
+ sfdp_header[6],
+ sfdp_header[7]);
// Verify SFDP signature for sanity
// Also check that major/minor version is acceptable
if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - _verify SFDP signature and version Failed");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - _verify SFDP signature and version Failed");
return -1;
}
else
{
- QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - verified SFDP Signature and version Successfully");
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: init - verified SFDP Signature and version Successfully");
}
// Discover Number of Parameter Headers
@@ -667,32 +667,32 @@ int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t &basic_table_addr, size_t &
// Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table)
for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
- status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_header, addr, data_length);
+ status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_header, addr, data_length);
if (status != QSPI_STATUS_OK) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read Param Table %d Failed", i_ind+1);
- return -1;
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: init - Read Param Table %d Failed", i_ind+1);
+ return -1;
}
// The SFDP spec indicates the standard table is always at offset 0
// in the parameter headers, we check just to be safe
if (param_header[2] != 1) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Param Table %d - Major Version should be 1!", i_ind+1);
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Param Table %d - Major Version should be 1!", i_ind+1);
return -1;
}
if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
- // Found Basic Params Table: LSB=0x00, MSB=0xFF
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Found Basic Param Table at Table: %d", i_ind+1);
- basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
- // Supporting up to 64 Bytes Table (16 DWORDS)
- basic_table_size = ((param_header[3]*4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[11]*4) : 64;
+ // Found Basic Params Table: LSB=0x00, MSB=0xFF
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Found Basic Param Table at Table: %d", i_ind+1);
+ basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
+ // Supporting up to 64 Bytes Table (16 DWORDS)
+ basic_table_size = ((param_header[3]*4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[11]*4) : 64;
}
else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
- // Found Sector Map Table: LSB=0x81, MSB=0xFF
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Found Sector Map Table at Table: %d", i_ind+1);
- sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
+ // Found Sector Map Table: LSB=0x81, MSB=0xFF
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Found Sector Map Table at Table: %d", i_ind+1);
+ sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
- sector_map_table_size = param_header[3] * 4;
+ sector_map_table_size = param_header[3] * 4;
}
addr += QSPIF_PARAM_HEADER_SIZE;
@@ -705,103 +705,103 @@ int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t &basic_table_addr, size_t &
int QSPIFBlockDevice::_sfdpSetQPIEnabled(uint8_t *basicParamTablePtr)
{
- uint8_t config_reg[1];
+ uint8_t config_reg[1];
- // QPI 4-4-4 Enable Procedure is specified in 5 Bits
- uint8_t en_seq_444_value = ( ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE+1] & 0x01) << 4 ));
+ // QPI 4-4-4 Enable Procedure is specified in 5 Bits
+ uint8_t en_seq_444_value = ( ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE+1] & 0x01) << 4 ));
- switch (en_seq_444_value) {
- case 1:
- case 2:
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - send command 38h");
- /*if (_setWriteEnable() != 0) {
- printf("ERROR: Write Enabe failed\n");
- return -1;
- }
- if( false == _isMemReady()) {
- printf("ERROR: Device not ready, write failed\n");
- return -1;
- }*/
-
- _qspiSendGeneralCommand(0x38, -1, NULL, 0, NULL, 0);
- /*wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
- if( false == _isMemReady()) {
- printf("ERROR: Device not ready after write, failed\n");
- return -1;
- }*/
+ switch (en_seq_444_value) {
+ case 1:
+ case 2:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - send command 38h");
+ /*if (_setWriteEnable() != 0) {
+ printf("ERROR: Write Enabe failed\n");
+ return -1;
+ }
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready, write failed\n");
+ return -1;
+ }*/
+
+ _qspiSendGeneralCommand(0x38, -1, NULL, 0, NULL, 0);
+ /*wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready after write, failed\n");
+ return -1;
+ }*/
- break;
+ break;
- case 4:
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - send command 35h");
- _qspiSendGeneralCommand(0x35, -1, NULL, 0, NULL, 0);
- break;
+ case 4:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - send command 35h");
+ _qspiSendGeneralCommand(0x35, -1, NULL, 0, NULL, 0);
+ break;
- case 8:
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - set config bit 6 and send command 71h");
- _qspiSendGeneralCommand(0x65, 0x800003, NULL, 0, (char *)config_reg, 1);
- config_reg[1] |= 0x40; //Set Bit 6
- _qspiSendGeneralCommand(0x71, 0x800003, NULL, 0, (char *)config_reg, 1);
- break;
+ case 8:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - set config bit 6 and send command 71h");
+ _qspiSendGeneralCommand(0x65, 0x800003, NULL, 0, (char *)config_reg, 1);
+ config_reg[1] |= 0x40; //Set Bit 6
+ _qspiSendGeneralCommand(0x71, 0x800003, NULL, 0, (char *)config_reg, 1);
+ break;
- case 16:
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - reset config bits 0-7 and send command 61h");
- _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
- config_reg[1] &= 0x7F; //Reset Bit 7 of CR
+ case 16:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQPIEnabled - reset config bits 0-7 and send command 61h");
+ _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
+ config_reg[1] &= 0x7F; //Reset Bit 7 of CR
- /*
- if (_setWriteEnable() != 0) {
- printf("ERROR: Write Enabe failed\n");
- return -1;
- }
- if( false == _isMemReady()) {
- printf("ERROR: Device not ready, write failed\n");
- return -1;
- }*/
+ /*
+ if (_setWriteEnable() != 0) {
+ printf("ERROR: Write Enabe failed\n");
+ return -1;
+ }
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready, write failed\n");
+ return -1;
+ }*/
- _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
+ _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
- /* wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
- if( false == _isMemReady()) {
- printf("ERROR: Device not ready after write, failed\n");
- return -1;
- }
+ /* wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready after write, failed\n");
+ return -1;
+ }
- _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
+ _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
- if (_setWriteEnable() != 0) {
- printf("ERROR: Write Enabe failed\n");
- return -1;
- }
- if( false == _isMemReady()) {
- printf("ERROR: Device not ready, write failed\n");
- return -1;
- }
- config_reg[1] = 0x00; //Reset Bits 0-7
- _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
- wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);*/
- /* if( false == _isMemReady()) {
- printf("ERROR: Device not ready after write, failed\n");
- return -1;
- }*/
+ if (_setWriteEnable() != 0) {
+ printf("ERROR: Write Enabe failed\n");
+ return -1;
+ }
+ if( false == _isMemReady()) {
+ printf("ERROR: Device not ready, write failed\n");
+ return -1;
+ }
+ config_reg[1] = 0x00; //Reset Bits 0-7
+ _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
+ wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);*/
+ /* if( false == _isMemReady()) {
+ printf("ERROR: Device not ready after write, failed\n");
+ return -1;
+ }*/
- break;
+ break;
- default:
- QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _setQPIEnabled - Unsuported En Seq 444 configuration");
- break;
+ default:
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _setQPIEnabled - Unsuported En Seq 444 configuration");
+ break;
- }
+ }
- return 0;
+ return 0;
}
@@ -813,62 +813,62 @@ int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr)
int sr_write_size = QSPI_MAX_STATUS_REGISTER_SIZE;
int status_reg_setup[QSPI_MAX_STATUS_REGISTER_SIZE];
- uint8_t status_reg[QSPI_MAX_STATUS_REGISTER_SIZE];
- unsigned int writeRegisterInst = QSPIF_WRSR;
- unsigned int readRegisterInst = QSPIF_RDSR;
+ uint8_t status_reg[QSPI_MAX_STATUS_REGISTER_SIZE];
+ unsigned int writeRegisterInst = QSPIF_WRSR;
+ unsigned int readRegisterInst = QSPIF_RDSR;
uint8_t qer_value = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4;
switch (qer_value) {
- case 0:
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Device Does not Have a QE Bit, continue based on Read Inst");
- return 0;
-
- case 1:
- case 4:
- status_reg_setup[0] = 0;
- status_reg_setup[1] = 0x02;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 1 of Status Reg 2");
+ case 0:
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Device Does not Have a QE Bit, continue based on Read Inst");
+ return 0;
+
+ case 1:
+ case 4:
+ status_reg_setup[0] = 0;
+ status_reg_setup[1] = 0x02;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 1 of Status Reg 2");
+ break;
+
+ case 2:
+ status_reg_setup[0] = 0x40;
+ status_reg_setup[1] = 0;
+ sr_write_size = 1;
+ sr_read_size = 1;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 6 of Status Reg 1");
+ break;
+
+ case 3:
+ status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1
+ status_reg_setup[1] = 0;
+ sr_write_size = 1;
+ sr_read_size = 1;
+ writeRegisterInst = 0x3E;
+ readRegisterInst = 0x3F;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 7 of Status Reg 1");
break;
-
- case 2:
- status_reg_setup[0] = 0x40;
- status_reg_setup[1] = 0;
- sr_write_size = 1;
- sr_read_size = 1;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 6 of Status Reg 1");
- break;
-
- case 3:
- status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1
- status_reg_setup[1] = 0;
- sr_write_size = 1;
- sr_read_size = 1;
- writeRegisterInst = 0x3E;
- readRegisterInst = 0x3F;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 7 of Status Reg 1");
- break;
- case 5:
- status_reg_setup[0] = 0;
- status_reg_setup[1] = 0x02;
- readRegisterInst = 0x35;
- sr_read_size = 1;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 1 of Status Reg 2 -special read command");
- break;
- default:
- QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _setQuadEnable - Unsuported QER configuration");
+ case 5:
+ status_reg_setup[0] = 0;
+ status_reg_setup[1] = 0x02;
+ readRegisterInst = 0x35;
+ sr_read_size = 1;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Setting QE Bit, Bit 1 of Status Reg 2 -special read command");
break;
+ default:
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _setQuadEnable - Unsuported QER configuration");
+ break;
}
// Read Status Register
if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, sr_read_size) ){ // store received values in status_value
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
} else {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed");
return -1;
}
@@ -878,37 +878,37 @@ int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr)
// Write new Status Register Setup
- if (_setWriteEnable() != 0) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Enabe failed\n");
- return -1;
- }
+ if (_setWriteEnable() != 0) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Write Enabe failed\n");
+ return -1;
+ }
- if( false == _isMemReady()) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready, write failed");
- return -1;
- }
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready, write failed");
+ return -1;
+ }
if (QSPI_STATUS_OK == _qspiSendGeneralCommand(writeRegisterInst, -1, (char *)status_reg, sr_write_size, NULL, 0) ){ // Write QE to status_register
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQuadEnable - Writing Status Register Success: value = 0x%x", (int)status_reg[0]);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _setQuadEnable - Writing Status Register Success: value = 0x%x", (int)status_reg[0]);
} else {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: _setQuadEnable - Writing Status Register failed");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: _setQuadEnable - Writing Status Register failed");
return -1;
}
wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
- if( false == _isMemReady()) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready after write, failed");
- return -1;
- }
+ if( false == _isMemReady()) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Device not ready after write, failed");
+ return -1;
+ }
- // For Debug
- memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE);
+ // For Debug
+ memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE);
if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, sr_read_size) ){ // store received values in status_value
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
} else {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed");
return -1;
}
@@ -919,149 +919,149 @@ int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr)
int QSPIFBlockDevice::_sfdpDetectPageSize(uint8_t *basicParamTablePtr)
{
- int page2PowerSize = ( (int)basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
- int pageSize = _utilsMathPower(2, page2PowerSize);
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _detectPageSize - Page Size: %d", pageSize);
- return pageSize;
+ int page2PowerSize = ( (int)basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
+ int pageSize = _utilsMathPower(2, page2PowerSize);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: _detectPageSize - Page Size: %d", pageSize);
+ return pageSize;
}
int QSPIFBlockDevice::_sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int &erase4KInst, unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr)
{
- erase4KInst = 0xff;
- bool found4KEraseType = false;
- uint8_t bitfield = 0x01;
-
- // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
- erase4KInst = basicParamTablePtr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
-
- // Loop Erase Types 1-4
- for (int i_ind=0; i_ind < 4; i_ind++) {
- eraseTypeInstArr[i_ind] = 0xff; //0xFF default for unsupported type
- eraseTypeSizeArr[i_ind] = _utilsMathPower(2, basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE+2*i_ind]);
- if (eraseTypeSizeArr[i_ind] > 1) {
- // if size==1 type is not supported
- eraseTypeInstArr[i_ind] = basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE+2*i_ind];
-
- if ((eraseTypeSizeArr[i_ind] < _minCommonEraseSize) || (_minCommonEraseSize == 0) ) {
- //Set default minimal common erase for singal region
- _minCommonEraseSize = eraseTypeSizeArr[i_ind];
- }
-
- if (eraseTypeSizeArr[i_ind] == 4096) {
- found4KEraseType = true;
- if (erase4KInst != eraseTypeInstArr[i_ind]) {
- //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
- erase4KInst = eraseTypeInstArr[i_ind];
- QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
-
- }
- }
- _region_erase_types[0] |= bitfield; // If there's no region map, set region "0" types as defualt;
- }
-
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind+1), eraseTypeInstArr[i_ind], eraseTypeSizeArr[i_ind]);
- bitfield = bitfield << 1;
- }
-
- if (false == found4KEraseType) {
- QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: Couldn't find Erase Type for 4KB size");
- }
- return 0;
+ erase4KInst = 0xff;
+ bool found4KEraseType = false;
+ uint8_t bitfield = 0x01;
+
+ // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
+ erase4KInst = basicParamTablePtr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
+
+ // Loop Erase Types 1-4
+ for (int i_ind=0; i_ind < 4; i_ind++) {
+ eraseTypeInstArr[i_ind] = 0xff; //0xFF default for unsupported type
+ eraseTypeSizeArr[i_ind] = _utilsMathPower(2, basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE+2*i_ind]);
+ if (eraseTypeSizeArr[i_ind] > 1) {
+ // if size==1 type is not supported
+ eraseTypeInstArr[i_ind] = basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE+2*i_ind];
+
+ if ((eraseTypeSizeArr[i_ind] < _minCommonEraseSize) || (_minCommonEraseSize == 0) ) {
+ //Set default minimal common erase for singal region
+ _minCommonEraseSize = eraseTypeSizeArr[i_ind];
+ }
+
+ if (eraseTypeSizeArr[i_ind] == 4096) {
+ found4KEraseType = true;
+ if (erase4KInst != eraseTypeInstArr[i_ind]) {
+ //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
+ erase4KInst = eraseTypeInstArr[i_ind];
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
+
+ }
+ }
+ _region_erase_types[0] |= bitfield; // If there's no region map, set region "0" types as defualt;
+ }
+
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind+1), eraseTypeInstArr[i_ind], eraseTypeSizeArr[i_ind]);
+ bitfield = bitfield << 1;
+ }
+
+ if (false == found4KEraseType) {
+ QSPIF_LOG(QSPIF_DEBUG_WARNING,"WARNING: Couldn't find Erase Type for 4KB size");
+ }
+ return 0;
}
int QSPIFBlockDevice::_sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool &setQuadEnable, bool &isQPIMode, unsigned int &readInst) {
- bool isDone = false;
+ bool isDone = false;
- setQuadEnable = false;
- isQPIMode = false;
- int dummyCycles = 0;
- uint8_t examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
+ setQuadEnable = false;
+ isQPIMode = false;
+ int dummyCycles = 0;
+ uint8_t examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
do { // compound statement is the loop body
- if (examinedByte & 0x10) {
- // QPI 4-4-4 Supported
- readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE];
- setQuadEnable = true;
- isQPIMode = true;
- _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE-1] >> 5)
- + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE-1] & 0x1F);
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 4-4-4, Instruction: 0x%xh",_readInstruction);
- //_inst_width = QSPI_CFG_BUS_QUAD;
- _address_width = QSPI_CFG_BUS_QUAD;
- _data_width = QSPI_CFG_BUS_QUAD;
-
- break;
- }
-
-
- examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
- if (examinedByte & 0x40) {
- // Fast Read 1-4-4 Supported
- readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE];
- setQuadEnable = true;
- // dummy cycles + mode cycles = Dummy Cycles
- _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE-1] >> 5)
- + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE-1] & 0x1F);
- _address_width = QSPI_CFG_BUS_QUAD;
- _data_width = QSPI_CFG_BUS_QUAD;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-4-4, Instruction: 0x%xh",_readInstruction);
- break;
- }
- if (examinedByte & 0x80) {
- // Fast Read 1-1-4 Supported
- readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE];
- setQuadEnable = true;
- _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE-1] >> 5)
- + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE-1] & 0x1F);
- _data_width = QSPI_CFG_BUS_QUAD;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-4, Instruction: 0x%xh",_readInstruction);
- break;
- }
- examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
- if (examinedByte & 0x01) {
- // Fast Read 2-2-2 Supported
- readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE];
- _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE-1] >> 5)
- + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE-1] & 0x1F);
- _address_width = QSPI_CFG_BUS_DUAL;
- _data_width = QSPI_CFG_BUS_DUAL;
- QSPIF_LOG(QSPIF_DEBUG_INFO,"/nINFO: Read Bus Mode set to 2-2-2, Instruction: 0x%xh",_readInstruction);
- break;
- }
-
- examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
- if (examinedByte & 0x20) {
- // Fast Read 1-2-2 Supported
- readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE];
- _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE-1] >> 5)
- + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE-1] & 0x1F);
- _address_width = QSPI_CFG_BUS_DUAL;
- _data_width = QSPI_CFG_BUS_DUAL;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh",_readInstruction);
- break;
- }
- if (examinedByte & 0x01) {
- // Fast Read 1-1-2 Supported
- readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE];
- _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE-1] >> 5)
- + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE-1] & 0x1F);
- _data_width = QSPI_CFG_BUS_DUAL;
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh",_readInstruction);
- break;
- }
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh",_readInstruction);
- isDone = true;
- }
- while (isDone == false);
-
- return 0;
+ if (examinedByte & 0x10) {
+ // QPI 4-4-4 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE];
+ setQuadEnable = true;
+ isQPIMode = true;
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE-1] & 0x1F);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 4-4-4, Instruction: 0x%xh",_readInstruction);
+ //_inst_width = QSPI_CFG_BUS_QUAD;
+ _address_width = QSPI_CFG_BUS_QUAD;
+ _data_width = QSPI_CFG_BUS_QUAD;
+
+ break;
+ }
+
+
+ examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
+ if (examinedByte & 0x40) {
+ // Fast Read 1-4-4 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE];
+ setQuadEnable = true;
+ // dummy cycles + mode cycles = Dummy Cycles
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE-1] & 0x1F);
+ _address_width = QSPI_CFG_BUS_QUAD;
+ _data_width = QSPI_CFG_BUS_QUAD;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-4-4, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ if (examinedByte & 0x80) {
+ // Fast Read 1-1-4 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE];
+ setQuadEnable = true;
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE-1] & 0x1F);
+ _data_width = QSPI_CFG_BUS_QUAD;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-4, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
+ if (examinedByte & 0x01) {
+ // Fast Read 2-2-2 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE];
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE-1] & 0x1F);
+ _address_width = QSPI_CFG_BUS_DUAL;
+ _data_width = QSPI_CFG_BUS_DUAL;
+ QSPIF_LOG(QSPIF_DEBUG_INFO,"/nINFO: Read Bus Mode set to 2-2-2, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+
+ examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
+ if (examinedByte & 0x20) {
+ // Fast Read 1-2-2 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE];
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE-1] & 0x1F);
+ _address_width = QSPI_CFG_BUS_DUAL;
+ _data_width = QSPI_CFG_BUS_DUAL;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ if (examinedByte & 0x01) {
+ // Fast Read 1-1-2 Supported
+ readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE];
+ _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE-1] >> 5)
+ + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE-1] & 0x1F);
+ _data_width = QSPI_CFG_BUS_DUAL;
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh",_readInstruction);
+ break;
+ }
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"/nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh",_readInstruction);
+ isDone = true;
+ }
+ while (isDone == false);
+
+ return 0;
}
@@ -1072,9 +1072,9 @@ int QSPIFBlockDevice::_resetFlashMem()
QSPIF_LOG(QSPIF_DEBUG_ERROR,"INFO: _resetFlashMem:\n");
//Read the Status Register from device
if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, 1) ){ // store received values in status_value
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]);
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]);
} else {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed\n");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed\n");
status = -1;
}
@@ -1082,9 +1082,9 @@ int QSPIFBlockDevice::_resetFlashMem()
{
//Send Reset Enable
if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RSTEN, -1, NULL, 0, NULL, 0) ) { // store received values in status_value
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Sending RSTEN Success\n");
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Sending RSTEN Success\n");
} else {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sending RSTEN failed\n");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sending RSTEN failed\n");
status = -1;
}
@@ -1093,9 +1093,9 @@ int QSPIFBlockDevice::_resetFlashMem()
{
//Send Reset
if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RST, -1, NULL, 0, NULL, 0)) { // store received values in status_value
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Sending RST Success\n");
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"DEBUG: Sending RST Success\n");
} else {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sending RST failed\n");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Sending RST failed\n");
status = -1;
}
@@ -1111,19 +1111,19 @@ bool QSPIFBlockDevice::_isMemReady()
{
char status_value[2];
int retries = 0;
- bool memReady = true;
+ bool memReady = true;
do
{
retries++;
//Read the Status Register from device
if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, 2)) { // store received values in status_value
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed\n");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Reading Status Register failed\n");
}
} while( (status_value[0] & 0x1) != 0 && retries <10000 );
if((status_value[0] & 0x1) != 0) {
- QSPIF_LOG(QSPIF_DEBUG_DEBUG,"ERROR: _isMemReady FALSE\n");
+ QSPIF_LOG(QSPIF_DEBUG_DEBUG,"ERROR: _isMemReady FALSE\n");
memReady = false;
}
return memReady;
@@ -1132,9 +1132,9 @@ bool QSPIFBlockDevice::_isMemReady()
int QSPIFBlockDevice::_setWriteEnable()
{
- int status = 0;
+ int status = 0;
if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_WREN, -1, NULL, 0, NULL, 0)) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR:Sending WREN command FAILED\n");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR:Sending WREN command FAILED\n");
status = -1;
}
return status;
@@ -1149,8 +1149,8 @@ int QSPIFBlockDevice::_utilsMathPower(int base, int exp)
{
int result = 1;
while(exp) {
- result *= base;
- exp--;
+ result *= base;
+ exp--;
}
return result;
}
@@ -1158,48 +1158,48 @@ int QSPIFBlockDevice::_utilsMathPower(int base, int exp)
int QSPIFBlockDevice::_utilsFindAddrRegion(int offset)
{
- if ((offset > (int)_deviceSizeBytes) || (_regions_count == 0)){
- return -1;
- }
+ if ((offset > (int)_deviceSizeBytes) || (_regions_count == 0)){
+ return -1;
+ }
- if (_regions_count == 1) {
- return 0;
- }
+ if (_regions_count == 1) {
+ return 0;
+ }
- for (int i_ind = _regions_count-2; i_ind >= 0; i_ind--) {
+ for (int i_ind = _regions_count-2; i_ind >= 0; i_ind--) {
- if (offset > _region_high_boundary[i_ind]) {
- return (i_ind+1);
- }
- }
- return -1;
+ if (offset > _region_high_boundary[i_ind]) {
+ return (i_ind+1);
+ }
+ }
+ return -1;
}
int QSPIFBlockDevice::_utilsIterateNextLargestEraseType(uint8_t &bitfield, int size, int offset, int boundry)
{
- uint8_t type_mask = 0x08;
- int i_ind = 0;
- int largestEraseType = 0;
- for (i_ind = 3; i_ind >= 0; i_ind--) {
- if (bitfield & type_mask) {
- largestEraseType = i_ind;
- if ( (size > _eraseTypeSizeArr[largestEraseType]) &&
- ((boundry - offset) > _eraseTypeSizeArr[largestEraseType]) ) {
- break;
- }
- else {
- bitfield &= ~type_mask;
- }
- }
- type_mask = type_mask >> 1;
- }
-
- if (i_ind == 4) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: no erase type was found for current region addr");
- }
- return largestEraseType;
+ uint8_t type_mask = 0x08;
+ int i_ind = 0;
+ int largestEraseType = 0;
+ for (i_ind = 3; i_ind >= 0; i_ind--) {
+ if (bitfield & type_mask) {
+ largestEraseType = i_ind;
+ if ( (size > _eraseTypeSizeArr[largestEraseType]) &&
+ ((boundry - offset) > _eraseTypeSizeArr[largestEraseType]) ) {
+ break;
+ }
+ else {
+ bitfield &= ~type_mask;
+ }
+ }
+ type_mask = type_mask >> 1;
+ }
+
+ if (i_ind == 4) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: no erase type was found for current region addr");
+ }
+ return largestEraseType;
}
@@ -1210,7 +1210,7 @@ int QSPIFBlockDevice::_utilsIterateNextLargestEraseType(uint8_t &bitfield, int s
qspi_status_t QSPIFBlockDevice::_qspiSetFrequency(int freq)
{
- return _qspi.set_frequency(freq);
+ return _qspi.set_frequency(freq);
}
@@ -1218,13 +1218,13 @@ qspi_status_t QSPIFBlockDevice::_qspiSendReadCommand(unsigned int readInst, void
{
// Check the address and size fit onto the chip.
- /* OFR_DBG */
- //MBED_ASSERT(is_valid_read(addr, size));
+ /* OFR_DBG */
+ //MBED_ASSERT(is_valid_read(addr, size));
- size_t bufLen = size;
+ size_t bufLen = size;
if(_qspi.read( readInst, -1, (unsigned int )addr, (char *)buffer, &bufLen) != QSPI_STATUS_OK ) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Read failed");
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: Read failed");
return QSPI_STATUS_ERROR;
}
@@ -1237,12 +1237,12 @@ qspi_status_t QSPIFBlockDevice::_qspiSendProgramCommand(unsigned int progInst, c
{
// Check the address and size fit onto the chip.
//MBED_ASSERT(is_valid_program(addr, (*size)));
- qspi_status_t result = QSPI_STATUS_OK;
+ qspi_status_t result = QSPI_STATUS_OK;
- result = _qspi.write( progInst, -1, addr/*(((unsigned int)addr) & 0x00FFFF00)*/, (char *)buffer, (size_t *)size);
- if(result != QSPI_STATUS_OK) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Write failed");
- }
+ result = _qspi.write( progInst, -1, addr/*(((unsigned int)addr) & 0x00FFFF00)*/, (char *)buffer, (size_t *)size);
+ if(result != QSPI_STATUS_OK) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Write failed");
+ }
return result;
}
@@ -1251,21 +1251,21 @@ qspi_status_t QSPIFBlockDevice::_qspiSendProgramCommand(unsigned int progInst, c
qspi_status_t QSPIFBlockDevice::_qspiSendEraseCommand(unsigned int eraseInst, bd_addr_t addr, bd_size_t size)
{
// Check the address and size fit onto the chip.
- //MBED_ASSERT(is_valid_erase(addr, size));
-
- qspi_status_t result = QSPI_STATUS_OK;
-
- result = _qspi.command_transfer(eraseInst, // command to send
- (((int)addr) & 0x00FFF000), // Align addr to 4096
- NULL, // do not transmit
- 0, // do not transmit
- NULL, // just receive two bytes of data
- 0); // store received values in status_value
- if (QSPI_STATUS_OK != result) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase failed");
- }
+ //MBED_ASSERT(is_valid_erase(addr, size));
+
+ qspi_status_t result = QSPI_STATUS_OK;
+
+ result = _qspi.command_transfer(eraseInst, // command to send
+ (((int)addr) & 0x00FFF000), // Align addr to 4096
+ NULL, // do not transmit
+ 0, // do not transmit
+ NULL, // just receive two bytes of data
+ 0); // store received values in status_value
+ if (QSPI_STATUS_OK != result) {
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR: QSPI Erase failed");
+ }
- return result;
+ return result;
}
@@ -1274,10 +1274,10 @@ qspi_status_t QSPIFBlockDevice::_qspiSendGeneralCommand(unsigned int instruction
{
- qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length);
+ qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length);
if (QSPI_STATUS_OK != status) {
- QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR:Sending Generic command: %x", instruction);
+ QSPIF_LOG(QSPIF_DEBUG_ERROR,"ERROR:Sending Generic command: %x", instruction);
}
return status;
@@ -1286,7 +1286,7 @@ qspi_status_t QSPIFBlockDevice::_qspiSendGeneralCommand(unsigned int instruction
qspi_status_t QSPIFBlockDevice::_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)
{
- _qspi.configure_format( inst_width, address_width, address_size, alt_width, alt_size, data_width, dummy_cycles);
+ _qspi.configure_format( inst_width, address_width, address_size, alt_width, alt_size, data_width, dummy_cycles);
return QSPI_STATUS_OK;
}