STM32F4 Discovery SPI with DMA Ghost byte
I want to write a buffer into Winbond SPI flash using SPI DMA. When I write buffer, DMA write a null byte at first location and then start writing my buffer from second location and hence writes one character less than it should write. I donot know from where this null byte is comming. For example when I write ''ALI'' at 0x00 address, Data read from flash is ''<NULL>AL''. Without DMA all works fine. Below is the Code(I have included only necessary functions)
uint8_t TxBuffer1[] = ''ALI'';&sharpdefine countof(a) (sizeof(a) / sizeof(*(a)))&sharpdefine TxBufferSize1 (countof(TxBuffer1)-1)/** * @brief Initializes the peripherals used by the SPI FLASH driver. * @param None * @retval None */void sFLASH_Init(void){ SPI_InitTypeDef SPI_InitStructure; sFLASH_LowLevel_Init(); /*!< Deselect the FLASH: Chip Select high */ sFLASH_CS_HIGH(); /*!< SPI configuration */ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;// also works at SPI_CPOL_Low with SPI_CPHA_1Edge SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;//(APB1/2=21MHz SPI Clock) SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(sFLASH_SPI, &SPI_InitStructure); /*!< Enable the sFLASH_SPI */ SPI_Cmd(sFLASH_SPI, ENABLE);}/** * @brief Writes more than one byte to the FLASH with a single WRITE cycle * (Page WRITE sequence). * @note The number of byte can't exceed the FLASH page size. * @param pBuffer: pointer to the buffer containing the data to be written * to the FLASH. * @param WriteAddr: FLASH's internal address to write to. * @param NumByteToWrite: number of bytes to write to the FLASH, must be equal * or less than ''sFLASH_PAGESIZE'' value. * @retval None */void sFLASH_DMA_WritePage(uint32_t WriteAddr){ /*!< Enable the write access to the FLASH */ sFLASH_WriteEnable(); /*!< Select the FLASH: Chip Select low */ sFLASH_CS_LOW(); /*!< Send ''Write to Memory '' instruction */ sFLASH_SendByte(sFLASH_CMD_WR_PAGE); /*!< Send WriteAddr high nibble address byte to write to */ sFLASH_SendByte((WriteAddr & 0xFF0000) >> 16); /*!< Send WriteAddr medium nibble address byte to write to */ sFLASH_SendByte((WriteAddr & 0xFF00) >> 8); /*!< Send WriteAddr low nibble address byte to write to */ sFLASH_SendByte(WriteAddr & 0xFF); while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET); /*!< while there is data to be written on the FLASH */ DMA_Cmd(DMA1_Stream4, ENABLE); }/** * @brief Sends a byte through the SPI interface and return the byte received * from the SPI bus. * @param byte: byte to send. * @retval The value of the received byte. */uint8_t sFLASH_SendByte(uint8_t byte){ /*!< Loop while DR register in not emplty */ while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET); /*!< Send byte through the SPI1 peripheral */ SPI_I2S_SendData(sFLASH_SPI, byte); /*!< Wait to receive a byte */ while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(sFLASH_SPI);}/** * @brief Configures the DMA. * @param None * @retval None */void DMA_Configuration(void){ /* SPI2_Tx DMA1_Channel0_Stream4 */ /* DMA clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); DMA_DeInit(DMA1_Stream4); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)TxBuffer1; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = TxBufferSize1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream4, &DMA_InitStructure); DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}void DMA1_Stream4_IRQHandler(void){ /* Test on DMA Stream Transfer Complete interrupt */ if (DMA_GetITStatus(DMA1_Stream4, DMA_IT_TCIF4)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA1_Stream4, DMA_IT_TCIF4); sFLASH_CS_HIGH(); sFLASH_WaitForWriteEnd(); while(SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET); while(SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_BSY) == SET); /*!< while there is data to be written on the FLASH */ DMA_Cmd(DMA1_Stream4, DISABLE);}}int main(void){ // Configure the DMA DMA_Configuration(); // Enable SPI DMA TX request SPI_I2S_DMACmd(sFLASH_SPI,SPI_I2S_DMAReq_Tx, ENABLE); sFLASH_Erase4KB_32KB_64KB_Chip(0x00,sFLASH_CMD_ER_SECTOR_4KB); sFLASH_DMA_WritePage(0x00); /* Read data from SPI FLASH memory */ sFLASH_ReadBuffer(Read_Buf1, 0x00, TxBufferSize1); for (Index = 0; Index < TxBufferSize1; Index++) { USART1_Put(Read_Buf1[Index]); } while (1);} #spi-dma-stm32
