/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-04-29 supperthomas first version * */ #include #include "board.h" #include "nrfx_qspi.h" #if defined(RT_USING_FAL) #include //log #include #define LOG_TAG "drv.qspiflash" #define WAIT_FOR_PERIPH() do { \ while (!m_finished) {} \ m_finished = false; \ } while (0) static volatile bool m_finished = false; static void qspi_handler(nrfx_qspi_evt_t event, void *p_context) { m_finished = true; } static void configure_memory() { #define QSPI_STD_CMD_WRSR 0x01 #define QSPI_STD_CMD_RSTEN 0x66 #define QSPI_STD_CMD_RST 0x99 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 = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); if (NRFX_SUCCESS != err_code) { LOG_E("\r\n ERROR: QSPI_STD_CMD_RSTEN:0x%x\n", err_code); return ; } // Send reset command cinstr_cfg.opcode = QSPI_STD_CMD_RST; err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); if (NRFX_SUCCESS != err_code) { LOG_E("\r\n ERROR: QSPI_STD_CMD_RST:0x%x\n", err_code); return ; } // Switch to qspi mode cinstr_cfg.opcode = QSPI_STD_CMD_WRSR; cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B; err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, &temporary, NULL); if (NRFX_SUCCESS != err_code) { LOG_E("\r\n ERROR: QSPI_STD_CMD_WRSR:0x%x\n", err_code); return; } } static int init(void) { uint32_t err_code; nrfx_qspi_config_t config = NRFX_QSPI_DEFAULT_CONFIG(BSP_QSPI_SCK_PIN, BSP_QSPI_CSN_PIN, BSP_QSPI_IO0_PIN, BSP_QSPI_IO1_PIN, BSP_QSPI_IO2_PIN, BSP_QSPI_IO3_PIN); err_code = nrfx_qspi_init(&config, qspi_handler, NULL); if (NRFX_SUCCESS != err_code) { LOG_E("\r\n ERROR: QSPI_init:0x%x\n", err_code); return -1; } configure_memory(); return 0; } static int read(long offset, uint8_t *buf, size_t size) { uint32_t err_code; m_finished = false; err_code = nrfx_qspi_read(buf, size, offset); WAIT_FOR_PERIPH(); if (NRFX_SUCCESS == err_code) { return size; } else { LOG_E("\r\n ERROR: read:0x%x\n", err_code); return -1; } } static int write(long offset, const uint8_t *buf, size_t size) { uint32_t err_code; m_finished = false; err_code = nrfx_qspi_write(buf, size, offset); WAIT_FOR_PERIPH(); if (NRFX_SUCCESS == err_code) { return size; } else { LOG_E("\r\n ERROR: write:0x%x\n", err_code); return -1; } } static int erase(long offset, size_t size) { uint32_t err_code; m_finished = false; err_code = nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_64KB, offset); WAIT_FOR_PERIPH(); if (NRFX_SUCCESS == err_code) { return size; } else { LOG_E("\r\n ERROR: erase:0x%x\n", err_code); return -1; } } struct fal_flash_dev nor_flash0 = { .name = NOR_FLASH_DEV_NAME, .addr = 0, .len = QSPI_FLASH_SIZE_KB * 1024, .blk_size = 4096, .ops = {init, read, write, erase}, .write_gran = 1 }; #endif