regarding the QSPI example merging with my application with other interruptions

Hi Nordic,

I am using your QSPI example code and make it into functions for my application. The code could run if I block the rest part of my code and only run the QSPI part. But when I add the rest of the application code, the QSPI function is not working. Could you please help to suggest how to fix this issue?

I am using the SDK 17.0.2

1. here is my main function part of the code , when I disable  the line 41-45, then the QSPI read and write works fine.

Else(when I enable) it reports errors below 

<error> app: ERROR 16 [NRF_ERROR_INVALID_ADDR] at D:\nRF5_SDK_17.0.2_d674dde\examples\nrf52840_222\ble_app_uart_peripheral\test\data_storage.c:301
PC at: 0x0002B261, It reports errors when calling "nrf_drv_qspi_write", my guessing is nrf_drv_qspi_init is not properly initialized wither.  

//@brief Application main function.

int main(void)
   {
	   
	  
    //gpio_output_voltage_setup_3v3();    //
	//NRF_LOG_INFO("\nTT\n");nrf_delay_ms(10);
    #ifdef  WATCHDOG_ENABLE
        start_watchdog();
    #endif
    
    gpio_output_voltage_setup(); 
    //gpio_output_voltage_setup_1_8();
    bool erase_bonds;
    uint8_t find_flag=0;
    AxesRaw_t data;

    log_init();
    
    store_data(); //Here is the QSPI function calling 

   
    //NRF_LOG_DEFAULT_BACKENDS_INIT();
    nrf_gpio_cfg_output(BLUE_LED);
	
	NRF_LOG_INFO("\nTT\n");nrf_delay_ms(10);

    //store_data(); //flash memory chipset test 
    //store_data(); //flash memory chipset test 
   
   #ifdef DEBUG_UART_INFO_RTT
	NRF_LOG_INFO("\nstart.\n");nrf_delay_ms(10);
	#endif
	
    nrf_gpio_cfg_output(BSP_BOARD_LED_0);

    nrf_gpio_cfg_output(IMU_POWER_PIN);
    nrf_gpio_pin_set(IMU_POWER_PIN); 
   
    // the code below added which cause the QSPI not running
    LIS3DH_Init(); 
    power_management_init();
    interrupt_pin_init();
    saadc_init();
}

2. the code for the function of QSPI is attached. 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "nrf_drv_qspi.h"
#include "nrf_delay.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "boards.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "sdk_config.h"

#define QSPI_STD_CMD_WRSR   0x01
#define QSPI_STD_CMD_RSTEN  0x66
#define QSPI_STD_CMD_RST    0x99

#define QSPI_TEST_DATA_SIZE 256

#define WAIT_FOR_PERIPH() do { \
        while (!m_finished) {} \
        m_finished = false;    \
    } while (0)

static volatile bool m_finished = false;
static uint8_t m_buffer_tx[QSPI_TEST_DATA_SIZE];
static uint8_t m_buffer_rx[QSPI_TEST_DATA_SIZE];

static void qspi_handler(nrf_drv_qspi_evt_t event, void * p_context)
{
    UNUSED_PARAMETER(event);
    UNUSED_PARAMETER(p_context);
    m_finished = true;
}

static void configure_memory()
{
    uint8_t temporary = 0x40;
    uint32_t err_code;
    nrf_qspi_cinstr_conf_t cinstr_cfg = {
        .opcode    = QSPI_STD_CMD_RSTEN,
        .length    = NRF_QSPI_CINSTR_LEN_1B,
        .io2_level = true,
        .io3_level = true,
        .wipwait   = true,
        .wren      = true
    };

    // Send reset enable
    err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    // Send reset command
    cinstr_cfg.opcode = QSPI_STD_CMD_RST;
    err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    // Switch to qspi mode
    cinstr_cfg.opcode = QSPI_STD_CMD_WRSR;
    cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B;
    err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, &temporary, NULL);
    APP_ERROR_CHECK(err_code);
}


