• 公開日:2026年03月04日

RA0E1マイコンでSPI Flash Memoryを動かす

メモリ足りてますか?

突然ですが、メモリは足りてますか?
「あと少し容量があれば…」という場面は、組み込み開発では珍しくありません。そんなとき、外付けのSPI Flash Memoryは手軽で強力な選択肢になります。
今回はRA0E1マイコンとSPI Flash Memory Moduleを使い、配線から読み書きまでを実際に動かして確認していきます。

この記事でできるようになること

  • RA0E1の簡易SPIでSPI Flash Memoryを制御する
  • SPI Flash MemoryのJEDEC IDを読む
  • SPI Flash Memoryのデータ読み書き

必要なもの

配線と簡易SPIの設定

RA0E1マイコンとSPI Flash Memory Moduleの接続ですが、今回使用したモジュールはシンプルなSPI接続(Single SPI)のみとなっているため、電源線(VCC、GND)とSPI制御に必要な4本の信号線の合計6本の線をつなぎます。

RA0E1マイコンのSPI設定

RA0E1マイコンは、SPI専用の通信ペリフェラルを搭載していません。そのため、SAU(Serial Array Unit)の簡易SPIを用いて、SPI Flash Memoryモジュールと接続する必要があります。また、SAUの簡易SPIは3線式のためCS信号(チップセレクト)はユーザプログラムで制御する必要があります。今回はGPIOのP103端子をCS信号に割り当てて制御を行います。

RA0E1マイコンのSAU構成

RA0E1マイコンのSAUは以下の表の構成となっています。今回はユニット0のチャネル0(SPI00)を使用します。

RA0E1マイコン 32ピン製品のSAU機能割り当て
ユニット チャネル 簡易 SPI UART 簡易 I2C
0 0 SPI00 UART0 IIC00
1
2 UART1
3 SPI11 IIC11
1 0 SPI20 UART2(LIN バス対応) IIC20
1

SPI00の場合、SPI Clock信号はピン番号22の端子、SPI MOSI(Master Out-Slave In)信号はピン番号23の端子、SPI MISO(Master In-Slave Out)信号はピン番号24の端子に割り当てられています。

SAU SPI00の端子割り当て
ピン番号 RA0E1信号名 機能
22 SCK00_A SPI Clock信号
23 SO00_A SPI MOSI信号
24 SI00_A SPI MISO信号

 

RA0E1マイコンとSPI Flash Memory Moduleの接続

RA0E1マイコンとSPI Flash Memory Moduleとの接続は下図のようになります。

また、FPB RA0E1評価ボードは以下のような端子割り当てになっています。

そのため、実際に接続される際は以下の様にして下さい。

RA0E1マイコンのFSP(RA Flexible Software Package)設定

使用するSPI Flash Memory ModuleにはWinbond社のSerial NOR Flash MemoryであるW25Q64FVが搭載されています。このSerial NOR Flash MemoryのSPI仕様はモード0、および、モード3をサポートしており、最大ビットレートは50MHz(3.0 ~ 3.6V時)となっています。
そのため、RA0E1の簡易SPI設定、IO設定は下図(簡易SPI通信設定、簡易SPI IO設定、GPIO設定)のように設定して下さい。

【FSP設定画面 : 簡易SPI通信設定】

【FSP設定画面 : 簡易SPI IO設定(CLK信号、MOSI信号、MISO信号)】

【FSP設定画面 : GPIO設定(CS信号)】

なお、「Clock Phase」と「Clock Polarity」の設定はFSP SAU SPI Web版ドキュメントに以下のような記載がありますのでご参考ください。

SAU SPIのFSP SPIモード設定
SPIモード / SCRレジスタ:DCP設定 Clock Phase Clock Polarity
SPIモード / 00 : タイプ1(SCK:反転、入力タイミング:立ち上がりエッジ) Data sampling on odd edge, data variation on even edge High when idle
SPIモード / 01 : タイプ2(SCK:非反転、入力タイミング:立ち下がりエッジ) Data sampling on odd edge, data variation on even edge Low when idle
SPIモード / 10 : タイプ3(SCK:反転、入力タイミング:立ち下がりエッジ) Data sampling on even edge, data variation on odd edge High when idle
SPIモード3 / 11 : タイプ4(SCK:非反転、入力タイミング:立ち上がりエッジ) Data sampling on even edge, data variation on odd edge Low when idle

プログラム実装

