Skip to main content
Visitor II
May 7, 2025
Question

How to configure octospi with DMA in indirect write mode?

  • May 7, 2025
  • 3 replies
  • 784 views
/* OCTOSPI1 init function */
void MX_OCTOSPI1_Init(void)
{

 /* USER CODE BEGIN OCTOSPI1_Init 0 */

 /* USER CODE END OCTOSPI1_Init 0 */

 OSPIM_CfgTypeDef sOspiManagerCfg = {0};
 HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};

 /* USER CODE BEGIN OCTOSPI1_Init 1 */

 /* USER CODE END OCTOSPI1_Init 1 */
 hospi1.Instance = OCTOSPI1;
 hospi1.Init.FifoThreshold = 1;
 hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
 hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
 hospi1.Init.DeviceSize = 32;
 hospi1.Init.ChipSelectHighTime = 1;
 hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
 hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
 hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
 hospi1.Init.ClockPrescaler = 4;
 hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
 hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
 hospi1.Init.ChipSelectBoundary = 0;
 hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
 hospi1.Init.MaxTran = 0;
 hospi1.Init.Refresh = 0;
 if (HAL_OSPI_Init(&hospi1) != HAL_OK)
 {
 Error_Handler();
 }
 sOspiManagerCfg.ClkPort = 1;
 sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
 if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
 HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
 if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN OCTOSPI1_Init 2 */

 /* USER CODE END OCTOSPI1_Init 2 */

}

void HAL_OSPI_MspInit(OSPI_HandleTypeDef* ospiHandle)
{

 GPIO_InitTypeDef GPIO_InitStruct = {0};
 DMA_NodeConfTypeDef NodeConfig= {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 if(ospiHandle->Instance==OCTOSPI1)
 {
 /* USER CODE BEGIN OCTOSPI1_MspInit 0 */

 /* USER CODE END OCTOSPI1_MspInit 0 */

 /** Initializes the peripherals clock
 */
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_OSPI;
 PeriphClkInit.OspiClockSelection = RCC_OSPICLKSOURCE_SYSCLK;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 Error_Handler();
 }

 /* OCTOSPI1 clock enable */
 __HAL_RCC_OSPIM_CLK_ENABLE();
 __HAL_RCC_OSPI1_CLK_ENABLE();

 __HAL_RCC_GPIOA_CLK_ENABLE();
 __HAL_RCC_GPIOB_CLK_ENABLE();
 __HAL_RCC_GPIOE_CLK_ENABLE();
 /**OCTOSPI1 GPIO Configuration
 PA3 ------> OCTOSPIM_P1_CLK
 PB0 ------> OCTOSPIM_P1_IO1
 PB1 ------> OCTOSPIM_P1_IO0
 PE14 ------> OCTOSPIM_P1_IO2
 PE15 ------> OCTOSPIM_P1_IO3
 */
 GPIO_InitStruct.Pin = GPIO_PIN_3;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPI1;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPI1;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPI1;
 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

 /* OCTOSPI1 DMA Init */
 /* GPDMA1_REQUEST_OCTOSPI1 Init */
 NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
 NodeConfig.Init.Request = GPDMA1_REQUEST_OCTOSPI1;
 NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
 NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
 NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
 NodeConfig.Init.DestInc = DMA_DINC_FIXED;
 NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
 NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
 NodeConfig.Init.SrcBurstLength = 1;
 NodeConfig.Init.DestBurstLength = 1;
 NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
 NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
 NodeConfig.Init.Mode = DMA_NORMAL;
 NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
 NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
 NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
 if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel3) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel3, NULL, &Node_GPDMA1_Channel3) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel3) != HAL_OK)
 {
 Error_Handler();
 }

 handle_GPDMA1_Channel3.Instance = GPDMA1_Channel3;
 handle_GPDMA1_Channel3.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
 handle_GPDMA1_Channel3.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
 handle_GPDMA1_Channel3.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
 handle_GPDMA1_Channel3.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
 handle_GPDMA1_Channel3.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
 if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel3) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel3, &List_GPDMA1_Channel3) != HAL_OK)
 {
 Error_Handler();
 }

 __HAL_LINKDMA(ospiHandle, hdma, handle_GPDMA1_Channel3);

 if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel3, DMA_CHANNEL_NPRIV) != HAL_OK)
 {
 Error_Handler();
 }

 /* USER CODE BEGIN OCTOSPI1_MspInit 1 */

 /* USER CODE END OCTOSPI1_MspInit 1 */
 }
}
void OCTOSPI1_Init(void)
{
 OCTOSPI1->CR &= ~OCTOSPI_CR_EN;
 while ((OCTOSPI1->CR & OCTOSPI_CR_EN) != 0);

 OCTOSPI1->FCR = OCTOSPI_FCR_CTCF | OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF;

 OCTOSPI1->CR = (1 << OCTOSPI_CR_FTHRES_Pos) | (1 << OCTOSPI_CR_DMAEN_Pos);

 OCTOSPI1->CCR = (0x3 << OCTOSPI_CCR_DMODE_Pos);

 OCTOSPI1->WCCR = (0x3 << OCTOSPI_WCCR_DMODE_Pos);

 OCTOSPI1->WTCR = 0x00000000;

 OCTOSPI1->DLR = 1;

 OCTOSPI1->CR |= (0x0 << OCTOSPI_CR_FMODE_Pos);

 OCTOSPI1->CR |= OCTOSPI_CR_EN;

 MODIFY_REG(OCTOSPI1->CR, OCTOSPI_CR_FMODE, 0x00000000);
}

