You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

996 lines
28 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// #include <main.h>
// #include "SerialFlash.h"
// #include "context/guicontext.h"
// #include "usermain.h"
#include "ALLinclude.h"
#define CMD_RDID 0x9F
#define CMD_READ 0x03
#define CMD_WREN 0x06
#define CMD_PP 0x02
#define CMD_RDSR 0x05
#define CMD_SE 0x20//0xD8
#define STATUS_WIP 0x01
#define W25X_ChipErase 0xC7
SPI_HandleTypeDef FlashSpiHandle; //FOR P25QXX
DMA_HandleTypeDef HdmaCh4;
DMA_HandleTypeDef HdmaCh3;
/**
SPI Flash
CS: PB6
CLK:PB3
MOSI: PB5
MISO:PB4
***/
//extern prototypes
void Error_Handler(void);
//private variables
//DMA handle for reading pixels from SPI peripheral
//extern DMA_HandleTypeDef hdma_spi1_rx;
//extern DMA_HandleTypeDef hdma_spi1_tx;
//Status flag. Non-zero when receiving data
static volatile uint8_t isReceivingData = 0;
/* Chip Select macro definition */
extern GPIO_TypeDef* FLASHCS_GPIO ;
extern uint16_t FLASHCS_PIN;
SPI_TypeDef* FlashSPI;
#define SPI_FLASH FlashSPI
#define FLASHDMA_SPI2
#define FLASH_CS_LOW() {FLASH_CS_PORT->BRR = FLASH_CS_PIN;}//HAL_GPIO_WritePin(FLASH_CS_GPIO_PORT, FLASH_CS_PIN, GPIO_PIN_RESET)
#define FLASH_CS_HIGH() {FLASH_CS_PORT->BSRR = FLASH_CS_PIN;}//HAL_GPIO_WritePin(FLASH_CS_GPIO_PORT, FLASH_CS_PIN, GPIO_PIN_SET)
static void enter4addrmode();
static uint32_t readStatusRegister();
/********************************************************************************************************
**函数信息 :
**功能描述 :
**输入参数 :
**输出参数 :
** 备注 :
********************************************************************************************************/
void P25QXX_Gpio_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
// __HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pin = FLASH_CS_PIN;
HAL_GPIO_Init(FLASH_CS_PORT, &GPIO_InitStruct);
FLASH_CS_H();
//GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pin = FLASH_MOSI_PIN;
GPIO_InitStruct.Alternate = FLASH_SPI_AF;
HAL_GPIO_Init(FLASH_MOSI_PORT, &GPIO_InitStruct);
//GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pin = FLASH_MISO_PIN;
GPIO_InitStruct.Alternate = FLASH_SPI_AF;
HAL_GPIO_Init(FLASH_MISO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pin = FLASH_CLK_PIN;
GPIO_InitStruct.Alternate = FLASH_SPI_AF;
HAL_GPIO_Init(FLASH_CLK_PORT, &GPIO_InitStruct);
/* Interrupt configuration */
HAL_NVIC_SetPriority(SPI1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
/********************************************************************************************************
**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ :
**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :
**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :
**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :
** <20><>ע :
********************************************************************************************************/
static void P25QXX_SPI_DMA_Init(void)
{
FLASH_SPI_CLOCK_EN();
__HAL_RCC_DMA1_CLK_ENABLE(); /* Enable DMA clock */
FlashSpiHandle.Instance = FLASH_SPI; // SPI1
FlashSpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // 2<><32>Ƶ 72M->36Mhz
FlashSpiHandle.Init.Direction = SPI_DIRECTION_2LINES; // full duplex
FlashSpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; // SPI Clock Polarity: low
FlashSpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; // Data sampling starts at the first clock edge
FlashSpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; // SPI Data Size is 8 bit
FlashSpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; // SPI MSB Transmission
FlashSpiHandle.Init.NSS = SPI_NSS_SOFT; // NSS Hardware mode
FlashSpiHandle.Init.Mode = SPI_MODE_MASTER; // Configure as host
FlashSpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // The CRC check is disabled
HAL_SPI_DeInit(&FlashSpiHandle);
HAL_SPI_Init(&FlashSpiHandle);
//======================================================================//
__HAL_RCC_DMA1_CLK_ENABLE();
HdmaCh4.Instance = DMA1_Channel4; // DMA_CH4
HdmaCh4.Init.Direction = DMA_MEMORY_TO_PERIPH; // <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B7BD>
HdmaCh4.Init.PeriphInc = DMA_PINC_DISABLE; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ <20>ر<EFBFBD>
HdmaCh4.Init.MemInc = DMA_MINC_ENABLE; // <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ģʽ <20><><EFBFBD><EFBFBD>
HdmaCh4.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD>ʽ: BYTE
HdmaCh4.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>ݸ<EFBFBD>ʽ: BYTE
HdmaCh4.Init.Mode = DMA_NORMAL; // <20><>ֹѭ<D6B9><D1AD>ģʽ
HdmaCh4.Init.Priority = DMA_PRIORITY_MEDIUM; // <20><><EFBFBD>ȼ<EFBFBD>: <20><>
HAL_DMA_Init(&HdmaCh4);
__HAL_LINKDMA(&FlashSpiHandle, hdmatx, HdmaCh4); // DMA_CH2 <20><><EFBFBD><EFBFBD> SPI1
if(FLASH_SPI == SPI1){
HAL_DMA_ChannelMap(&HdmaCh4, DMA_CHANNEL_MAP_SPI1_WR); // SPI1_TX DMA_CH4
}else{
HAL_DMA_ChannelMap(&HdmaCh4, DMA_CHANNEL_MAP_SPI2_WR); // SPI2_TX DMA_CH4
}
//======================================================================//
HdmaCh3.Instance = DMA1_Channel3; // DMA CH3
HdmaCh3.Init.Direction = DMA_PERIPH_TO_MEMORY; // <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B7BD>
HdmaCh3.Init.PeriphInc = DMA_PINC_DISABLE; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ <20>ر<EFBFBD>
HdmaCh3.Init.MemInc = DMA_MINC_ENABLE; // <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ģʽ <20><><EFBFBD><EFBFBD>
HdmaCh3.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD>ʽ: BYTE
HdmaCh3.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>ݸ<EFBFBD>ʽ: BYTE
HdmaCh3.Init.Mode = DMA_NORMAL; // <20><>ֹѭ<D6B9><D1AD>ģʽ
HdmaCh3.Init.Priority = DMA_PRIORITY_HIGH; // <20><><EFBFBD>ȼ<EFBFBD>: <20><>
HAL_DMA_Init(&HdmaCh3);
__HAL_LINKDMA(&FlashSpiHandle, hdmarx, HdmaCh3); // DMA_CH3 <20><><EFBFBD><EFBFBD> SPI1
if(FLASH_SPI == SPI1){
HAL_DMA_ChannelMap(&HdmaCh3, DMA_CHANNEL_MAP_SPI1_RD); // SPI1_RX DMA_CH3
}else{
HAL_DMA_ChannelMap(&HdmaCh3, DMA_CHANNEL_MAP_SPI2_RD); // SPI2_RX DMA_CH3
}
//======================================================================//
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
__HAL_SPI_ENABLE(&FlashSpiHandle);//FlashSpiHandle.Instance
// __HAL_SPI_ENABLE(FlashSpiHandle.Instance);//FlashSpiHandle.Instance
#if ADDR4_MODE
enter4addrmode();
#endif
}
uint8_t __readwritebyte(uint8_t data){
#if 0
while((SPI_FLASH->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = data;
while((SPI_FLASH->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
return *((__IO uint8_t*)&SPI_FLASH->DR);
#endif
uint8_t rxData = 0;
HAL_SPI_TransmitReceive(&FlashSpiHandle, &data, &rxData, 1, HAL_MAX_DELAY);
return rxData;
}
void Clear_SPI_DR(void) {
uint8_t dummy;
while ((SPI_FLASH->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE)
dummy = SPI_FLASH->DR;
}
uint8_t fy_flash_isbusy(void) {
uint8_t status = readStatusRegister(); // 实现读取状态寄存器
return (status & STATUS_WIP)?1:0; // STATUS_WIP = 0x01
}
uint32_t readDeviceId(void)
{
#if 0
FLASH_CS_LOW();
*((__IO uint8_t*)&SPI_FLASH->DR) = CMD_RDID;
while((SPI_FLASH->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE);
while((SPI_FLASH->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
uint8_t data0 = *((__IO uint8_t*)&SPI_FLASH->DR);
*((__IO uint8_t*)&SPI_FLASH->DR) = 0;
while((SPI_FLASH->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE);
while((SPI_FLASH->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
uint8_t data1 = *((__IO uint8_t*)&SPI_FLASH->DR);
*((__IO uint8_t*)&SPI_FLASH->DR) = 0;
while((SPI_FLASH->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE);
while((SPI_FLASH->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
uint8_t data2 = *((__IO uint8_t*)&SPI_FLASH->DR);
*((__IO uint8_t*)&SPI_FLASH->DR) = 0;
while((SPI_FLASH->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE);
while((SPI_FLASH->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
uint8_t data3 = *((__IO uint8_t*)&SPI_FLASH->DR);
FLASH_CS_HIGH();
return data1<<16 | data2<<8 | data3;
#endif
uint8_t tx[4] = {CMD_RDID, 0x00, 0x00, 0x00};
uint8_t rx[4] = {0};
FLASH_CS_LOW();
HAL_SPI_TransmitReceive(&FlashSpiHandle, tx, rx, 4, HAL_MAX_DELAY);
FLASH_CS_HIGH();
// rx[1] = Manufacturer ID
// rx[2] = Memory Type
// rx[3] = Capacity
return (rx[1] << 16) | (rx[2] << 8) | rx[3];
}
static uint32_t readStatusRegister()
{
#if 0
FLASH_CS_LOW();
*((__IO uint8_t*)&SPI_FLASH->DR) = CMD_RDSR; //0x05, 0x00
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = 0;
/* Wait until the bus is ready before releasing Chip select */
while(((SPI_FLASH->SR) & SPI_FLAG_BSY) != RESET) { }
FLASH_CS_HIGH();
//combine bytes
uint8_t data0 = *((__IO uint8_t*)&SPI_FLASH->DR);
uint8_t data1 = *((__IO uint8_t*)&SPI_FLASH->DR);
return data1;
#endif
uint8_t cmd = CMD_RDSR;
uint8_t status = 0;
FLASH_CS_LOW();
HAL_SPI_Transmit(&FlashSpiHandle, &cmd, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&FlashSpiHandle, &status, 1, HAL_MAX_DELAY);
FLASH_CS_HIGH();
return status;
}
static void sendWriteEnable()
{
#if 0
FLASH_CS_LOW();
*((__IO uint8_t*)&SPI_FLASH->DR) = CMD_WREN; //0x06
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
/* Wait until the bus is ready before releasing Chip select */
while(((SPI_FLASH->SR) & SPI_FLAG_BSY) != RESET) { }
FLASH_CS_HIGH();
//read dummy byte
uint8_t data0 = *((__IO uint8_t*)&SPI_FLASH->DR);
#endif
uint8_t cmd = CMD_WREN;
FLASH_CS_LOW();
HAL_SPI_Transmit(&FlashSpiHandle, &cmd, 1, HAL_MAX_DELAY);
FLASH_CS_HIGH();
}
static void enter4addrmode()
{
FLASH_CS_LOW();
#if 0
*((__IO uint8_t*)&SPI_FLASH->DR) = 0XB7;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
/* Wait until the bus is ready before releasing Chip select */
while(((SPI_FLASH->SR) & SPI_FLAG_BSY) != RESET) { }
#endif
__readwritebyte(0XB7);
FLASH_CS_HIGH();
//read dummy byte
uint8_t data0 = *((__IO uint8_t*)&SPI_FLASH->DR);
}
static void sendSectorErase(uint32_t address24)
{
FLASH_CS_LOW();
__readwritebyte(0xD8);
//clock out address
__readwritebyte(address24 >> 16);
__readwritebyte(address24 >> 8);
__readwritebyte(address24&0xff);
FLASH_CS_HIGH();
}
static void sendSector4KErase(uint32_t address24)
{
FLASH_CS_LOW();
__readwritebyte(0x20);
//clock out address
__readwritebyte(address24 >> 16);
__readwritebyte(address24 >> 8);
__readwritebyte(address24&0xff);
FLASH_CS_HIGH();
}
static void cmd_Erase()
{
FLASH_CS_LOW();
__readwritebyte(W25X_ChipErase);
//SPI_FLASH->DR;
FLASH_CS_HIGH();
}
static void sendPageProgram(uint32_t address24, const uint8_t* data, uint32_t length)
{
#if 0
FLASH_CS_LOW();
*((__IO uint8_t*)&SPI_FLASH->DR) = CMD_PP;
//clock out address
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 16) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 8) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = address24 & 0xFF;
//now write data bytes
while(length > 0)
{
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = *data;
data++;
length--;
}
/* Wait until the bus is ready before releasing Chip select */
while(((SPI_FLASH->SR) & SPI_FLAG_BSY) != RESET) { }
FLASH_CS_HIGH();
//read dummy bytes
while(((SPI_FLASH->SR) & SPI_FLAG_RXNE) == SPI_FLAG_RXNE)
{
*((__IO uint8_t*)&SPI_FLASH->DR);
}
#endif
uint8_t cmd[4];
cmd[0] = CMD_PP; // Page Program command
cmd[1] = (address24 >> 16) & 0xFF; // 24-bit address
cmd[2] = (address24 >> 8) & 0xFF;
cmd[3] = (address24) & 0xFF;
FLASH_CS_LOW();
// 先发命令 + 地址
HAL_SPI_Transmit(&FlashSpiHandle, cmd, 4, HAL_MAX_DELAY);
// 再发数据
HAL_SPI_Transmit(&FlashSpiHandle, (uint8_t*)data, length, HAL_MAX_DELAY);
FLASH_CS_HIGH();
}
static uint8_t dummy;
const uint32_t addr128MB = 0x1000000; //16MB
void readData(uint32_t address24, uint8_t* buffer, uint32_t length)
{
#if 0
FLASH_CS_LOW();
#if ADDR4_MODE
*((__IO uint8_t*)&SPI_FLASH->DR) = 0x13;//CMD_READ;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
dummy = *((__IO uint8_t*)&SPI_FLASH->DR);
//clock out address
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 24) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 16) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 8) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = address24 & 0xFF;
#else
*((__IO uint8_t*)&SPI_FLASH->DR) = CMD_READ;
//clock out address
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 16) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 8) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = address24 & 0xFF;
#endif
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
while((SPI_FLASH->SR & SPI_FLAG_BSY) != RESET) { }
dummy = *((__IO uint8_t*)&SPI_FLASH->DR);
dummy = *((__IO uint8_t*)&SPI_FLASH->DR);
dummy = *((__IO uint8_t*)&SPI_FLASH->DR);
dummy = *((__IO uint8_t*)&SPI_FLASH->DR);
*((__IO uint8_t*)&SPI_FLASH->DR) = 0xFF;
for (int i = 0; i<length-1; i++)
{
while((SPI_FLASH->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
*buffer++ = *((__IO uint8_t*)&SPI_FLASH->DR);
*((__IO uint8_t*)&SPI_FLASH->DR) = 0xFF;
}
while((SPI_FLASH->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
*buffer++ = *((__IO uint8_t*)&SPI_FLASH->DR);
FLASH_CS_HIGH();
isReceivingData = 0;
#endif
uint8_t cmd[5];
uint8_t cmdLen;
#if ADDR4_MODE
cmd[0] = 0x13; // 4-byte READ command
cmd[1] = (address24 >> 24) & 0xFF;
cmd[2] = (address24 >> 16) & 0xFF;
cmd[3] = (address24 >> 8) & 0xFF;
cmd[4] = (address24) & 0xFF;
cmdLen = 5;
#else
cmd[0] = CMD_READ; // 3-byte READ
cmd[1] = (address24 >> 16) & 0xFF;
cmd[2] = (address24 >> 8) & 0xFF;
cmd[3] = (address24) & 0xFF;
cmdLen = 4;
#endif
FLASH_CS_LOW();
// Clear_SPI_DR();
// 发送读命令 + 地址
HAL_SPI_Transmit(&FlashSpiHandle, cmd, cmdLen, HAL_MAX_DELAY);
// 读取数据
// HAL_SPI_TransmitReceive(&FlashSpiHandle, buffer,buffer, length, HAL_MAX_DELAY);
HAL_SPI_Receive(&FlashSpiHandle, buffer, length, HAL_MAX_DELAY);
FLASH_CS_HIGH();
}
static uint8_t dumydata=0xff;
static uint16_t tickcount = 0;
void readDataDMA(uint32_t address24, uint8_t* buffer, uint32_t length)
{
#if 0
if(isReceivingData){
#if USER_PRINTF
printf("Read DMA error \n");
#endif
return ;
}
// Pull Flash CS pin low
isReceivingData = 1;
FLASH_CS_LOW();
#if ADDR4_MODE
*((__IO uint8_t*)&SPI_FLASH->DR) = 0x13;//CMD_READ;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
dummy = *((__IO uint8_t*)&SPI_FLASH->DR);
//clock out address
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 24) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 16) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 8) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = address24 & 0xFF;
#else
*((__IO uint8_t*)&SPI_FLASH->DR) = CMD_READ;
//clock out address
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 16) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = (address24 >> 8) & 0xFF;
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
*((__IO uint8_t*)&SPI_FLASH->DR) = address24 & 0xFF;
#endif
while(((SPI_FLASH->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE);
while((SPI_FLASH->SR & SPI_FLAG_BSY) != RESET) { }
while(((SPI_FLASH->SR) & SPI_FLAG_RXNE) == SPI_FLAG_RXNE){
dummy = *((__IO uint8_t*)&SPI_FLASH->DR);
}
__disable_irq();
SET_BIT(SPI_FLASH->CR2, SPI_RXFIFO_THRESHOLD);
CLEAR_BIT(SPI_FLASH->CR2, SPI_CR2_LDMA_TX);
CLEAR_BIT(SPI_FLASH->CR2, SPI_CR2_LDMA_RX);
/* Reset the threshold bit */
//CLEAR_BIT(FlashSpiHandle.Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
HdmaCh4.DmaBaseAddress->IFCR = (DMA_IFCR_CGIF2);
HdmaCh3.DmaBaseAddress->IFCR = (DMA_IFCR_CGIF3);
// /* Set RX Fifo threshold according the reception data length: 8bit */
//SET_BIT(FlashSpiHandle.Instance->CR2, SPI_CR2_CLRTXFIFO);
// __HAL_SPI_DISABLE(&FlashSpiHandle);
/******** TX ****************/
/* Disable the peripheral */
__HAL_DMA_DISABLE(&HdmaCh4);
/* Disable the peripheral */
__HAL_DMA_DISABLE(&HdmaCh3);
/* Clear all flags */
// __HAL_DMA_CLEAR_FLAG(&HdmaCh2, (DMA_ISR_GIF1 << (HdmaCh2.ChannelIndex)));
/* Configure DMA Channel data length */
HdmaCh4.Instance->CNDTR = length;
/* Configure DMA Channel destination address */
HdmaCh4.Instance->CPAR = (uint32_t)&(SPI_FLASH->DR);
/* Configure DMA Channel source address */
HdmaCh4.Instance->CMAR = (uint32_t)&dumydata;
/* Enable Tx DMA Request */
SET_BIT(FlashSpiHandle.Instance->CR2, SPI_CR2_TXDMAEN);
/* Enable the Peripheral */
__HAL_DMA_ENABLE(&HdmaCh4);
/******** RX ****************/
/* Clear all flags */
//__HAL_DMA_CLEAR_FLAG(&HdmaCh3, (DMA_ISR_GIF1 << (HdmaCh3.ChannelIndex )));
//__HAL_DMA_CLEAR_FLAG(&HdmaCh3, (DMA_ISR_GIF1 << (HdmaCh3.ChannelIndex )));
/* Configure DMA Channel data length */
HdmaCh3.Instance->CNDTR = length;
/* Configure DMA Channel destination address */
HdmaCh3.Instance->CPAR = (uint32_t)&(SPI_FLASH->DR);
/* Configure DMA Channel source address */
HdmaCh3.Instance->CMAR = (uint32_t)buffer;
/* Enable Rx DMA Request */
SET_BIT(FlashSpiHandle.Instance->CR2, SPI_CR2_RXDMAEN);
/* Enable the Peripheral */
__HAL_DMA_ENABLE(&HdmaCh3);
// printf("==> Read dma len[%d]ISR:%x \n",length ,DMA1->ISR);
//__HAL_DMA_DISABLE_IT(&HdmaCh3, DMA_IT_HT |DMA_IT_TC| DMA_IT_TE);
__HAL_DMA_DISABLE_IT(&HdmaCh3, DMA_IT_TC);
__HAL_DMA_ENABLE_IT(&HdmaCh3, (DMA_IT_TC));
__enable_irq();
// __HAL_SPI_ENABLE(&FlashSpiHandle);
//tickcount = HAL_GetTick();
// printf("dma start tick :%d \n",tickcount);
/* Enable SPI peripheral */
// __HAL_SPI_ENABLE(&FlashSpiHandle);
// HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);
#endif
if (isReceivingData) {
#if USER_PRINTF
printf("Read DMA busy\n");
#endif
return;
}
isReceivingData = 1;
FLASH_CS_LOW();
#if ADDR4_MODE
uint8_t cmd[5];
cmd[0] = 0x13;
cmd[1] = (address24 >> 24) & 0xFF;
cmd[2] = (address24 >> 16) & 0xFF;
cmd[3] = (address24 >> 8) & 0xFF;
cmd[4] = address24 & 0xFF;
HAL_SPI_Transmit(&FlashSpiHandle, cmd, 5, HAL_MAX_DELAY);
#else
uint8_t cmd[4];
cmd[0] = CMD_READ;
cmd[1] = (address24 >> 16) & 0xFF;
cmd[2] = (address24 >> 8) & 0xFF;
cmd[3] = address24 & 0xFF;
HAL_SPI_Transmit(&FlashSpiHandle, cmd, 4, HAL_MAX_DELAY);
#endif
// 清空 FIFO
__HAL_SPI_CLEAR_OVRFLAG(&FlashSpiHandle);
// 启动 DMATX 发 dummy, RX 收数据
static uint8_t dummyTX[256]; // 注意要保证 >= length可以循环发
memset(dummyTX, 0xFF, sizeof(dummyTX));
if (HAL_SPI_TransmitReceive_DMA(&FlashSpiHandle, dummyTX, buffer, length) != HAL_OK) {
#if USER_PRINTF
printf("Read DMA start failed\n");
#endif
isReceivingData = 0;
}
//FLASH_CS_HIGH();
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi == &FlashSpiHandle) {
// 等 SPI 完全结束
while ((hspi->Instance->SR & SPI_FLAG_BSY) != RESET);
// 拉高片选
FLASH_CS_HIGH();
// 关闭 SPI DMA
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN);
isReceivingData = 0;
#if USER_PRINTF
printf("DMA Rx Complete\n");
#endif
}
}
#if 0
void DataReader_DMACallback()
{
/// printf("ISR:%x \n",DMA1->ISR);
//
// return ;
/* Transfer Complete Interrupt management ***********************************/
// if ((0U != (DMA1->ISR & (DMA_FLAG_GL2)))/* && (0U != (HdmaCh3.Instance->CCR & DMA_IT_TC))*/)
// {
uint32_t flag_it = DMA1->ISR;
uint32_t source_it = HdmaCh3.Instance->CCR;
// HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);
/* Half Transfer Complete Interrupt management ******************************/
if ((0U != (DMA1->ISR & (DMA_FLAG_TC3))))
{
FLASH_CS_HIGH();
/* Disable the transfer complete and error interrupt */
__HAL_DMA_DISABLE_IT(&HdmaCh3, DMA_IT_TE | DMA_IT_TC);
/* Clear the transfer complete flag */
__HAL_DMA_CLEAR_FLAG(&HdmaCh3, __HAL_DMA_GET_TC_FLAG_INDEX(&HdmaCh3));
CLEAR_BIT(FlashSpiHandle.Instance->CR2, SPI_CR2_RXDMAEN);
CLEAR_BIT(FlashSpiHandle.Instance->CR2, SPI_CR2_TXDMAEN);
// Wait until the bus is not busy before changing configuration
// SPI is busy in communication or Tx buffer is not empty
//while(((SPI_FLASH->SR) & SPI_FLAG_BSY) != RESET) { }
//FlashSpiHandle.State = HAL_SPI_STATE_READY;
//FLASH_CS_GPIO_Port->BSRR = FLASH_CS_Pin;
isReceivingData = 0;
}
// else if (( RESET != (flag_it & (DMA_FLAG_TE1 << HdmaCh3.ChannelIndex))) && (RESET != (source_it & DMA_IT_TE)))
// {
// /* When a DMA transfer error occurs */
// /* A hardware clear of its EN bits is performed */
// /* Disable ALL DMA IT */
// __HAL_DMA_DISABLE_IT(&HdmaCh3, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
// /* Clear all flags */
// HdmaCh3.DmaBaseAddress->IFCR = (DMA_ISR_GIF1 <<HdmaCh3.ChannelIndex);
// }
// DMA1->IFCR = 0xff0; //clear dma2,1
}
#endif
//void SerialFlash_ReadData(uint32_t address24, uint8_t* buffer, uint32_t length)
//{
// readData(address24, buffer, length);
//}
//void SerialFlash_StartDMAReadData(uint32_t address24, uint8_t* buffer, uint32_t length)
//{
// // readDataDMA(address24, buffer, length);
// readData(address24, buffer, length);
//}
volatile uint32_t statusReg = 0;
void SerialFlash_ChipErase(){
uint32_t address = 0x000000;
sendWriteEnable();
cmd_Erase();
uint32_t status;
do
{
status = readStatusRegister();
} while (status & STATUS_WIP);
}
void SerialFlash_EraseSize(uint32_t startaddr,uint32_t size){
uint32_t address = startaddr;
uint32_t sizeOfBitmaps = address+size;
uint8_t flash_id = (uint8_t)fy_flash_readid();
uint32_t maxsize = 0x1F8000;
switch(flash_id) {
case 0x16: //25q16 //32M
maxsize = 0x3FF000;
break;
case 0x15: //25q16 //2M
maxsize = 0x1FF000;
break;
case 0x14: //25q80 //2M
maxsize = 0xFF000;
break;
}
do
{
if(address < maxsize){
sendWriteEnable();
sendSectorErase(address);
//wait until WIP is cleared
uint32_t status;
do
{
status = readStatusRegister();
} while (status & STATUS_WIP);
address += 0x8000; // 64K earser
}else{
sendWriteEnable();
sendSector4KErase(address);
//wait until WIP is cleared
uint32_t status;
do
{
status = readStatusRegister();
} while (status & STATUS_WIP);
address += 0x1000; //4K Earser
}
} while (address < sizeOfBitmaps);
}
void SerialFlash_ProgramInfo(uint32_t addr,uint8_t* data,uint32_t size){
sendWriteEnable();
sendPageProgram(addr, data, size);
//wait until WIP is cleared
uint32_t status;
do
{
status = readStatusRegister();
} while (status & STATUS_WIP);
}
uint32_t SerialFlash_IsReceivingData(void)
{
//isReceivingData = (FlashSpiHandle.State != HAL_SPI_STATE_READY);
return isReceivingData;
}
void SerialFlash_WaitForReceiveDone(void)
{
while (FlashSpiHandle.State != HAL_SPI_STATE_READY) {
//
}
// 方法2使用中断回调需在HAL_SPI_RxCpltCallback中设标志
while (isReceivingData); // 等待中断置位
}
void fly_flash_init(void){
//SerialFlash_DMAInit();
// P25QXX_Gpio_Init();
P25QXX_SPI_DMA_Init();
}
uint32_t fy_flash_readid(void)
{
return readDeviceId();
}
void fy_flash_read(uint32_t address24, uint8_t* buffer, uint32_t length)
{
if(length <= 0){
#if USER_PRINTF
printf("read error :%d \n",length);
#endif
return;
}
readData(address24,buffer,length);
}
void fy_flash_readdma(uint32_t address24, uint8_t* buffer, uint32_t length)
{
// readData(address24,buffer,length);
//printf("dma read len:%d \n",length);
if(length <= 0){
#if USER_PRINTF
printf("read dma error :%d \n",length);
#endif
return;
}
readDataDMA(address24,buffer,length);
}
void fy_flash_erase(){
SerialFlash_ChipErase();
//spi_flash_bulk_erase();
}
void fy_flash_erase_block(uint32_t start,uint32_t sizeOfBitmaps){
// spi_flash_sector_erase_size(start,sizeOfBitmaps);
SerialFlash_EraseSize(start,sizeOfBitmaps);
}
void fy_flash_page_write(uint32_t addr,uint8_t* data,uint32_t size){
//spi_flash_page_write(data,addr,size);
SerialFlash_ProgramInfo(addr,data,size);
}
uint32_t fy_flash_isreceiveing(void)
{
// return isReceivingData;
return SerialFlash_IsReceivingData();
}
void fy_flash_waitreceive_done(void)
{
SerialFlash_WaitForReceiveDone();
}
void fy_flash_dmainit(void)
{
}
#if 0
const flythings_flash m_flash ={
.flash_init = fly_flash_init,
.flash_deinit = fy_flash_dmainit,
.flash_readdata = fy_flash_read,
.flash_readdata_dma = fy_flash_readdma,
.flash_wait_dma_end = fy_flash_waitreceive_done,
.flash_isreading = fy_flash_isreceiveing
};
#endif
#define TEST_ADDR 0x00000000 // 测试地址
#define TEST_SIZE 512 // 测试数据长度 (多一点测试DMA)
// 普通 + DMA Flash 测试
void Flash_Test_DMA(void)
{
uint32_t id;
uint8_t txBuf[TEST_SIZE];
uint8_t rxBuf[TEST_SIZE];
// printf("==== SPI FLASH DMA TEST START ====\n");
// 1. 初始化 Flash
// fly_flash_init();
// 2. 读取 JEDEC ID
id = fy_flash_readid();
// printf("Flash ID = 0x%06X\n", id);
// 3. 擦除测试区域 (4KB)
// printf("Erasing sector...\n");
// fy_flash_erase_block(TEST_ADDR, 0x1000);
// while (fy_flash_isbusy());
// 4. 准备写入数据
for (int i = 0; i < TEST_SIZE; i++)
txBuf[i] = i + 0xA0;
// // printf("Writing test data...\n");
// fy_flash_page_write(TEST_ADDR, txBuf, TEST_SIZE);
// while (fy_flash_isbusy());
// 5. DMA读测试
memset(rxBuf, 0, sizeof(rxBuf));
// printf("Start DMA read...\n");
fy_flash_read(TEST_ADDR, rxBuf, TEST_SIZE); //OK,but Speed limited
fy_flash_readdma(0x40000, gImage_test, 25600);//gImage_test
fy_flash_readdma(TEST_ADDR, gImage_test, 256);//gImage_test
fy_flash_readdma(0x46400, gImage_test, 25600);//gImage_test
// 等待DMA完成
// fy_flash_waitreceive_done();
// 6. 比对结果
if (memcmp(txBuf, rxBuf, TEST_SIZE) == 0)
{
// printf("DMA Flash Test OK! Data matched.\n");
}
else
{
// printf("DMA Flash Test FAILED!\n");
// printf("TX: ");
// for (int i = 0; i < TEST_SIZE; i++) printf("%02X ", txBuf[i]);
// printf("\nRX: ");
// for (int i = 0; i < TEST_SIZE; i++) printf("%02X ", rxBuf[i]);
// printf("\n");
}
// printf("==== SPI FLASH DMA TEST END ====\n");
}