/**
 ****************************************************************************************************
 * @file        norflash.h
 * @author      
 * @version     V1.0
 * @date        2021-10-26
 * @brief       NOR FLASH(25QXX) 驱动代码
 * @license     Copyright (c) 2020-2032
 ****************************************************************************************************
 */

#ifndef __BSP_SPIFLASH_H
#define __BSP_SPIFLASH_H

#include "main.h"
#include "spi.h"

/*
	2022-7-27 经过测试 华邦的 W25Q256JV   32M 字节 容量的spi flash没有问题  
	spi配置是  上升沿采集数据 ---> CPOL =0 CPOA=0  或者是 CPOL=1 CPOA=1   
	hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;  
	hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
	华邦的  W25Q16JVSSIQ 2M 字节 容量的spi flash没有问题 
*/


/* SPI总线速度设置 */
#define SPI_SPEED_2         0
#define SPI_SPEED_4         1
#define SPI_SPEED_8         2
#define SPI_SPEED_16        3
#define SPI_SPEED_32        4
#define SPI_SPEED_64        5
#define SPI_SPEED_128       6
#define SPI_SPEED_256       7


/******************************************************************************************/
/* NORFLASH 片选 引脚 定义 */

// #define spiflash_CS_GPIO_PORT           GPIOA
// #define spiflash_CS_GPIO_PIN            GPIO_PIN_2
// #define spiflash_CS_GPIO_CLK_ENABLE()   do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PI口时钟使能 */

/******************************************************************************************/

extern uint16_t g_spiflash_type;      /* 定义FLASH芯片型号 */

/* NORFLASH 片选信号 */
#define spiflash_CS(x)      do{ x ? \
                                  HAL_GPIO_WritePin(SPI5_CS_GPIO_Port, SPI5_CS_Pin, GPIO_PIN_SET) : \
                                  HAL_GPIO_WritePin(SPI5_CS_GPIO_Port, SPI5_CS_Pin, GPIO_PIN_RESET); \
                            }while(0)

/* FLASH芯片列表 */
#define W25Q80      0XEF13          /* W25Q80   芯片ID */
#define W25Q16      0XEF14          /* W25Q16   芯片ID */
#define W25Q32      0XEF15          /* W25Q32   芯片ID */
#define W25Q64      0XEF16          /* W25Q64   芯片ID */
#define W25Q128     0XEF17          /* W25Q128  芯片ID */
#define W25Q256     0XEF18          /* W25Q256  芯片ID */
#define BY25Q64     0X6816          /* BY25Q64  芯片ID */
#define BY25Q128    0X6817          /* BY25Q128 芯片ID */
#define NM25Q64     0X5216          /* NM25Q64  芯片ID */
#define NM25Q128    0X5217          /* NM25Q128 芯片ID */

 
/* 指令表 */
#define FLASH_WriteEnable           0x06 
#define FLASH_WriteDisable          0x04 
#define FLASH_ReadStatusReg1        0x05 
#define FLASH_ReadStatusReg2        0x35 
#define FLASH_ReadStatusReg3        0x15 
#define FLASH_WriteStatusReg1       0x01 
#define FLASH_WriteStatusReg2       0x31 
#define FLASH_WriteStatusReg3       0x11 
#define FLASH_ReadData              0x03 
#define FLASH_FastReadData          0x0B 
#define FLASH_FastReadDual          0x3B 
#define FLASH_FastReadQuad          0xEB  
#define FLASH_PageProgram           0x02 
#define FLASH_PageProgramQuad       0x32 
#define FLASH_BlockErase            0xD8 
#define FLASH_SectorErase           0x20 
#define FLASH_ChipErase             0xC7 
#define FLASH_PowerDown             0xB9 
#define FLASH_ReleasePowerDown      0xAB 
#define FLASH_DeviceID              0xAB 
#define FLASH_ManufactDeviceID      0x90 
#define FLASH_JedecDeviceID         0x9F 
#define FLASH_Enable4ByteAddr       0xB7
#define FLASH_Exit4ByteAddr         0xE9
#define FLASH_SetReadParam          0xC0 
#define FLASH_EnterQPIMode          0x38
#define FLASH_ExitQPIMode           0xFF

/* 静态函数 */
static void spiflash_wait_busy(void);               /* 等待空闲 */
static void spiflash_send_address(uint32_t address);/* 发送地址 */
static void spiflash_write_page(uint8_t *pbuf, uint32_t addr, uint16_t datalen);    /* 写入page */
static void spiflash_write_nocheck(uint8_t *pbuf, uint32_t addr, uint16_t datalen); /* 写flash,不带擦除 */

/* 普通函数 */
void spiflash_init(void);                   /* 初始化25QXX */
uint16_t spiflash_read_id(void);            /* 读取FLASH ID */
void spiflash_write_enable(void);           /* 写使能 */
uint8_t spiflash_read_sr(uint8_t regno);    /* 读取状态寄存器 */
void spiflash_write_sr(uint8_t regno,uint8_t sr);   /* 写状态寄存器 */

void spiflash_erase_chip(void);             /* 整片擦除 */
void spiflash_erase_sector(uint32_t saddr); /* 扇区擦除 */
void spiflash_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen);     /* 读取flash */
void spiflash_write(uint8_t *pbuf, uint32_t addr, uint16_t datalen);    /* 写入flash */

void spi_flash_test();

#endif
