Hello,
I am currently having issues with storing structure data in nRF52840 DK external flash. The default QSPI example present in peripheral sections work fine. But in my use case i have to store structured data instead of simple data types. I have worked with storing structured data in flash with STM boards so i know how to store data in flash.
But for some reason whenever i try to write structure data using QSPI example it always read out 0XFF which means the write operation didn't worked. But the write operation returns Success as return value.
For Example:
My code implementation with STM board which i want to achieve with nRF52840 DK boards:
/* USER CODE END PTD */ typedef struct { char name[20]; uint8_t age; uint8_t height; uint8_t weight; } Player, *PlayerPtr; Player player1 = {.name="xhabja",.age = 26,.height=165, .weight=80}; Player player2 = {.name="sahgd",.age = 54,.height=160, .weight=75}; Player player3 = {.name="asdia",.age = 50,.height=155, .weight=70}; Player player4 = {.name="manona",.age = 30,.height=150, .weight=65}; Player player5 = {.name="uythui",.age = 3,.height=40, .weight=20}; //List of my structure Player player_data[5] = {player1,player2,player3,player4,player5}; //Writing structure data into the Flash for (int i=0;i<5;i++){ QSPI_Flash_Write_Byte(addr,(uint8_t*) &(player_data[i]), sizeof(Player)); addr = addr + sizeof(Player); HAL_Delay(50); } ///And this would be my Read Function reading data in structured format from flash void Flash_ReadPage(void) { PlayerPtr p1ptr; uint8_t rcv[sizeof(Player)]; uint32_t addr = 0x000000; Serial.PrintString("Reading structure from page\r\n",DEBUG_PORT); for (int j=0;j<5;j++){ rcv[sizeof(Player)]= "\0"; //Reading data into buffer QSPI_Flash_Read_Byte(addr,rcv,sizeof(Player)); //type casting rxbuf into structure pointer p1ptr = (PlayerPtr*)&rcv; Serial.PrintString("Name: ",DEBUG_PORT); Serial.PrintString(p1ptr->name,DEBUG_PORT); Serial.PrintString(" Age: ",DEBUG_PORT); Serial.PrintInteger(p1ptr->age,DEBUG_PORT); Serial.PrintString(" Height: ",DEBUG_PORT); Serial.PrintInteger(p1ptr->height,DEBUG_PORT); Serial.PrintString(" Weight: ",DEBUG_PORT); Serial.PrintInteger(p1ptr->weight,DEBUG_PORT); Serial.PrintString("\r\n",DEBUG_PORT); //Incrementing to next structure addr = addr + sizeof(Player); HAL_Delay(100); } Serial.PrintString("Reading Completed\r\n",DEBUG_PORT); }
Here is my main.c file for QSPI example trying to achieve the above but without any success.
/** * Copyright (c) 2016 - 2020, 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 qspi_example_main main.c * @{ * @ingroup qspi_example * * @brief QSPI Example Application main file. * * This file contains the source code for a sample application using QSPI. */ #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); } typedef struct { char name[20]; uint8_t age; uint8_t height; uint8_t weight; } Player, *PlayerPtr; int main(void) { uint32_t i; uint32_t err_code; err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); Player player1 = {.name="xhabja",.age = 26,.height=165, .weight=80}; Player player2 = {.name="sahgd",.age = 54,.height=160, .weight=75}; Player player3 = {.name="asdia",.age = 50,.height=155, .weight=70}; Player player4 = {.name="manona",.age = 30,.height=150, .weight=65}; Player player5 = {.name="uythui",.age = 3,.height=40, .weight=20}; Player player_data[5] = {player1,player2,player3,player4,player5}; 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_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); APP_ERROR_CHECK(err_code); WAIT_FOR_PERIPH(); NRF_LOG_INFO("Process of erasing first block start"); uint32_t addr = 0x00000000; for (int i=0;i<1;i++) { err_code = nrf_drv_qspi_write((uint8_t*) &(player_data[i]), sizeof(Player), addr); APP_ERROR_CHECK(err_code); WAIT_FOR_PERIPH(); NRF_LOG_INFO("Process of writing data start"); addr = addr + sizeof(Player); nrf_delay_ms(1000); } err_code = nrf_drv_qspi_read(m_buffer_rx, QSPI_TEST_DATA_SIZE, addr); WAIT_FOR_PERIPH(); NRF_LOG_INFO("Data read"); NRF_LOG_RAW_HEXDUMP_INFO(m_buffer_rx,QSPI_TEST_DATA_SIZE); NRF_LOG_INFO("Data read"); nrf_drv_qspi_uninit(); for (;;) { } } /** @} */
Can anyone please help me and tell how could i store and read structured data using QSPI example in NRF5 SDK ?