SPI Flash Memory Moduleに搭載のWinbond W25Q64FVはデファクトスタンダードのコマンド(命令)を用いて制御を行います。様々なコマンドインターフェースを持っていますが、今回の記事では必要最低限のコマンド用いて制御を行います。

実装するコマンドインターフェースの一覧

コマンドインターフェース一覧
コマンド(命令) コマンド値 最大実行時間 機能概要
Release Powerdown 0xAB 3マイクロ秒 パワーダウン解除
JEDEC ID 0x9F JEDEC IDの読み出し
Read Status Register-1 0x05 ステータスレジスタの読み出し
Write Enable 0x06 書き込み許可
Sector Erase (4KB) 0x20 400ミリ秒 セクタ消去
Page Program 0x02 3ミリ秒 データ書き込み
Read Data 0x03 データ読み出し
Chip Erase 0xC7 100秒 チップ消去

初期化(パワーダウン解除)

プログラムコード

W25Q64_Init関数

/* -------------------------------------------------------
 * 初期化
 * ------------------------------------------------------- */
fsp_err_t W25Q64_Init(void)
{
    CS_HIGH();  /* 非選択状態を確定 */

    fsp_err_t err = R_SAU_SPI_Open(&g_spi0_ctrl, &g_spi0_cfg);
    if (FSP_SUCCESS != err) return err;

    /* パワーダウン解除 */
    uint8_t cmd = W25Q64_CMD_RELEASE_POWER_DOWN;
    CS_LOW();
    err = spi_write(&cmd, 1U);
    CS_HIGH();

    /* tRES1 待機(最低3us → 余裕を持って1ms) */
    R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);

    return err;
}

入出力波形

JEDEC IDの読み出し

プログラムコード

W25Q64_ReadJEDECID関数

/* -------------------------------------------------------
 * JEDEC ID 読み出し
 * 正常時:id[0]=0xEF  id[1]=0x40  id[2]=0x17
 * ------------------------------------------------------- */
fsp_err_t W25Q64_ReadJEDECID(uint8_t *id)
{
    uint8_t tx[4] = { W25Q64_CMD_JEDEC_ID, 0xFFU, 0xFFU, 0xFFU };
    uint8_t rx[4] = { 0U };

    CS_LOW();
    fsp_err_t err = spi_write_read(tx, rx, 4U);
    CS_HIGH();

    if (FSP_SUCCESS == err)
    {
        id[0] = rx[1];  /* Manufacturer ID : 0xEF */
        id[1] = rx[2];  /* Memory Type     : 0x40 */
        id[2] = rx[3];  /* Capacity        : 0x17 */
    }
    return err;
}

入出力波形

書き込み許可

プログラムコード

write_enable関数

/* -------------------------------------------------------
 * 書き込み許可
 * ------------------------------------------------------- */
static fsp_err_t write_enable(void)
{
    uint8_t cmd = W25Q64_CMD_WRITE_ENABLE;
    CS_LOW();
    fsp_err_t err = spi_write(&cmd, 1U);
    CS_HIGH();
    return err;
}

入出力波形

ステータスレジスタ読み出し

プログラムコード

read_status1関数

/* -------------------------------------------------------
 * ステータスレジスタ1 読み出し
 * ------------------------------------------------------- */
static fsp_err_t read_status1(uint8_t *status)
{
    uint8_t tx[2] = { W25Q64_CMD_READ_STATUS1, 0xFFU };
    uint8_t rx[2] = { 0U };

    CS_LOW();
    fsp_err_t err = spi_write_read(tx, rx, 2U);
    CS_HIGH();

    if (FSP_SUCCESS == err) *status = rx[1];
    return err;
}

入出力波形

セクタ消去(4KB)

プログラムコード

W25Q64_SectorErase関数

/* -------------------------------------------------------
 * セクタ消去(4KB単位)
 * addr は 4KB 境界アドレス(下位12bitは無視される)
 * ------------------------------------------------------- */
fsp_err_t W25Q64_SectorErase(uint32_t addr)
{
    fsp_err_t err = write_enable();
    if (FSP_SUCCESS != err) return err;

    uint8_t tx[4] = {
        W25Q64_CMD_SECTOR_ERASE,
        (uint8_t)(addr >> 16U),
        (uint8_t)(addr >>  8U),
        (uint8_t)(addr >>  0U)
    };

    CS_LOW();
    err = spi_write(tx, 4U);
    CS_HIGH();

    if (FSP_SUCCESS == err)
    {
        W25Q64_WaitDone();                /* tSE 完了待ち(最大400ms) */
    }
    return err;
}

