2023-02-10 03:24 AM
Hello All,
I am adding parts of my code. Storing to flash is working if I DMA TIM1 CCR1 to memory and then copy from memory buffer to Flash.
I assumed that writing to QSPI_DR will trigger transfer to Flash.
Is it feasible to DMA to QSPI?
/////////////////////////////////////////////////////////////////////////////////
/* Erasing sectors 1 and 2 - want to store at 0x2000*/
W25Q_EraseSector(1);
W25Q_EraseSector(2);
HAL_DMA_RegisterCallback(&hdma_tim6_up, HAL_DMA_XFER_CPLT_CB_ID, frequencyCollectCallback);
QSPI_CommandTypeDef com;
com.InstructionMode = QSPI_INSTRUCTION_1_LINE;
com.Instruction = W25Q_PAGE_PROGRAM; // Command = 0x2
com.AddressSize = QSPI_ADDRESS_24_BITS;
com.AddressMode = QSPI_ADDRESS_1_LINE;
com.Address = 0x2000;
com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
com.DummyCycles = 0;
com.DataMode = QSPI_DATA_1_LINE;
com.NbData = 100;
com.DdrMode = QSPI_DDR_MODE_DISABLE;
com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
com.SIOOMode = QSPI_SIOO_INST_ONLY_FIRST_CMD;
if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
return W25Q_SPI_ERR;
HAL_Delay(100);
HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2); // Indirect Channel
HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1); // main channel
HAL_Delay(10);
HAL_TIM_Base_Start(&htim6); // Start Collecting
/* DMA from CCR1 to QSPI DR */
HAL_DMA_Start_IT(&hdma_tim6_up, (uint32_t)(&TIM1->CCR1), (uint32_t)(&QUADSPI->DR), 100);
htim6.Instance->DIER = 0x0100;
HAL_Delay(1000);
if (buffer_full1) { //buffer_full1 is set in Interrupt routine
uint32_t flash_data_addr = 0x2000;
uint8_t read_buf[MEM_PAGE_SIZE] = {0};
W25Q_SingleRead(read_buf, 100, flash_data_addr);
LOGD("\nflash_data_addr: 0x%x\n",flash_data_addr);
for (uint32_t j=0; j< 100; j+=2)
LOGD("0x%x\t", read_buf[j]);
while(1){}
/////////////////////////////////////////////////////////////////////////////////////////////////
DMA init part : Have tried Mem Data Half Word alignment also
/* TIM6 DMA Init */
/* TIM6_UP Init */
hdma_tim6_up.Instance = DMA1_Channel3;
hdma_tim6_up.Init.Request = DMA_REQUEST_6;
hdma_tim6_up.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_tim6_up.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim6_up.Init.MemInc = DMA_MINC_DISABLE;
hdma_tim6_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_tim6_up.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_tim6_up.Init.Mode = DMA_NORMAL;
hdma_tim6_up.Init.Priority = DMA_PRIORITY_VERY_HIGH;
if (HAL_DMA_Init(&hdma_tim6_up) != HAL_OK)
2023-02-10 04:22 AM
The Hardware doesn't work this way.
You'll need to stage in RAM and be more aware of how page write works.
2023-02-12 08:51 PM
Hello
I have these doubts, can you please clarify.
HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) -- With this I am preparing the Flash write command (QSPI CCR).
QSPI_SIOO_INST_ONLY_FIRST_CMD => implies that the command need not be repeated every write to Flash ( supported by WINBOUND W25Q128 Flash)
HAL_DMA_Start_IT : DMA transfer from TIM1_CCR1 to QSPI_DR register (Peripheral to peripheral) - This in turn should write to the QSPI_DR. The first write to QSPI_DR should provide the Write command (Command opcode 0x2) to Flash along with Data (Command+Data).
Next DMA transfers should result in QSPI_DR being written and thus write to Flash without repeating Command every write (because of QSPI_SIOO_INST_ONLY_FIRST_CMD).
I am writing <256 bytes starting from a Page Boundary. I have erased the corresponding sector at beginning.
Winbound W25Q128 Flash has 4096 byte sector, supports Sector Erase.
Page = 256 bytes.
My regards