Thanks Tesla DeLorean for the helpful input. I realize I should have put up some signal form just to explain what I was after.
Summarizing my issue and solution:
- I was struggling to understand how the looping (of circular mode) was being handled through the HAL API. The most important part I missed is that the HAL_DMA_Start_IT(Channel, Output, Input, **DATALENGTH**); is talking about the size of the output location, which is directly stuffed into the DMA NDTR register.
- The circular mode being triggered off an EXTI interrupt means that "PeriphDataAlignment" will be read "dmamux_ReqGenParams.RequestNumber" times per interrupt. What I missed here is again related to point 1, datalength (aka NDTR) controls the warp around point of the DMA output. Which I initially thought to be controlled by "dmamux_ReqGenParams.RequestNumber".
Fixes:
- Changed the datalength to be 2, as I want the completion interrupt only when 2 values have been read. I don't need the halfway interrupt.
- Set request to back to 1. Because each edge just needs to trigger 1 read.
- Went back to a single buffer, as I have ample time to use the values in sram.
Here is the currently working init and a picture that explains the data collected for portA
int InitializeDmaChannels(void)
{
HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams = {0};
/*##-2- Configure the DMA ##################################################*/
/* Enable BDMA clock */
__HAL_RCC_BDMA_CLK_ENABLE();
{ // Channel 0 init.
/* Configure the DMA handler for Transmission process */
/* DMA mode is set to circular for an infinite DMA transfer */
DMA_Handle_Channel0.Instance = BDMA_Channel0;
DMA_Handle_Channel0.Init.Request = BDMA_REQUEST_GENERATOR0;
DMA_Handle_Channel0.Init.Direction = DMA_PERIPH_TO_MEMORY;
DMA_Handle_Channel0.Init.PeriphInc = DMA_PINC_DISABLE;
DMA_Handle_Channel0.Init.MemInc = DMA_MINC_ENABLE;
DMA_Handle_Channel0.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
DMA_Handle_Channel0.Init.MemDataAlignment = DMA_PDATAALIGN_WORD;
DMA_Handle_Channel0.Init.Mode = DMA_CIRCULAR;
DMA_Handle_Channel0.Init.Priority = DMA_PRIORITY_VERY_HIGH;
DMA_Handle_Channel0.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
DMA_Handle_Channel0.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
DMA_Handle_Channel0.Init.MemBurst = DMA_MBURST_SINGLE;
DMA_Handle_Channel0.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Initialize the DMA with for Transmission process */
HAL_StatusTypeDef dmares = HAL_OK;
dmares = HAL_DMA_Init(&DMA_Handle_Channel0);
if (dmares != HAL_OK) {
Error_Handler();
}
/* Select Callbacks functions called after Transfer complete and Transfer error */
dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_CPLT_CB_ID, NULL);
if (dmares != HAL_OK) {
Error_Handler();
}
dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
if (dmares != HAL_OK) {
Error_Handler();
}
/* NVIC configuration for DMA transfer complete interrupt*/
HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
/*##-3- Configure and enable the DMAMUX Request generator ####################*/
dmamux_ReqGenParams.SignalID = HAL_DMAMUX2_REQ_GEN_EXTI0;
dmamux_ReqGenParams.Polarity = HAL_DMAMUX_REQ_GEN_RISING_FALLING;
dmamux_ReqGenParams.RequestNumber = 1; /* 1 requests on each edge of the external request signal */
dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel0, &dmamux_ReqGenParams);
if (dmares != HAL_OK) {
Error_Handler();
}
/* NVIC configuration for DMAMUX request generator overrun errors*/
HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel0);
if (dmares != HAL_OK) {
Error_Handler();
}
dmares = HAL_DMA_Start_IT(&DMA_Handle_Channel0, (uint32_t)&(GPIOB->IDR), (uint32_t)(PortBBuffer), 2);
if (dmares != HAL_OK) {
Error_Handler();
}
}
{ // Channel 1 init.
/* Configure the DMA handler for Transmission process */
/* DMA mode is set to circular for an infinite DMA transfer */
DMA_Handle_Channel1.Instance = BDMA_Channel1;
DMA_Handle_Channel1.Init.Request = BDMA_REQUEST_GENERATOR0;
DMA_Handle_Channel1.Init.Direction = DMA_PERIPH_TO_MEMORY;
DMA_Handle_Channel1.Init.PeriphInc = DMA_PINC_DISABLE;
DMA_Handle_Channel1.Init.MemInc = DMA_MINC_ENABLE;
DMA_Handle_Channel1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DMA_Handle_Channel1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
DMA_Handle_Channel1.Init.Mode = DMA_CIRCULAR;
DMA_Handle_Channel1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
DMA_Handle_Channel1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
DMA_Handle_Channel1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
DMA_Handle_Channel1.Init.MemBurst = DMA_MBURST_SINGLE;
DMA_Handle_Channel1.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Initialize the DMA with for Transmission process */
HAL_StatusTypeDef dmares = HAL_OK;
dmares = HAL_DMA_Init(&DMA_Handle_Channel1);
if (dmares != HAL_OK) {
Error_Handler();
}
/* Select Callbacks functions called after Transfer complete and Transfer error */
dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_CPLT_CB_ID, NULL);
if (dmares != HAL_OK) {
Error_Handler();
}
dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
if (dmares != HAL_OK) {
Error_Handler();
}
/* NVIC configuration for DMA transfer complete interrupt*/
HAL_NVIC_SetPriority(BDMA_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(BDMA_Channel1_IRQn);
/*##-3- Configure and enable the DMAMUX Request generator ####################*/
dmamux_ReqGenParams.SignalID = HAL_DMAMUX2_REQ_GEN_EXTI0;
dmamux_ReqGenParams.Polarity = HAL_DMAMUX_REQ_GEN_RISING_FALLING;
dmamux_ReqGenParams.RequestNumber = 1;
dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel1, &dmamux_ReqGenParams);
if (dmares != HAL_OK) {
Error_Handler();
}
/* NVIC configuration for DMAMUX request generator overrun errors*/
HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel1);
if (dmares != HAL_OK) {
Error_Handler();
}
volatile uint32_t dmares1 = HAL_DMA_Start_IT(&DMA_Handle_Channel1, (uint32_t)&(GPIOA->IDR), (uint32_t)(PortABuffer), 2);
if (dmares1 != HAL_OK) {
Error_Handler();
}
}
return 0;
}