入出力波形

データ書き込み

プログラムコード

W25Q64_PageProgram関数

/* -------------------------------------------------------
 * ページプログラム(最大256バイト)
 * addr はページ境界(256バイト境界)を推奨
 * ------------------------------------------------------- */
fsp_err_t W25Q64_PageProgram(uint32_t addr, const uint8_t *buf, uint32_t len)
{
    if (len == 0U || len > W25Q64_PAGE_SIZE)
    {
        return FSP_ERR_INVALID_ARGUMENT;
    }

    fsp_err_t err = write_enable();
    if (FSP_SUCCESS != err) return err;

    uint8_t hdr[4] = {
        W25Q64_CMD_PAGE_PROGRAM,
        (uint8_t)(addr >> 16U),
        (uint8_t)(addr >>  8U),
        (uint8_t)(addr >>  0U)
    };

    CS_LOW();                             /* CS アサート */
    err = spi_write(hdr, 4U);             /* コマンド+アドレス送信 */
    if (FSP_SUCCESS == err)
    {
        err = spi_write(buf, len);        /* データ送信(CS維持) */
    }
    CS_HIGH();                            /* CS ネゲート */

    if (FSP_SUCCESS == err)
    {
        W25Q64_WaitDone();                /* tPP 完了待ち(最大3ms) */
    }
    return err;
}

入出力波形

データ読み出し

プログラムコード

W25Q64_ReadData関数

/* -------------------------------------------------------
 * データ読み出し
 * コマンド+アドレス送信後、CSを維持したままデータ受信
 * ------------------------------------------------------- */
fsp_err_t W25Q64_ReadData(uint32_t addr, uint8_t *buf, uint32_t len)
{
    uint8_t hdr[4] = {
        W25Q64_CMD_READ_DATA,
        (uint8_t)(addr >> 16U),
        (uint8_t)(addr >>  8U),
        (uint8_t)(addr >>  0U)
    };

    CS_LOW();                             /* CS アサート */
    fsp_err_t err = spi_write(hdr, 4U);   /* コマンド+アドレス送信 */
    if (FSP_SUCCESS == err)
    {
        err = spi_read(buf, len);         /* データ受信(CS維持) */
    }
    CS_HIGH();                            /* CS ネゲート */

    return err;
}

入出力波形

チップ消去

プログラムコード

W25Q64_ChipErase関数

/* -------------------------------------------------------
 * チップ全消去
 * 完了まで最大200秒かかる場合あり(W25Q64仕様)
 * ------------------------------------------------------- */
fsp_err_t W25Q64_ChipErase(void)
{
    fsp_err_t err = write_enable();
    if (FSP_SUCCESS != err) return err;

    uint8_t cmd = W25Q64_CMD_CHIP_ERASE;
    CS_LOW();
    err = spi_write(&cmd, 1U);
    CS_HIGH();

    if (FSP_SUCCESS == err)
    {
        W25Q64_WaitDone();
    }
    return err;
}

入出力波形

※ チップ消去の入出力波形はありません

SPI Flash Memoryの制御サンプルプログラム(hal_entry関数)

プログラムコード

📄 hal_entry.c – W25Q64 Read/Write Test

void hal_entry関数(void)
{
    /* TODO: add your own code here */
    /* W25Q64の初期化(SPIの初期化を含む) ---- */
    gui_err = W25Q64_Init();
    if (FSP_SUCCESS != gui_err) { while (1); }

    /* JEDEC IDの確認 / W25Q64のJEDEC IDは : 0xEF, 0x40, 0x17 */
    gui_err = W25Q64_ReadJEDECID((uint8_t *)gui_id);
    if (FSP_SUCCESS != gui_err || gui_id[0] != 0xEFU) { while (1); }

    /* セクタ消去(先頭4KB) */
    gui_err = W25Q64_SectorErase(0x000000UL);
    if (FSP_SUCCESS != gui_err) { while (1); }

    /* 書き込みバッファの初期化(256バイト : 0 - 255) */
    for (int i = 0; i < 256; i++) { gui_wbuf[i] = (uint8_t)i; }
    /* ページ書き込み(256バイト) */
    gui_err = W25Q64_PageProgram(0x000000UL, (uint8_t *)gui_wbuf, sizeof(gui_wbuf));
    if (FSP_SUCCESS != gui_err) { while (1); }

    /* データ読み出し */
    gui_err = W25Q64_ReadData(0x000000UL, (uint8_t *)gui_rbuf, sizeof(gui_rbuf));
    if (FSP_SUCCESS != gui_err) { while (1); }

    /* 検証 */
    if (memcmp((uint8_t *)gui_wbuf, (uint8_t *)gui_rbuf, sizeof(gui_wbuf)) == 0)
    {
        /* 成功 */
        while (1);
    }
    else
    {
        /* 不一致エラー */
        while (1);
    }
}

