2025-01-08 05:53 AM - last edited on 2025-01-08 05:56 AM by SofLit
Hello and good year everyone,
I am trying to follow the architecture below, where I read 1 ADC halfword at 2KHz via SPI. The idea is to trigger the DMA 1 Channel 3 as soon a new data is available in my SPI. It transfers my data from SPI to RAM.
As soon the DMA Transfer is complete, I need the MDMA to immediately transfer the data from RAM to DTCM.
It seems like my SPI read is good, my DMA transfer from SPI to RAM is good too. However, the MDMA does not transfer any data from RAM to DTCM, do you know why ? Below are the interesting part of my code :
MDMA Config :
static void MX_MDMA_Init(void)
{
/* Activer l'horloge MDMA */
__HAL_RCC_MDMA_CLK_ENABLE();
/* Configuration du canal MDMA */
hmdma_mdma_channel3_dma1_stream3_tc_0.Instance = MDMA_Channel3;
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.Request = MDMA_REQUEST_DMA1_Stream3_TC; // Déclencheur DMA1 Stream3
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.TransferTriggerMode = MDMA_BUFFER_TRANSFER; // Mode Répétitif
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.Priority = MDMA_PRIORITY_HIGH;
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;
/* Configuration Source/Destination */
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.SourceInc = MDMA_SRC_INC_HALFWORD; // Incrémentation source après chaque transfert
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.DestinationInc = MDMA_DEST_INC_HALFWORD; // Incrémentation destination après chaque transfert
/* Alignement des données */
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.SourceDataSize = MDMA_SRC_DATASIZE_HALFWORD;
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.DestDataSize = MDMA_DEST_DATASIZE_HALFWORD;
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
/* Configuration Taille et Burst */
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.BufferTransferLength = 2; // Transferts par bloc
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE;
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.DestBurst = MDMA_DEST_BURST_SINGLE;
/* Offsets */
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.SourceBlockAddressOffset = 0;
hmdma_mdma_channel3_dma1_stream3_tc_0.Init.DestBlockAddressOffset = 0;
/* Initialisation MDMA */
if (HAL_MDMA_Init(&hmdma_mdma_channel3_dma1_stream3_tc_0) != HAL_OK)
{
Error_Handler();
}
/* Configuration du masque */
if (HAL_MDMA_ConfigPostRequestMask(&hmdma_mdma_channel3_dma1_stream3_tc_0, 0, 0) != HAL_OK)
{
Error_Handler();
}
/* Activation de l'interruption MDMA */
HAL_NVIC_SetPriority(MDMA_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(MDMA_IRQn);
/* Démarrer le transfert MDMA */
if (HAL_MDMA_Start_IT(&hmdma_mdma_channel3_dma1_stream3_tc_0,
(uint32_t)adc_burst_sram, // Adresse source
(uint32_t)adc_burst_dtcm, // Adresse destination
2, // Nombre total d'éléments
1) != HAL_OK) // Taille par transfert (en éléments)
{
Error_Handler();
}
}
DMA Config :
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
HAL_DMA_MuxSyncConfigTypeDef pSyncConfig;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(hspi->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspInit 0 */
/* USER CODE END SPI3_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_CLKP;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI3 GPIO Configuration
PB2 ------> SPI3_MOSI
PB3 (JTDO/TRACESWO) ------> SPI3_SCK
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI3 DMA Init */
/* SPI3_RX Init */
hdma_spi3_rx.Instance = DMA1_Stream3;
hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX;
hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi3_rx.Init.Mode = DMA_NORMAL;
hdma_spi3_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
//hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi3_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi3_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_spi3_rx) != HAL_OK)
{
Error_Handler();
}
pSyncConfig.SyncSignalID = HAL_DMAMUX1_SYNC_EXTI0;
pSyncConfig.SyncPolarity = HAL_DMAMUX_SYNC_NO_EVENT;
pSyncConfig.SyncEnable = DISABLE;
pSyncConfig.EventEnable = ENABLE;
pSyncConfig.RequestNumber = 3;
if (HAL_DMAEx_ConfigMuxSync(&hdma_spi3_rx, &pSyncConfig) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi3_rx);
/* SPI3 interrupt Init */
HAL_NVIC_SetPriority(SPI3_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(SPI3_IRQn);
/* USER CODE BEGIN SPI3_MspInit 1 */
__HAL_DMA_ENABLE_IT(&hdma_spi3_rx, DMA_IT_TC); // Désactiver l'interruption de Transfert Complet
__HAL_DMA_DISABLE_IT(&hdma_spi3_rx, DMA_IT_HT); // Désactiver l'interruption de Demi-Transfert
__HAL_DMA_DISABLE_IT(&hdma_spi3_rx, DMA_IT_TE); // Désactiver l'interruption d'Erreur
__HAL_DMA_DISABLE_IT(&hdma_spi3_rx, DMA_IT_DME); // Désactiver les erreurs Direct Mode
__HAL_DMA_DISABLE_IT(&hdma_spi3_rx, DMA_IT_FE); // Désactiver les erreurs FIFO
//HAL_NVIC_DisableIRQ(DMA1_Stream3_IRQn);
/* USER CODE END SPI3_MspInit 1 */
}
}
And my interruption look like :
void DMA1_Stream3_IRQHandler(void)
{
// Appeler le handler HAL pour le DMA1_Stream3
HAL_DMA_IRQHandler(&hdma_spi3_rx);
}
void MDMA_IRQHandler(void)
{
// Gérer l'interruption du MDMA
HAL_MDMA_IRQHandler(&hmdma_mdma_channel3_dma1_stream3_tc_0);
}
/************************************************************
* TIMER INTERRUPTS *
************************************************************/
uint8_t dma_index = 0;
/**
* @brief This function handles TIM1 capture compare interrupt.
*/
void TIM1_CC_IRQHandler(void)
{
/* Vérifier le Flag CC2 et si l'interruption est activée */
if (__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC2) != RESET)
{
if (__HAL_TIM_GET_IT_SOURCE(&htim1, TIM_IT_CC2) != RESET)
{
__HAL_TIM_CLEAR_IT(&htim1, TIM_IT_CC2);
HAL_GPIO_TogglePin(test_2_GPIO_Port, test_2_Pin);
if (dma_index <= 100)
{
HAL_SPI_Receive_DMA(&hspi3, (uint8_t *)&adc_burst_sram[dma_index], 2);
dma_index += 2;
}
else
{
dma_index = 0;
}
}
}
/* Appeler la fonction HAL pour gérer les autres cas généraux */
HAL_TIM_IRQHandler(&htim1);
}
Any help would be much appreciated ! :)
Regards,