cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429I Discovery Peripheral to Memory doesn't work at all DMA

Ahmed Tolba
Associate II

Hello,

I'm trying to use interrupt + dma to capture port D data input, and the interrupt occurs but DMA is not starting to work at all.

Here is my code:

 

 

void HAL_DMA_TransferComplete(DMA_HandleTypeDef *hdma) {

if (hdma->Instance == DMA1_Stream0) {

uint8_t A1;

uint8_t CS1;

uint8_t CS2;

uint8_t data_byte = 0;

for (int i = 0; i < 8; i++) {

data_byte |= ((buffer[0] >> i) & 0x01) << i;

}

A1 = (buffer[0] >> 8) & 0x01;

CS1 = (buffer[0] >> 9) & 0x01;

CS2 = (buffer[0] >> 10) & 0x01;

if ((!CS1) && (!A1)) {

LCD1_write_cmd(data_byte);

}

if ((!CS1) && (A1)) {

LCD1_write_dat(data_byte);

}

if ((!CS2) && (!A1)) {

LCD2_write_cmd(data_byte);

}

if ((!CS2) && (A1)) {

LCD2_write_dat(data_byte);

}



}

}

// External interrupt callback function

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {



if (GPIO_Pin == GPIO_PIN_0) { // PA0 IOWR



HAL_DMA_Start_IT(&hdma_adc1 , (uint32_t)&GPIOD->IDR, (uint32_t)&buffer, 256);



}

static void MX_DMA_Init(void) {

/* DMA controller clock enable */

__HAL_RCC_DMA1_CLK_ENABLE();



/* DMA interrupt init */

HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);



/* DMA initialization code */

hdma_adc1.Instance = DMA1_Stream0;

hdma_adc1.Init.Channel = DMA_CHANNEL_0;

hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;

hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_adc1.Init.Mode = DMA_NORMAL;

hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;

hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)

{

Error_Handler();

}

}

void DMA1_Stream0_IRQHandler(void) {

HAL_DMA_IRQHandler(&hdma_adc1);

}

 

22 REPLIES 22
SofLit
ST Employee

Hello,

Advice: when you face an issue with something try to isolate it and do a test with a reduced code running only that feature.

In your case do a test with a DMA transfer from GPIO to a memory nothing else. So remove LCD, EXTI etc from your code..

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

@SofLit 

I isolated everything and STMCube doesn't support adding GPIO to Memory configuration, it says dma request is not available.

I don't know what's wrong 

SofLit
ST Employee

Need to use DMA2 instead of DMA1 and configure your DMA in memory to memory direction no peripheral request here. You assume GPIOC_IDR as a memory not a peripheral:

  /* Configure DMA request hdma_memtomem_dma2_stream0 on DMA2_Stream0 */
  hdma_memtomem_dma2_stream0.Instance = DMA2_Stream0;
  hdma_memtomem_dma2_stream0.Init.Channel = DMA_CHANNEL_0;
  hdma_memtomem_dma2_stream0.Init.Direction = DMA_MEMORY_TO_MEMORY;
  hdma_memtomem_dma2_stream0.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_memtomem_dma2_stream0.Init.MemInc = DMA_MINC_ENABLE;
  hdma_memtomem_dma2_stream0.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  hdma_memtomem_dma2_stream0.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  hdma_memtomem_dma2_stream0.Init.Mode = DMA_NORMAL;
  hdma_memtomem_dma2_stream0.Init.Priority = DMA_PRIORITY_LOW;
  hdma_memtomem_dma2_stream0.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
  hdma_memtomem_dma2_stream0.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
  hdma_memtomem_dma2_stream0.Init.MemBurst = DMA_MBURST_SINGLE;
  hdma_memtomem_dma2_stream0.Init.PeriphBurst = DMA_PBURST_SINGLE;
  if (HAL_DMA_Init(&hdma_memtomem_dma2_stream0) != HAL_OK)
  {
    Error_Handler( );
  }

HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0 , (uint32_t)&GPIOC->IDR, (uint32_t)&buffer, 256);

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

@SofLit 

I'm trying to read a databus from another MCU using STM32, that solution won't be accepted. I need to capture as much data as I can. I'm capturing based on an interrupt on PA0

What is the solution that won't be accepted??

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

You'll need to diagram / explain better.

Selective pasting of uncommented not as helpful as you might imagine. Comment and show variable definitions.

What's the definition for buffer[] ?

You moving data out to the ADC? Callback doesn't seem to do much, bit processing seems inefficient.

As @SofLit explains on the F2/F4 processors &GPIOx->IDR / ODR is considered a MEMORY address, only DMA2 supports Memory-to-Memory operation.

Typically DMA1 handles Peripherals on APB1 to/from Memory

Typically DMA2 handles Peripherals on APB2 to/from Memory, plus M2M

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Ahmed Tolba
Associate II

@Tesla DeLorean 

I would like to trigger on IOWR (PINA0), and copy the data bus PORTD from PD0 to PD11

I'm not sure which type of DMA to use

I'm bit banging another CPU and capturing its data bus and it's 8080 Interface.

Ahmed Tolba
Associate II
I have to use DMA Per to Mem triggered by the timer
The trigger to timer source, is an interrupt (IOWR) PA0
Ahmed Tolba
Associate II

@SofLit 

to be clear here is an example which is not working:

 

static void MX_TIM2_Init(void)

{

 

/* USER CODE BEGIN TIM2_Init 0 */

 

/* USER CODE END TIM2_Init 0 */

 

TIM_SlaveConfigTypeDef sSlaveConfig = {0};

TIM_MasterConfigTypeDef sMasterConfig = {0};

 

/* USER CODE BEGIN TIM2_Init 1 */

 

/* USER CODE END TIM2_Init 1 */

htim2.Instance = TIM2;

htim2.Init.Prescaler = 0;

htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

htim2.Init.Period = 4294967295;

htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

if (HAL_TIM_Base_Init(&htim2) != HAL_OK)

{

Error_Handler();

}

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;

sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;

sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING;

sSlaveConfig.TriggerFilter = 0;

if (HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig) != HAL_OK)

{

Error_Handler();

}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN TIM2_Init 2 */

HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(TIM2_IRQn);

 

/* USER CODE END TIM2_Init 2 */

 

}

 

/**

* Enable DMA controller clock

*/

static void MX_DMA_Init(void)

{

 

/* DMA controller clock enable */

__HAL_RCC_DMA1_CLK_ENABLE();

 

 

hdma_tim2_up_ch3.Instance = DMA1_Stream5;

hdma_tim2_up_ch3.Init.Channel = DMA_CHANNEL_3;

hdma_tim2_up_ch3.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_tim2_up_ch3.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_tim2_up_ch3.Init.MemInc = DMA_MINC_ENABLE;

hdma_tim2_up_ch3.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

hdma_tim2_up_ch3.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

hdma_tim2_up_ch3.Init.Mode = DMA_NORMAL;

hdma_tim2_up_ch3.Init.Priority = DMA_PRIORITY_LOW;

hdma_tim2_up_ch3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

if (HAL_DMA_Init(&hdma_tim2_up_ch3) != HAL_OK)

{

Error_Handler();

}

 

__HAL_LINKDMA(&htim2, hdma[TIM_DMA_ID_CC1], hdma_tim2_up_ch3);

 

/* DMA interrupt init */

/* DMA1_Stream1_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

 

}

 

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {

 

 

if (GPIO_Pin == GPIO_PIN_0) { // IORD

HAL_TIM_Base_Start(&htim2);

 

}

 

// Timer 2 interrupt handler

void TIM2_IRQHandler(void)

{

HAL_TIM_IRQHandler(&htim2);

}