This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Not able to initalize the QSPI module.

Hi Everyone

*ITS VERY URGENT ISSUE*.

I am using nrf52840 PDK with segger embedded IDE. 

I was trying to use the QSPI module to write data to the external flash memory.

But I am not able to initialize the QSPI module.

It throws error "NRF_TIMEOUT_ERROR" after the init function is called.

What is the reason for this problem and how can it be solved.

Following are the linker section placement macros : 

FLASH_PH_START=0x0

FLASH_PH_SIZE=0x100000

RAM_PH_START=0x20000000

RAM_PH_SIZE=0x40000

FLASH_START=0x26000(My code is running BLE alongwith FREERTOS)

FLASH_SIZE=0x100000

RAM_START=0x20002A98

RAM_SIZE=0x3D568

If any other information is required , please revert back.

Thanks!

  • /**
     * Copyright (c) 2014 - 2018, 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 form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
     * 
     */
    /** @file
     *
     * @defgroup ble_sdk_uart_over_ble_main main.c
     * @{
     * @ingroup  ble_sdk_app_nus_eval
     * @brief    UART over BLE application main file.
     *
     * This file contains the source code for a sample application that uses the Nordic UART service.
     * This application uses the @ref srvlib_conn_params module.
     */
    
    #define TASK_DELAY        80           /**< No of ticks */
    
    #include "BLE_INTERRA.h"
    #include "UART.h"
    #include "FreeRTOS.h"
    #include "task.h"
    #include "timers.h"
    #include "nordic_common.h"
    #include "nrf_drv_clock.h"
    #include "sdk_errors.h"
    #include "semphr.h"
    
    #include "nrf_drv_qspi.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.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
    
    
    
    TaskHandle_t led_toggle_task0_handle;
    TaskHandle_t led_toggle_task1_handle;
    TaskHandle_t led_toggle_task2_handle;
    TaskHandle_t led_toggle_task3_handle;
    TaskHandle_t uart_put_char_task_handle;
    TaskHandle_t ble_put_task_handle;
    
    #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 uint16_t   m_conn_handle          = BLE_CONN_HANDLE_INVALID;                 /**< Handle of the current connection. */
    static uint16_t   m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3;            /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
    
    static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
    {
        {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
    };
    
    static void configure_memory();
    void write_and_check();
    
    static void qspi_handler(nrf_drv_qspi_evt_t event, void * p_context)
    {
        UNUSED_PARAMETER(event);
        UNUSED_PARAMETER(p_context);
        m_finished = true;
    }
    
    
    
    /*
    FREE RTOS FUNCTIONS 
    */
    
    void led_toggle_task0_function (void * pvParameter)
    {
        UNUSED_PARAMETER(pvParameter);
        TickType_t xLastWakeTime;
     const TickType_t xFrequency = TASK_DELAY;
     xLastWakeTime = xTaskGetTickCount();
        
        while (true)
        {
            
            bsp_board_led_invert(BSP_BOARD_LED_0);
           vTaskDelayUntil( &xLastWakeTime, xFrequency );
            /* Delay a task for a given number of ticks */
           
            
    
            /* Tasks must be implemented to never return... */
        }
    }
    
    void led_toggle_task1_function (void * pvParameter)
    {
        UNUSED_PARAMETER(pvParameter);
         TickType_t xLastWakeTime;
     const TickType_t xFrequency = TASK_DELAY;
     xLastWakeTime = xTaskGetTickCount();
        
        while (true)
        {   
            
            bsp_board_led_invert(BSP_BOARD_LED_1);
    
            /* Delay a task for a given number of ticks */
           vTaskDelayUntil( &xLastWakeTime, xFrequency );
            
            /* Tasks must be implemented to never return... */
        }
    }
    
    void led_toggle_task2_function (void * pvParameter)
    {
        UNUSED_PARAMETER(pvParameter);
        
           TickType_t xLastWakeTime;
     const TickType_t xFrequency =TASK_DELAY;
     xLastWakeTime = xTaskGetTickCount();
      
        while (true)
        {
       
            bsp_board_led_invert(BSP_BOARD_LED_2);
    
            /* Delay a task for a given number of ticks */
             vTaskDelayUntil( &xLastWakeTime, xFrequency );
            
            /* Tasks must be implemented to never return... */
        }
    }
    void led_toggle_task3_function (void * pvParameter)
    {
        UNUSED_PARAMETER(pvParameter);
               TickType_t xLastWakeTime;
     const TickType_t xFrequency = TASK_DELAY;
     xLastWakeTime = xTaskGetTickCount();
        
        while (true)
        {
        
            bsp_board_led_invert(BSP_BOARD_LED_3);
    
            /* Delay a task for a given number of ticks */
            vTaskDelayUntil( &xLastWakeTime, xFrequency );
            
           
            /* Tasks must be implemented to never return... */
        }
    }
    void uart_put_char_task_function(void * pvParameter)
    {
    UNUSED_PARAMETER(pvParameter);
    
     TickType_t xLastWakeTime;
     const TickType_t xFrequency = TASK_DELAY;
     xLastWakeTime = xTaskGetTickCount();
    int uart_rx=8;
    int uart_tx=6;
    char val='R';
    char *val_str="Hey You! by Pink Floyd";
    uart_init_terra(uart_rx,uart_tx);
    while(1)
    {
        uart_write_char('d');
        uart_write_data(val_str);
       
       
       vTaskDelayUntil( &xLastWakeTime, xFrequency );
       
    
    }
    
    
    }
    
    void ble_put_task_function(void * pvParameter)
    {
    UNUSED_PARAMETER(pvParameter);
    
    TickType_t xLastWakeTime;
     const TickType_t xFrequency = TASK_DELAY;
     xLastWakeTime = xTaskGetTickCount();
    char *my_data="Mydata123#@12";
    
    
    init_ble();
    while(1)
    {
    
        start(my_data);
        vTaskDelayUntil(&xLastWakeTime, xFrequency );
       
    }
    }
    
    
    
    
    int main(void)
    {
         
        //printf("Before Task Creation : %d\n",xPortGetFreeHeapSize());
       ret_code_t err_code;
      
        /* Initialize clock driver for better time accuracy in FREERTOS */
        err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
       write_and_check();
        /* Configure LED-pins as outputs */
        //bsp_board_init(BSP_INIT_LEDS);
      
       
      // bsp_board_led_invert(BSP_BOARD_LED_1)
      UNUSED_VARIABLE(xTaskCreate(led_toggle_task0_function, "L0", configMINIMAL_STACK_SIZE+50 , NULL, 2, &led_toggle_task0_handle));
      //UNUSED_VARIABLE(xTaskCreate(led_toggle_task1_function, "L1", configMINIMAL_STACK_SIZE+30 , NULL, 2, &led_toggle_task1_handle));
     //UNUSED_VARIABLE(xTaskCreate(led_toggle_task2_function, "L2", configMINIMAL_STACK_SIZE+30 , NULL, 2, &led_toggle_task2_handle));
     //UNUSED_VARIABLE(xTaskCreate(led_toggle_task3_function, "L3", configMINIMAL_STACK_SIZE+30 , NULL, 2, &led_toggle_task3_handle));
    //UNUSED_VARIABLE(xTaskCreate(uart_put_char_task_function, "U1", configMINIMAL_STACK_SIZE + 100, NULL,1, &uart_put_char_task_handle));
      //UNUSED_VARIABLE(xTaskCreate(ble_put_task_function, "le",configMINIMAL_STACK_SIZE + 200, NULL, 2, &ble_put_task_handle));  
        
        /* Activate deep sleep mode */
       //SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
      
        //printf("After Task Creation : %d\n",xPortGetFreeHeapSize());
        /* Start FreeRTOS scheduler. */
      vTaskStartScheduler();
        while(1);
    
    }
    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);
    }
    
    
    
    
    void write_and_check()
    {
    
         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");
    
        
        for (i = 0; i < QSPI_TEST_DATA_SIZE; ++i)
        {
            m_buffer_tx[i] = 52;
        }
    
        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_4KB, 0);
        APP_ERROR_CHECK(err_code);
        WAIT_FOR_PERIPH();
        NRF_LOG_INFO("Proc ess 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");
    
        err_code = nrf_drv_qspi_read(m_buffer_rx, QSPI_TEST_DATA_SIZE, 0);
        WAIT_FOR_PERIPH();
        NRF_LOG_INFO("Data read");
        NRF_LOG_INFO("%d",m_buffer_rx[2]);
        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();
    
       
    }

    Here is the code that i have been using

  • Which functioncall is returning NRF_TIMEOUT_ERROR? I can't see this error code used in the QSPI driver. Which QSPI device are you interfacing? Have you checked that the connections are correct?

    Which SDK version are you using? I would recommend that you switch to using the nRF52840-DK.

  • I am using 15.0 version of SDK. 

    nrf_drv_qspi_init() function is throwing error. 

    I am using nrf52840 PDK and QSPI device is the onboard external memory of 64Mb( mx25R6435F ,  , so the connections would be correct ).

  • Did you test the QSPI Example from the SDK, to make sure the board/device is working as expected?

Related