// #include // #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); } /******************************************************************************************************** **������Ϣ : **�������� : **������� : **������� : ** ��ע : ********************************************************************************************************/ 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��Ƶ 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; // �ڴ������跽�� HdmaCh4.Init.PeriphInc = DMA_PINC_DISABLE; // ��������ģʽ �ر� HdmaCh4.Init.MemInc = DMA_MINC_ENABLE; // �ڴ�����ģʽ ���� HdmaCh4.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // �������ݸ�ʽ: BYTE HdmaCh4.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // �ڴ����ݸ�ʽ: BYTE HdmaCh4.Init.Mode = DMA_NORMAL; // ��ֹѭ��ģʽ HdmaCh4.Init.Priority = DMA_PRIORITY_MEDIUM; // ���ȼ�: �� HAL_DMA_Init(&HdmaCh4); __HAL_LINKDMA(&FlashSpiHandle, hdmatx, HdmaCh4); // DMA_CH2 ���� 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; // �ڴ������跽�� HdmaCh3.Init.PeriphInc = DMA_PINC_DISABLE; // ��������ģʽ �ر� HdmaCh3.Init.MemInc = DMA_MINC_ENABLE; // �ڴ�����ģʽ ���� HdmaCh3.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // �������ݸ�ʽ: BYTE HdmaCh3.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // �ڴ����ݸ�ʽ: BYTE HdmaCh3.Init.Mode = DMA_NORMAL; // ��ֹѭ��ģʽ HdmaCh3.Init.Priority = DMA_PRIORITY_HIGH; // ���ȼ�: �� HAL_DMA_Init(&HdmaCh3); __HAL_LINKDMA(&FlashSpiHandle, hdmarx, HdmaCh3); // DMA_CH3 ���� 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; iSR & 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); // 启动 DMA:TX 发 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 <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"); }