2024-05-03 10:26 AM
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);
}
2024-05-03 02:09 PM
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..
2024-05-03 02:37 PM
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
2024-05-03 03:20 PM
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);
2024-05-03 03:24 PM
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
2024-05-03 03:30 PM
What is the solution that won't be accepted??
2024-05-03 03:37 PM
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
2024-05-03 04:18 PM
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.
2024-05-03 04:22 PM - edited 2024-05-03 05:51 PM
2024-05-03 05:51 PM
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);
}