int store_data(void)
{
    uint32_t i;
    uint32_t err_code;

    err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    //NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO(""
                 "QSPI write and read example using 24bit addressing mode");

    srand(0);
    for (i = 0; i < QSPI_TEST_DATA_SIZE; ++i)
    {
        m_buffer_tx[i] = (uint8_t)rand();
        NRF_LOG_RAW_INFO("%2X ",m_buffer_tx[i]);
    }

    nrf_drv_qspi_config_t config = NRF_DRV_QSPI_DEFAULT_CONFIG;

    err_code = nrf_drv_qspi_init(&config, qspi_handler, NULL);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_INFO("QSPI example started.");

    configure_memory();

    m_finished = false;
    //err_code = nrf_drv_qspi_erase(NRF_QSPI_ERASE_LEN_64KB, 0);
    err_code = nrf_drv_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, 0);
    APP_ERROR_CHECK(err_code);
    WAIT_FOR_PERIPH();
    NRF_LOG_INFO("Process of erasing first block start");

    err_code = nrf_drv_qspi_write(m_buffer_tx, QSPI_TEST_DATA_SIZE, 0);
    APP_ERROR_CHECK(err_code);
    WAIT_FOR_PERIPH();
    NRF_LOG_INFO("Process of writing data start");
    for (i = 0; i < QSPI_TEST_DATA_SIZE; ++i)
    {
        NRF_LOG_RAW_INFO("%2X ",m_buffer_rx[i]);
    }

    err_code = nrf_drv_qspi_read(m_buffer_rx, QSPI_TEST_DATA_SIZE, 0);
    WAIT_FOR_PERIPH();
    NRF_LOG_INFO("Data read");

    for (i = 0; i < QSPI_TEST_DATA_SIZE; ++i)
    {
        NRF_LOG_RAW_INFO("%2X ",m_buffer_rx[i]);
    }



    NRF_LOG_INFO("Compare...");
    if (memcmp(m_buffer_tx, m_buffer_rx, QSPI_TEST_DATA_SIZE) == 0)
    {
        NRF_LOG_INFO("Data consistent");
    }
    else
    {
        NRF_LOG_INFO("Data inconsistent");
    }

    nrf_drv_qspi_uninit();


}

3. Here some interruption level I have setup. I wondering is it the interruption level cause the issues?

#ifndef GPIOTE_CONFIG_IRQ_PRIORITY
#define GPIOTE_CONFIG_IRQ_PRIORITY 7 
#endif

#ifndef SPI_DEFAULT_CONFIG_IRQ_PRIORITY
#define SPI_DEFAULT_CONFIG_IRQ_PRIORITY 6
#endif

#ifndef NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY
#define NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 6
#endif

#ifndef NRFX_QSPI_CONFIG_IRQ_PRIORITY
#define NRFX_QSPI_CONFIG_IRQ_PRIORITY 6

// </e>

// <e> NRFX_QSPI_ENABLED - nrfx_qspi - QSPI peripheral driver
//==========================================================
#ifndef NRFX_QSPI_ENABLED
#define NRFX_QSPI_ENABLED 1//
#endif
// <o> NRFX_QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns).  <0-255> 


#ifndef NRFX_QSPI_CONFIG_SCK_DELAY
#define NRFX_QSPI_CONFIG_SCK_DELAY 1
#endif

// <o> NRFX_QSPI_CONFIG_XIP_OFFSET - Address offset in the external memory for Execute in Place operation. 
#ifndef NRFX_QSPI_CONFIG_XIP_OFFSET
#define NRFX_QSPI_CONFIG_XIP_OFFSET 0
#endif

// <o> NRFX_QSPI_CONFIG_READOC  - Number of data lines and opcode used for reading.
 
// <0=> FastRead 
// <1=> Read2O 
// <2=> Read2IO 
// <3=> Read4O 
// <4=> Read4IO 

#ifndef NRFX_QSPI_CONFIG_READOC
#define NRFX_QSPI_CONFIG_READOC 0
#endif

// <o> NRFX_QSPI_CONFIG_WRITEOC  - Number of data lines and opcode used for writing.
 
// <0=> PP 
// <1=> PP2O 
// <2=> PP4O 
// <3=> PP4IO 

#ifndef NRFX_QSPI_CONFIG_WRITEOC
#define NRFX_QSPI_CONFIG_WRITEOC 0
#endif

// <o> NRFX_QSPI_CONFIG_ADDRMODE  - Addressing mode.
 