まとめ

今回は必要最低限のコマンドのみを実装しましたが、基本的な機能のJEDEC IDの読み出し・フラッシュメモリへの書き込みと読み出しが簡単にできることがわかったと思います。
実用的に使う場合、書き込みデータサイズや各セクタ、ブロック単位のページング処理などが必要となりますので、機会があればご紹介させていただきます。

最後までお読みいただき、ありがとうございました。

サンプルコード

w25q64.c


📄  w25q64.c  —  W25Q64 SPIフラッシュ ドライバ(RA0E1 / SAU-SPI)


/*
 * w25q64.c
 *
 *  Created on: 2026/02/21
 *      Author: 13963
 */

/* ヘッダファイル : 一部デバイス依存 */
#include "hal_data.h"
#include "r_sau_spi.h"
#include "bsp_api.h"
#include "w25q64.h"

/* -------------------------------------------------------
 * CS マクロ(BSP I/O access API・アクティブロー)
 * R_BSP_PinWrite の前後に Enable/Disable が必要
 * 端子設定はデバイス依存
 * ------------------------------------------------------- */
#define CS_LOW()  R_IOPORT_PinWrite(&g_ioport_ctrl, W25Q64_CS_PORT, BSP_IO_LEVEL_LOW)
#define CS_HIGH() R_IOPORT_PinWrite(&g_ioport_ctrl, W25Q64_CS_PORT, BSP_IO_LEVEL_HIGH)

/* -------------------------------------------------------
 * 転送完了フラグ(コールバックでセット)
 * ------------------------------------------------------- */
static volatile bool s_spi_done  = false;
static volatile bool s_spi_error = false;

/* -------------------------------------------------------
 * SAU SPI コールバック
 * FSP Configurator の Callback 欄に "sau_spi0_callback" を登録
 * ------------------------------------------------------- */
void sau_spi0_callback(spi_callback_args_t *p_args)
{
    if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
    {
        s_spi_done = true;
    }
    else
    {
        s_spi_error = true;
    }
}

/* -------------------------------------------------------
 * 内部:転送完了待ち(タイムアウト付き)
 * ------------------------------------------------------- */
static fsp_err_t spi_wait(void)
{
    uint32_t timeout = 500000UL;

    while (!s_spi_done && !s_spi_error)
    {
        if (--timeout == 0U)
        {
            return FSP_ERR_TIMEOUT;
        }
    }

    if (s_spi_error)
    {
        s_spi_error = false;
        s_spi_done  = false;
        return FSP_ERR_TRANSFER_ABORTED;
    }

    s_spi_done = false;
    return FSP_SUCCESS;
}

/* -------------------------------------------------------
 * 内部:送信のみ(CSはこの関数の外で制御)
 * ------------------------------------------------------- */
static fsp_err_t spi_write(const uint8_t *tx, uint32_t len)
{
    fsp_err_t err = R_SAU_SPI_Write(&g_spi0_ctrl, tx, len, SPI_BIT_WIDTH_8_BITS);
    if (FSP_SUCCESS != err) return err;
    return spi_wait();
}

/* -------------------------------------------------------
 * 内部:受信のみ(CSはこの関数の外で制御)
 * ------------------------------------------------------- */
static fsp_err_t spi_read(uint8_t *rx, uint32_t len)
{
    fsp_err_t err = R_SAU_SPI_Read(&g_spi0_ctrl, rx, len, SPI_BIT_WIDTH_8_BITS);
    if (FSP_SUCCESS != err) return err;
    return spi_wait();
}

/* -------------------------------------------------------
 * 内部:送受信(CSはこの関数の外で制御)
 * ------------------------------------------------------- */
static fsp_err_t spi_write_read(const uint8_t *tx, uint8_t *rx, uint32_t len)
{
    fsp_err_t err = R_SAU_SPI_WriteRead(&g_spi0_ctrl, tx, rx, len, SPI_BIT_WIDTH_8_BITS);
    if (FSP_SUCCESS != err) return err;
    return spi_wait();
}

/* -------------------------------------------------------
 * 初期化
 * ------------------------------------------------------- */
