Перейти к содержанию
    

Stm32f411 Не работает DMA (Memory->GPIO) по таймеру.

Приветствую!

Не работает DMA. Пересылка Memory->GPIO по таймеру.

Идея в том, что Timer1 Channel1 по событию UpdateEvent запускает DMA передачу в порт B. Побайтно, в циклическом режиме.

Таймер работает (видно по выходу осциллографом), а в порту B тишина - все пины 0 

Подскажите - как запустить DMA передачу?

PS: За основу брал статью https://istarik.ru/blog/stm32/139.html

 

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  PrepareDMAbuffer();   // Здесь в буфер заливаются данные буфер 12900байт
  HAL_DMA_Start(htim1.hdma[TIM_DMA_ID_UPDATE], (uint32_t)DMAbuff, (uint32_t)&GPIOB->ODR, BUFFSIZE);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);  

/* Enable the TIM Update DMA request */
  __HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);
  /* Enable the Peripheral */
  __HAL_TIM_ENABLE(&htim1);

 

2024-04-14_16_48_16-Cube_-_Device_Configuration_Tool_-_STM32CubeIDE.png

2024-04-14_16_45_45-Cube_-_Device_Configuration_Tool_-_STM32CubeIDE.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Флаги в регистрах DMA посмотрите, происходят ли передачи, не ли ошибок. Запись в GPIO->ODR программно работает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

53 minutes ago, amaora said:

Флаги в регистрах DMA посмотрите, происходят ли передачи, не ли ошибок. Запись в GPIO->ODR программно работает?

Да, программно работает.
Спасибо за идею с регистрами - посмотрю.

А  где то есть дока на функции типа HAL_DMA_Start() и макросы __HAL_TIM_ENABLE_DMA() - в какой последовательности их запускать, с примерами итд?
А то вслепую тащу их из интернета, а нормальной доки нет.

По исходникам смотрю - но там совсем не ясно в какой последовательности их использовать и какие из них нужны?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 16.04.2024 в 03:24, Mty сказал:

А  где то есть дока на функции типа HAL_DMA_Start

Так ищи в гугле слово "HAL_DMA_Start" там множество примеров будет.

Еще примеры были в комплекте с документацией для отладочных плат STM. Скачивается на их сайте.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Стоит обратить внимание, что GPIO находятся на шине AHB1, доступ к которой имеет только DMA2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Решено!

Спасибо всем.

HAL_DMA_Init(&hdma_tim1_up);

HAL_DMA_Start(&hdma_tim1_up, (uint32_t)&DMAbuff, (uint32_t)&GPIOB->ODR, MAX_TICKS);

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

TIM1->DIER |= (1 << 8);

Одна из основных проблем была в том, что потерялся & перед &DMAbuff
Кроме того переписал все попутно в регистрах. И думаю - дальше работать с регистрами, или остаться в HAL?
Привожу ниже - может кому пригодится

  DMA2_Stream5->PAR = (uint32_t)&(GPIOB->ODR); 		// Set peripheral address
  DMA2_Stream5->M0AR = (uint32_t)&DMAbuff;			// Set memory address
  DMA2_Stream5->NDTR = MAX_TICKS; 					// set number of bytes to transfer

  DMA2_Stream5->CR |= (6 << DMA_SxCR_CHSEL_Pos); 	// enable channel 6 (TIM1_UP)
  DMA2_Stream5->CR |= (2 << DMA_SxCR_PL_Pos); 		// set to high priority
  //   FIFO should be disabled by default
  DMA2_Stream5->CR |= (1 << DMA_SxCR_DIR_Pos); 		//set memory-to-peripheral
  DMA2_Stream5->CR |= (1 << DMA_SxCR_MINC_Pos); 	//Incremement memory address
  // Assume PINC is 0
  //Assume burst is set to single transfer
  DMA2_Stream5->CR |= (0 << DMA_SxCR_MSIZE_Pos); 	// Set memory data width to a byte
  DMA2_Stream5->CR |= (0 << DMA_SxCR_PSIZE_Pos); 	// Set peripheral data width to a byte
  DMA2_Stream5->CR |= (1 << DMA_SxCR_CIRC_Pos); 	// Set to circular mode
  // Assume DBM is zero
  DMA2_Stream5->CR |= (1 << DMA_SxCR_EN_Pos); 		//enable DMA


  TIM1->DIER |= (1 << 8);   // set UDE bit (update dma request enable)
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/17/2024 at 1:52 PM, Mty said:
  DMA2_Stream5->CR |= (6 << DMA_SxCR_CHSEL_Pos); 	// enable channel 6 (TIM1_UP)
  DMA2_Stream5->CR |= (2 << DMA_SxCR_PL_Pos); 		// set to high priority
  //   FIFO should be disabled by default
  DMA2_Stream5->CR |= (1 << DMA_SxCR_DIR_Pos); 		//set memory-to-peripheral
  DMA2_Stream5->CR |= (1 << DMA_SxCR_MINC_Pos); 	//Incremement memory address
  // Assume PINC is 0
  //Assume burst is set to single transfer
  DMA2_Stream5->CR |= (0 << DMA_SxCR_MSIZE_Pos); 	// Set memory data width to a byte
  DMA2_Stream5->CR |= (0 << DMA_SxCR_PSIZE_Pos); 	// Set peripheral data width to a byte
  DMA2_Stream5->CR |= (1 << DMA_SxCR_CIRC_Pos); 	// Set to circular mode
  // Assume DBM is zero
  DMA2_Stream5->CR |= (1 << DMA_SxCR_EN_Pos); 		//enable DMA