// <0=> 24bit 
// <1=> 32bit 

#ifndef NRFX_QSPI_CONFIG_ADDRMODE
#define NRFX_QSPI_CONFIG_ADDRMODE 0
#endif

// <o> NRFX_QSPI_CONFIG_MODE  - SPI mode.
 
// <0=> Mode 0 
// <1=> Mode 1 

#ifndef NRFX_QSPI_CONFIG_MODE
#define NRFX_QSPI_CONFIG_MODE 0
#endif

// <o> NRFX_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 NRFX_QSPI_CONFIG_FREQUENCY
#define NRFX_QSPI_CONFIG_FREQUENCY 15
#endif

// <s> NRFX_QSPI_PIN_SCK - SCK pin value.
#ifndef NRFX_QSPI_PIN_SCK
#define NRFX_QSPI_PIN_SCK 19// NRF_QSPI_PIN_NOT_CONNECTED
#endif

// <s> NRFX_QSPI_PIN_CSN - CSN pin value.
#ifndef NRFX_QSPI_PIN_CSN
#define NRFX_QSPI_PIN_CSN 17//NRF_QSPI_PIN_NOT_CONNECTED
#endif

// <s> NRFX_QSPI_PIN_IO0 - IO0 pin value.
#ifndef NRFX_QSPI_PIN_IO0
#define NRFX_QSPI_PIN_IO0 20// NRF_QSPI_PIN_NOT_CONNECTED
#endif

// <s> NRFX_QSPI_PIN_IO1 - IO1 pin value.
#ifndef NRFX_QSPI_PIN_IO1
#define NRFX_QSPI_PIN_IO1 21// NRF_QSPI_PIN_NOT_CONNECTED
#endif

// <s> NRFX_QSPI_PIN_IO2 - IO2 pin value.
#ifndef NRFX_QSPI_PIN_IO2
#define NRFX_QSPI_PIN_IO2 22// NRF_QSPI_PIN_NOT_CONNECTED
#endif

// <s> NRFX_QSPI_PIN_IO3 - IO3 pin value.
#ifndef NRFX_QSPI_PIN_IO3
#define NRFX_QSPI_PIN_IO3 23//NRF_QSPI_PIN_NOT_CONNECTED
#endif

// <o> NRFX_QSPI_CONFIG_IRQ_PRIORITY  - Interrupt priority
 
// <0=> 0 (highest) 
// <1=> 1 
// <2=> 2 
// <3=> 3 
// <4=> 4 
// <5=> 5 
// <6=> 6 
// <7=> 7 

#ifndef NRFX_QSPI_CONFIG_IRQ_PRIORITY
#define NRFX_QSPI_CONFIG_IRQ_PRIORITY  6 
#endif

// </e>

// <e> NRFX_RNG_ENABLED - nrfx_rng - RNG peripheral driver

Parents
  • Hello,

    Please use '__ALIGN(4)' when defining the your tx buffer array to ensure it always starts at a word-aligned address as required by the QSPI peripheral. The write call will return with NRF_ERROR_INVALID_ADDR if the source address is not aligned to a word boundary.

    Register description stating that source pointer must be word aligned

    Defining the buffers with the ALIGN keyword

    __ALIGN(4) static uint8_t m_buffer_tx[QSPI_TEST_DATA_SIZE];
    __ALIGN(4) static uint8_t m_buffer_rx[QSPI_TEST_DATA_SIZE];

    Best regards,

    Vidar

  • Thank you, Now it works fine with your suggested modification. 

    Strangely that the official example did not use the __ALIGN(4), and itself still run to be fine . Also that QSPI_TEST_DATA_SIZE equals to 256, which equals the 64*4 bytes= 64 words, should theoretically fine. Also in the QSPI official example(below D:\nRF5_SDK_17.0.2_d674dde\examples\peripheral\qspi\pca10056\blank\ses ) not using the __ALIGN(4). 

  • Thanks for the update. Yes, we should have used __ALIGN(4) or changed the type to a uint32_t in the example code. Now there is always the risk that the linker may decide to place the array at an unaligned start address like what happened in your case.

    Also, as you experienced, it doesn't help that the array size is a multiple of 4.

Reply Children
No Data
Related