fsp_err_t W25Q64_Init(void)
{
    CS_HIGH();  /* 非選択状態を確定 */

    fsp_err_t err = R_SAU_SPI_Open(&g_spi0_ctrl, &g_spi0_cfg);
    if (FSP_SUCCESS != err) return err;

    /* パワーダウン解除 */
    uint8_t cmd = W25Q64_CMD_RELEASE_POWER_DOWN;
    CS_LOW();
    err = spi_write(&cmd, 1U);
    CS_HIGH();

    /* tRES1 待機(最低3us → 余裕を持って1ms) */
    R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);

    return err;
}

/* -------------------------------------------------------
 * JEDEC ID 読み出し
 * 正常時:id[0]=0xEF  id[1]=0x40  id[2]=0x17
 * ------------------------------------------------------- */
fsp_err_t W25Q64_ReadJEDECID(uint8_t *id)
{
    uint8_t tx[4] = { W25Q64_CMD_JEDEC_ID, 0xFFU, 0xFFU, 0xFFU };
    uint8_t rx[4] = { 0U };

    CS_LOW();
    fsp_err_t err = spi_write_read(tx, rx, 4U);
    CS_HIGH();

    if (FSP_SUCCESS == err)
    {
        id[0] = rx[1];  /* Manufacturer ID : 0xEF */
        id[1] = rx[2];  /* Memory Type     : 0x40 */
        id[2] = rx[3];  /* Capacity        : 0x17 */
    }
    return err;
}

/* -------------------------------------------------------
 * 内部:ステータスレジスタ1 読み出し
 * ------------------------------------------------------- */
static fsp_err_t read_status1(uint8_t *status)
{
    uint8_t tx[2] = { W25Q64_CMD_READ_STATUS1, 0xFFU };
    uint8_t rx[2] = { 0U };

    CS_LOW();
    fsp_err_t err = spi_write_read(tx, rx, 2U);
    CS_HIGH();

    if (FSP_SUCCESS == err) *status = rx[1];
    return err;
}

/* -------------------------------------------------------
 * ビジー確認
 * ------------------------------------------------------- */
bool W25Q64_IsBusy(void)
{
    uint8_t status = 0U;
    read_status1(&status);
    return (bool)(status & W25Q64_STATUS_BUSY);
}

/* -------------------------------------------------------
 * 書き込み/消去完了待ち
 * ------------------------------------------------------- */
void W25Q64_WaitDone(void)
{
    while (W25Q64_IsBusy())
    {
        R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
    }
}

/* -------------------------------------------------------
 * 内部:ライトイネーブル
 * ------------------------------------------------------- */
static fsp_err_t write_enable(void)
{
    uint8_t cmd = W25Q64_CMD_WRITE_ENABLE;
    CS_LOW();
    fsp_err_t err = spi_write(&cmd, 1U);
    CS_HIGH();
    return err;
}

/* -------------------------------------------------------
 * データ読み出し
 * コマンド+アドレス送信後、CSを維持したままデータ受信
 * ------------------------------------------------------- */
fsp_err_t W25Q64_ReadData(uint32_t addr, uint8_t *buf, uint32_t len)
{
    uint8_t hdr[4] = {
        W25Q64_CMD_READ_DATA,
        (uint8_t)(addr >> 16U),
        (uint8_t)(addr >>  8U),
        (uint8_t)(addr >>  0U)
    };

    CS_LOW();                               /* CS アサート */
    fsp_err_t err = spi_write(hdr, 4U);    /* コマンド+アドレス送信 */
    if (FSP_SUCCESS == err)
    {
        err = spi_read(buf, len);            /* データ受信(CS維持) */
    }
    CS_HIGH();                              /* CS ネゲート */

    return err;
}

/* -------------------------------------------------------
 * ページプログラム(最大256バイト)
 * addr はページ境界(256バイト境界)を推奨
 * ------------------------------------------------------- */
fsp_err_t W25Q64_PageProgram(uint32_t addr, const uint8_t *buf, uint32_t len)
{
    if (len == 0U || len > W25Q64_PAGE_SIZE)
    {
        return FSP_ERR_INVALID_ARGUMENT;
    }

    fsp_err_t err = write_enable();
    if (FSP_SUCCESS != err) return err;

    uint8_t hdr[4] = {
        W25Q64_CMD_PAGE_PROGRAM,
        (uint8_t)(addr >> 16U),
        (uint8_t)(addr >>  8U),
        (uint8_t)(addr >>  0U)
    };

    CS_LOW();                               /* CS アサート */
    err = spi_write(hdr, 4U);              /* コマンド+アドレス送信 */
    if (FSP_SUCCESS == err)
    {
        err = spi_write(buf, len);           /* データ送信(CS維持) */
    }
    CS_HIGH();                              /* CS ネゲート */

    if (FSP_SUCCESS == err)
    {
        W25Q64_WaitDone();                   /* tPP 完了待ち(最大3ms) */
    }
    return err;
}