Почему на запись каждого бита отдельная операция ?

Почему не прописали все биты одной операцией ?

 

Вот так

  DMA2_Stream5->CR =  (6 << DMA_SxCR_CHSEL_Pos) |	// enable channel 6 (TIM1_UP)
                      (2 << DMA_SxCR_PL_Pos)    |	// set to high priority
                      (1 << DMA_SxCR_DIR_Pos)   |	//set memory-to-peripheral
                      (1 << DMA_SxCR_MINC_Pos)  |	//Incremement memory address
                      (0 << DMA_SxCR_MSIZE_Pos) |	// Set memory data width to a byte
                      (0 << DMA_SxCR_PSIZE_Pos) | 	// Set peripheral data width to a byte
                      (1 << DMA_SxCR_CIRC_Pos)  |	// Set to circular mode
                      (1 << DMA_SxCR_EN_Pos); 		//enable DMA

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Mty сказал:
  DMA2_Stream5->CR |= (6 << DMA_SxCR_CHSEL_Pos); 	// enable channel 6 (TIM1_UP)
  DMA2_Stream5->CR |= (2 << DMA_SxCR_PL_Pos); 		// set to high priority
...

Кошмар....:fool:  Отрубание хвоста собаки по частям.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/17/2024 at 3:27 PM, jcxz said:

Кошмар....:fool:  Отрубание хвоста собаки по частям.

Так наоборот же.

Пришивание :sarcastic:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

27 minutes ago, dimka76 said:

Почему на запись каждого бита отдельная операция ?

Почему не прописали все биты одной операцией ?

 

Вот так

  DMA2_Stream5->CR =  (6 << DMA_SxCR_CHSEL_Pos) |	// enable channel 6 (TIM1_UP)
                      (2 << DMA_SxCR_PL_Pos)    |	// set to high priority
                      (1 << DMA_SxCR_DIR_Pos)   |	//set memory-to-peripheral
                      (1 << DMA_SxCR_MINC_Pos)  |	//Incremement memory address
                      (0 << DMA_SxCR_MSIZE_Pos) |	// Set memory data width to a byte
                      (0 << DMA_SxCR_PSIZE_Pos) | 	// Set peripheral data width to a byte
                      (1 << DMA_SxCR_CIRC_Pos)  |	// Set to circular mode
                      (1 << DMA_SxCR_EN_Pos); 		//enable DMA

 

Да, спасибо, конечно так сделаю.
А для проверки ошибок DMA можно просто опрашивать флаг DMA high interrupt status register (DMA_HISR)  TEIF5 без прерывания, верно?


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/17/2024 at 3:53 PM, Mty said:

А для проверки ошибок DMA можно просто опрашивать флаг DMA high interrupt status register (DMA_HISR)  TEIF5 без прерывания, верно?

Можно.

Только зачем тратить на это процессорное время ?

Лучше разрешить на них прерывания и обработку ошибок вести только в случае возникновения этих ошибок.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...