void main(void)
{
 ...
 MX_OCTOSPI1_Init();
 OCTOSPI1_Init(); 
 HAL_DMA_Start(hospi1.hdma, (uint32_t)QSpiTable, (uint32_t)&OCTOSPI1->DR, 2);

 ...
 while(1);
}

Run the code, dma doesn't transmit anything via octospi.

if I run the code below with the same configuration, I can get signals on oscilloscope.

void main(void)
{

 while(1) {
	 OCTOSPI1_WriteData(QSpiTable, 2);
	 HAL_Delay(1);
 }
}

void OCTOSPI1_WriteData(uint8_t* data, uint32_t length)
{
 for (uint32_t i = 0; i < length; i++) {
 while (!(OCTOSPI1->SR & OCTOSPI_SR_FTF));
 *(__IO uint8_t*)&OCTOSPI1->DR = data[i];
 }
 while (!(OCTOSPI1->SR & OCTOSPI_SR_FTF));
}

Does anyone have the experience about octospi inidrect write mode with dma?

Is it possible to make octospi (quad spi) work as same as spi, just with more IOs?

    This topic has been closed for replies.

    3 replies

    dh_leslieAuthor
    Visitor II
    May 7, 2025

    Another question: Does octospi works under dma circular mode?

    /* OCTOSPI1 init function */
    void MX_OCTOSPI1_Init(void)
    {
    
     /* USER CODE BEGIN OCTOSPI1_Init 0 */
    
     /* USER CODE END OCTOSPI1_Init 0 */
    
     OSPIM_CfgTypeDef sOspiManagerCfg = {0};
     HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};
    
     /* USER CODE BEGIN OCTOSPI1_Init 1 */
    
     /* USER CODE END OCTOSPI1_Init 1 */
     hospi1.Instance = OCTOSPI1;
     hospi1.Init.FifoThreshold = 1;
     hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
     hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
     hospi1.Init.DeviceSize = 32;
     hospi1.Init.ChipSelectHighTime = 1;
     hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
     hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
     hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
     hospi1.Init.ClockPrescaler = 2;
     hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
     hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
     hospi1.Init.ChipSelectBoundary = 0;
     hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
     hospi1.Init.MaxTran = 0;
     hospi1.Init.Refresh = 0;
     if (HAL_OSPI_Init(&hospi1) != HAL_OK)
     {
     Error_Handler();
     }
     sOspiManagerCfg.ClkPort = 1;
     sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
     if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
     {
     Error_Handler();
     }
     HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
     HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
     if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN OCTOSPI1_Init 2 */
    
     /* USER CODE END OCTOSPI1_Init 2 */
    
    }
    
    void HAL_OSPI_MspInit(OSPI_HandleTypeDef* ospiHandle)
    {
    
     GPIO_InitTypeDef GPIO_InitStruct = {0};
     DMA_NodeConfTypeDef NodeConfig= {0};
     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
     if(ospiHandle->Instance==OCTOSPI1)
     {
     /* USER CODE BEGIN OCTOSPI1_MspInit 0 */
    
     /* USER CODE END OCTOSPI1_MspInit 0 */
    
     /** Initializes the peripherals clock
     */
     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_OSPI;
     PeriphClkInit.OspiClockSelection = RCC_OSPICLKSOURCE_PLL1;
     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
     {
     Error_Handler();
     }
    
     /* OCTOSPI1 clock enable */
     __HAL_RCC_OSPIM_CLK_ENABLE();
     __HAL_RCC_OSPI1_CLK_ENABLE();
    
     __HAL_RCC_GPIOA_CLK_ENABLE();
     __HAL_RCC_GPIOB_CLK_ENABLE();
     __HAL_RCC_GPIOE_CLK_ENABLE();
     /**OCTOSPI1 GPIO Configuration
     PA3 ------> OCTOSPIM_P1_CLK
     PB0 ------> OCTOSPIM_P1_IO1
     PB1 ------> OCTOSPIM_P1_IO0
     PE14 ------> OCTOSPIM_P1_IO2
     PE15 ------> OCTOSPIM_P1_IO3
     */
     GPIO_InitStruct.Pin = GPIO_PIN_3;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
     GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPI1;
     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
     GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
     GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPI1;
     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
     GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
     GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPI1;
     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    
     /* OCTOSPI1 DMA Init */
     /* GPDMA1_REQUEST_OCTOSPI1 Init */
     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
     NodeConfig.Init.Request = GPDMA1_REQUEST_OCTOSPI1;
     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
     NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
     NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
     NodeConfig.Init.DestInc = DMA_DINC_FIXED;
     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
     NodeConfig.Init.SrcBurstLength = 1;
     NodeConfig.Init.DestBurstLength = 1;
     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
     NodeConfig.Init.Mode = DMA_NORMAL;
     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
     if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel3) != HAL_OK)
     {
     Error_Handler();
     }
    
     if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel3, NULL, &Node_GPDMA1_Channel3) != HAL_OK)
     {
     Error_Handler();
     }
    
     if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel3) != HAL_OK)
     {
     Error_Handler();
     }
    
     handle_GPDMA1_Channel3.Instance = GPDMA1_Channel3;
     handle_GPDMA1_Channel3.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
     handle_GPDMA1_Channel3.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
     handle_GPDMA1_Channel3.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
     handle_GPDMA1_Channel3.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
     handle_GPDMA1_Channel3.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
     if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel3) != HAL_OK)
     {
     Error_Handler();
     }
    
     if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel3, &List_GPDMA1_Channel3) != HAL_OK)
     {
     Error_Handler();
     }
    
     __HAL_LINKDMA(ospiHandle, hdma, handle_GPDMA1_Channel3);
    
     if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel3, DMA_CHANNEL_NPRIV) != HAL_OK)
     {
     Error_Handler();
     }
    
     /* OCTOSPI1 interrupt Init */
     HAL_NVIC_SetPriority(OCTOSPI1_IRQn, 0, 0);
     HAL_NVIC_EnableIRQ(OCTOSPI1_IRQn);
     /* USER CODE BEGIN OCTOSPI1_MspInit 1 */
    
     /* USER CODE END OCTOSPI1_MspInit 1 */
     }
    }
    HAL_StatusTypeDef QSPI_Write_DMA(uint8_t cmd, uint8_t * pData, uint16_t length)
    {
    	HAL_StatusTypeDef err = HAL_OK;
    	OSPI_RegularCmdTypeDef sCommand = { 0 };
    
    	sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
    
    	sCommand.Instruction = cmd;
    	sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
    	sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
    
    	sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
    	sCommand.NbData = length;
    
    	sCommand.SIOOMode = HAL_OSPI_SIOO_INST_ONLY_FIRST_CMD;
    
    	err = HAL_OSPI_Command(&hospi1, &sCommand, 100);
    	if(HAL_OK != err) {
    		return err;
    	}
    
    	err = HAL_OSPI_Transmit_DMA(&hospi1, pData);
    	if(HAL_OK != err) {
    		return err;
    	}
    	return HAL_OK;
    }
    void main(void)
    {
     MX_OCTOSPI1_Init();
     QSPI_Write_DMA(0xff, QSpiTable, 4);
     while(1) {
     }
    }

    if setting dma as circular mode, HAL_OSPI_Transmit_DMA only sends data one time.

    Is there anything wrong in my configuration?

    Technical Moderator
    May 9, 2025

    Hello @dh_leslie 

     

    For the configuration of OCTOSPI interface in indirect write mode with DMA, I recommend you to look at OSPI_NOR_ReadWrite_DMA_DTR example. This example describes how to erase part of an OSPI NOR memory, write data in DMA mode, read data in DMA mode then compare the result in an infinite loop. The memory is configured in octal DTR mode.

    The OCTOSPI interface is fully configurable and supports two, four, or eight data lines: Single-SPI (traditional SPI), Dual-SPI, Quad-SPI and Octo-SPI. 

    To use the OCTOSPI interface with QUAD memory, I advise you to follow the steps shared in AN5050 section "7.2 OCTOSPI configuration with STM32CubeMX" related Quad-SPI PSRAM APS1604M-3SQR memory.

     

    Thank you.

    Kaouthar

     

    dh_leslieAuthor
    Visitor II
    May 10, 2025

    I have read the documents and soure code before, but I am using a qspi DAC, not a flash memory.

    I suspect whether octospi works under dma circular mode with tim15 trgo.

    Technical Moderator
    May 12, 2025

    Hello @dh_leslie,

     

    I don't find any issue to use the OCTOSPI under DMA normal or circular.

    You just need to respect the constraints imposed by the OCTOSPI, which aren’t related to a circular mode or not.

    Could you please try with DMA normal? Did you find any issues with DMA normal?

    Thank you.

    Kaouthar

    dh_leslieAuthor
    Visitor II
    May 14, 2025

    Just now I tried again to send 4bytes under 1MHz, 10MHz and 40MHz octospi clock,

    octospi under dma normal works well.

    If change to dma circular, (see the pics)

    1MHz clock: works just like dma normal, data is transmitted just once.

    10MHz clock: Command sent once, followed by sending data twice. 

    40MHz clock: Command sent once, followed by sending data 6 times. 

    Something weird:

      1. there is some obvious delay during dma return to the head.

      2. DMA stops after 2~2.5uS under 10MHz and 40MHz.

    Could you share your test code under dma circular?

    scope_1.png

    scope_0.png

    scope_3.png

    HAL_StatusTypeDef QSPI_Write_DMA(uint8_t cmd, uint8_t * pData, uint16_t length)
    {
    	HAL_StatusTypeDef err = HAL_OK;
    	OSPI_RegularCmdTypeDef sCommand = { 0 };
    
    	sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
    
    	sCommand.Instruction = cmd;
    	sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
    	sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
    
    	sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
    	sCommand.NbData = length;
    
    	sCommand.SIOOMode = HAL_OSPI_SIOO_INST_ONLY_FIRST_CMD;
    
    	err = HAL_OSPI_Command(&hospi1, &sCommand, 100);
    	if(HAL_OK != err) {
    		return err;
    	}
    
    	err = HAL_OSPI_Transmit_DMA(&hospi1, pData);
    	if(HAL_OK != err) {
    		return err;
    	}
    	return HAL_OK;
    }