mirror of https://github.com/ARMmbed/mbed-os.git
QSPI: initial HAL nrf52840 version
This commit adds QSPI HAL implementation for nrf52840 MCU targetspull/7783/head
parent
a3c8117b0e
commit
d1b51b6328
|
@ -2748,6 +2748,136 @@
|
||||||
|
|
||||||
// </e>
|
// </e>
|
||||||
|
|
||||||
|
// <e> QSPI_ENABLED - nrf_drv_qspi - QSPI peripheral driver.
|
||||||
|
//==========================================================
|
||||||
|
#ifndef QSPI_ENABLED
|
||||||
|
#define QSPI_ENABLED 1
|
||||||
|
#endif
|
||||||
|
#if QSPI_ENABLED
|
||||||
|
// <o> 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
|
||||||
|
|
||||||
|
// <o> 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
|
||||||
|
|
||||||
|
// <o> 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
|
||||||
|
|
||||||
|
// <o> QSPI_CONFIG_ADDRMODE - Addressing mode.
|
||||||
|
|
||||||
|
// <0=> 24bit
|
||||||
|
// <1=> 32bit
|
||||||
|
|
||||||
|
#ifndef QSPI_CONFIG_ADDRMODE
|
||||||
|
#define QSPI_CONFIG_ADDRMODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <o> QSPI_CONFIG_MODE - SPI mode.
|
||||||
|
|
||||||
|
// <0=> Mode 0
|
||||||
|
// <1=> Mode 1
|
||||||
|
|
||||||
|
#ifndef QSPI_CONFIG_MODE
|
||||||
|
#define QSPI_CONFIG_MODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <o> 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
|
||||||
|
|
||||||
|
// <s> QSPI_PIN_SCK - SCK pin value.
|
||||||
|
#ifndef QSPI_PIN_SCK
|
||||||
|
#define QSPI_PIN_SCK NRF_QSPI_PIN_NOT_CONNECTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <s> QSPI_PIN_CSN - CSN pin value.
|
||||||
|
#ifndef QSPI_PIN_CSN
|
||||||
|
#define QSPI_PIN_CSN NRF_QSPI_PIN_NOT_CONNECTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <s> QSPI_PIN_IO0 - IO0 pin value.
|
||||||
|
#ifndef QSPI_PIN_IO0
|
||||||
|
#define QSPI_PIN_IO0 NRF_QSPI_PIN_NOT_CONNECTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <s> QSPI_PIN_IO1 - IO1 pin value.
|
||||||
|
#ifndef QSPI_PIN_IO1
|
||||||
|
#define QSPI_PIN_IO1 NRF_QSPI_PIN_NOT_CONNECTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <s> QSPI_PIN_IO2 - IO2 pin value.
|
||||||
|
#ifndef QSPI_PIN_IO2
|
||||||
|
#define QSPI_PIN_IO2 NRF_QSPI_PIN_NOT_CONNECTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <s> QSPI_PIN_IO3 - IO3 pin value.
|
||||||
|
#ifndef QSPI_PIN_IO3
|
||||||
|
#define QSPI_PIN_IO3 NRF_QSPI_PIN_NOT_CONNECTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// <o> QSPI_CONFIG_IRQ_PRIORITY - Interrupt priority
|
||||||
|
|
||||||
|
|
||||||
|
// <i> 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
|
||||||
|
|
||||||
|
// </e>
|
||||||
|
|
||||||
|
// </e>
|
||||||
|
|
||||||
// <e> TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver
|
// <e> TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver
|
||||||
//==========================================================
|
//==========================================================
|
||||||
#ifndef TIMER_ENABLED
|
#ifndef TIMER_ENABLED
|
||||||
|
|
|
@ -142,6 +142,17 @@ struct flash_s {
|
||||||
uint32_t placeholder;
|
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"
|
#include "gpio_object.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
/** @}*/
|
|
@ -3873,7 +3873,8 @@
|
||||||
"SPI_ASYNCH",
|
"SPI_ASYNCH",
|
||||||
"STCLK_OFF_DURING_SLEEP",
|
"STCLK_OFF_DURING_SLEEP",
|
||||||
"TRNG",
|
"TRNG",
|
||||||
"USTICKER"
|
"USTICKER",
|
||||||
|
"QSPI"
|
||||||
],
|
],
|
||||||
"extra_labels": [
|
"extra_labels": [
|
||||||
"NORDIC",
|
"NORDIC",
|
||||||
|
|
Loading…
Reference in New Issue