/* -------------------------------------------------------
 * セクタ消去(4KB単位)
 * addr は 4KB 境界アドレス(下位12bitは無視される)
 * ------------------------------------------------------- */
fsp_err_t W25Q64_SectorErase(uint32_t addr)
{
    fsp_err_t err = write_enable();
    if (FSP_SUCCESS != err) return err;

    uint8_t tx[4] = {
        W25Q64_CMD_SECTOR_ERASE,
        (uint8_t)(addr >> 16U),
        (uint8_t)(addr >>  8U),
        (uint8_t)(addr >>  0U)
    };

    CS_LOW();
    err = spi_write(tx, 4U);
    CS_HIGH();

    if (FSP_SUCCESS == err)
    {
        W25Q64_WaitDone();                   /* tSE 完了待ち(最大400ms) */
    }
    return err;
}

/* -------------------------------------------------------
 * チップ全消去
 * 完了まで最大200秒かかる場合あり(W25Q64仕様)
 * ------------------------------------------------------- */
fsp_err_t W25Q64_ChipErase(void)
{
    fsp_err_t err = write_enable();
    if (FSP_SUCCESS != err) return err;

    uint8_t cmd = W25Q64_CMD_CHIP_ERASE;
    CS_LOW();
    err = spi_write(&cmd, 1U);
    CS_HIGH();

    if (FSP_SUCCESS == err)
    {
        W25Q64_WaitDone();
    }
    return err;
}

w25q64.h


📄  w25q64.h  —  W25Q64 SPIフラッシュ ドライバ ヘッダ(RA0E1 / SAU-SPI)


/*
 * w25q64.h
 *
 *  Created on: 2026/02/21
 *      Author: 13963
 */

#ifndef W25Q64_H_
#define W25Q64_H_

/* ヘッダファイル : 一部デバイス依存 */
#include "hal_data.h"
#include <stdint.h>
#include <stdbool.h>

/* -------------------------------------------------------
 * W25Q64 コマンド定義
 * ------------------------------------------------------- */
#define W25Q64_CMD_JEDEC_ID             (0x9FU)
#define W25Q64_CMD_READ_STATUS1         (0x05U)
#define W25Q64_CMD_WRITE_ENABLE         (0x06U)
#define W25Q64_CMD_PAGE_PROGRAM         (0x02U)
#define W25Q64_CMD_READ_DATA            (0x03U)
#define W25Q64_CMD_SECTOR_ERASE         (0x20U)  /* 4KB */
#define W25Q64_CMD_CHIP_ERASE           (0xC7U)
#define W25Q64_CMD_RELEASE_POWER_DOWN   (0xABU)

/* ステータスレジスタ1 ビット定義 */
#define W25Q64_STATUS_BUSY              (0x01U)
#define W25Q64_STATUS_WEL               (0x02U)

/* フラッシュパラメータ */
#define W25Q64_PAGE_SIZE                (256U)
#define W25Q64_SECTOR_SIZE              (4096U)

/*
 * CSピン定義(Pin20)
 * ハードウェアマニュアルのピン配置表で実際のポートを確認して変更すること
 * 端子設定はデバイス依存
 */
#define W25Q64_CS_PORT                  BSP_IO_PORT_01_PIN_03

/* -------------------------------------------------------
 * 公開API(戻り値 : デバイス依存)
 * ------------------------------------------------------- */
fsp_err_t W25Q64_Init(void);
fsp_err_t W25Q64_ReadJEDECID(uint8_t *id);
fsp_err_t W25Q64_ReadData(uint32_t addr, uint8_t *buf, uint32_t len);
fsp_err_t W25Q64_PageProgram(uint32_t addr, const uint8_t *buf, uint32_t len);
fsp_err_t W25Q64_SectorErase(uint32_t addr);
fsp_err_t W25Q64_ChipErase(void);
bool      W25Q64_IsBusy(void);
void      W25Q64_WaitDone(void);

#endif /* W25Q64_H_ */