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> 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
|
||||
//==========================================================
|
||||
#ifndef TIMER_ENABLED
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
"STCLK_OFF_DURING_SLEEP",
|
||||
"TRNG",
|
||||
"USTICKER"
|
||||
"USTICKER",
|
||||
"QSPI"
|
||||
],
|
||||
"extra_labels": [
|
||||
"NORDIC",
|
||||
|
|
Loading…
Reference in New Issue