154 lines
3.5 KiB
C
154 lines
3.5 KiB
C
/*
|
|
* 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 <stdint.h>
|
|
#include "board.h"
|
|
#include "nrfx_qspi.h"
|
|
#if defined(PKG_USING_FAL)
|
|
#include <fal.h>
|
|
|
|
//log
|
|
#include <rtdbg.h>
|
|
#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
|