QSPI: initial HAL nrf52840 version

This commit adds QSPI HAL implementation for nrf52840 MCU targets
pull/7783/head
Martin Kojtal 2017-11-10 12:24:13 +00:00 committed by Maciej Bocianski
parent a3c8117b0e
commit d1b51b6328
4 changed files with 357 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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
/** @}*/

View File

@ -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",