DMA не генерирует прерывания

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик

Сообщение КАШАК »

Доброго времени суток.
Вывожу WAV файл с SD карты, контроллер STM32F103VCT6. Использую DAC и DMA. Сначала сделал так:
Спойлер

Код: Выделить всё

void Init_Sound(){
   RCC->APB1ENR |= RCC_APB1ENR_DACEN;      // включить тактирование ЦАПа
   DAC->CR      |= DAC_CR_BOFF1;           // отключить выходной буфер
   DAC->CR      |= DAC_CR_EN1;              // включить канал №1

   GPIOA->CRL &= ~GPIO_CRL_MODE4;
   GPIOA->CRL &= ~GPIO_CRL_CNF4;

   //Настроить третий канал ДМА для перемещения данных из буфера
   //в промежуточный регистр данных первого канала ЦАПа:
   RCC->AHBENR         |= RCC_AHBENR_DMA2EN;      //тактирование DMA

   DMA2_Channel3->CPAR  = (uint32_t)&DAC->DHR8R1; //указатель на регистр периферии
   DMA2_Channel3->CMAR  = (uint32_t)&DAC_Buff[0]; //указатель на начало буфера в памяти
   DMA2_Channel3->CCR  |=  DMA_CCR3_DIR;          //направление передачи - из памяти в периферию
   DMA2_Channel3->CNDTR =  512;                   //размер буфера
   DMA2_Channel3->CCR  &= ~DMA_CCR3_PINC;         //адрес периферии не инкрементируем
   DMA2_Channel3->CCR  |=  DMA_CCR3_MINC;         //адрес памяти инкрементируем
   DMA2_Channel3->CCR  &= ~DMA_CCR3_PSIZE;        //размерность данных периферии - 8 бит.
   DMA2_Channel3->CCR  &= ~DMA_CCR3_MSIZE;        //размерность данных памяти    - 8 бит
   DMA2_Channel3->CCR  |=  DMA_CCR3_CIRC;         //включить циклический режим передачи данных
   DMA2_Channel3->CCR  |=  DMA_CCR3_PL;           //приоритет
   DMA2_Channel3->CCR  |=  DMA_CCR3_EN;           //разрешаем работу третьего канала DMA

   NVIC_EnableIRQ(DMA2_Channel3_IRQn);

   //Запуск передачи очередного значения через ДМА будет происходить от TIM6
   RCC->APB1ENR        |=  RCC_APB1ENR_TIM6EN;    //подаем тактирование TIM6
   TIM6->PSC            =  0;                     //Задаем частоту дискретизации 44100

   TIM6->DIER          |=  TIM_DIER_UDE;          //разрешить запрос DMA
}

void wave_playback(const char *FileName)
{
  uint32_t samples;

  f_open( &file, FileName, FA_READ );   //открыть файл FileName для чтения

  f_lseek(&file, 0x1C);                  //переместить указатель на начало полезных данных

  f_read (&file, &samples, 4, &cnt); //прочитать количество семплов

  f_read (&file, &DAC_Buff[0], 512, &cnt);       //загрузить буфер ЦАПа данными

  TIM6->ARR = 72000000/samples;    
  TIM6->CR1 |= TIM_CR1_CEN;                  

  /*                        воспроизведение                              */
  while(1)
  {
     while(!(DMA2->ISR & DMA_ISR_HTIF3)) {}   //ждем освобождение первой части буфера

     f_read (&file, &DAC_Buff[0], 256, &cnt);    //загрузить ее данными

     DMA2->IFCR |= DMA_ISR_HTIF3;             //сбросить флаг

     if(cnt < 256)break;                        //если конец файла

     while(!(DMA2->ISR & DMA_ISR_TCIF3)) {}   //ждем освобождение второй части буфера

     f_read (&file, &DAC_Buff[256], 256, &cnt);  //загрузить ее данными

     DMA2->IFCR |= DMA_ISR_TCIF3;             //сбросить флаг

     if(cnt < 256) break;                        //если конец файла
  }

}
Но так тратится слишком много времени на ожидание установки флагов. МК по сути "висит" до конца воспроизведения. Поэтому решил сделать через прерывания от DMA. Добавил строки:

Код: Выделить всё

 DMA2_Channel3->CCR  |=  DMA_CCR3_HTIE;
 DMA2_Channel3->CCR  |=  DMA_CCR3_TCIE;

NVIC_EnableIRQ(DMA2_Channel3_IRQn);

и саму функцию:
void DMA2_Channel3_IRQHandler(void){//какие-то действия}
В итоге в функцию void DMA2_Channel3_IRQHandler(void) не входит. А может и генерируются, но флаги TCIF3 и HTIF3 не выставляются. Где тут может быть ошибка?
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 725
Зарегистрирован: Вт апр 26, 2011 13:58:36
Откуда: Ростовская область

Сообщение amv2000 »

КАШАК писал(а):Где тут может быть ошибка?
А где он у Вас включается?

Код: Выделить всё

DAC->CR |= DAC_CR_DMAEN1; //Разрешаем запрос DMA в канале 1
Реклама
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик

Сообщение КАШАК »

Добавление этой строчки ничего не изменило, прерываний все равно нет... А без прерываний работало и без этой строчки :dont_know: Может заголовок функции DMA2_Channel3_IRQHandler не верный? Пишу в Eclipse, компилятор Sourcery CodeBench Lite.
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик

Сообщение КАШАК »

Самое интересное то, что от других каналов DMA прерывания приходят, от TIM6 тоже, а именно от 3 канала второго DMA не хотят... Пока сделал через прерывания таймера:

Код: Выделить всё

void TIM6_DAC_IRQHandler(void){

if(TIM6->SR & TIM_SR_UIF){ 
	 
	TIM6->SR &= ~TIM_SR_UIF;

	if(DMA2->ISR & DMA_ISR_HTIF3) {   //ждем освобождение первой части буфера

		f_read (&file, &DAC_Buff[0], 256, &cnt);    //загрузить ее данными

		DMA2->IFCR |= DMA_ISR_HTIF3;             //сбросить флаг

		if(cnt < 256){
			DMA2_Channel3->CCR  &=  ~DMA_CCR3_EN;  //если конец файла

			TIM6->CR1 &= ~TIM_CR1_CEN;             //остановить преобразование

			f_close(&file);                        //закрыть файл
		}
	}

	if(DMA2->ISR & DMA_ISR_TCIF3) {   //ждем освобождение второй части буфера

		f_read (&file, &DAC_Buff[256], 256, &cnt);  //загрузить ее данными

		DMA2->IFCR |= DMA_ISR_TCIF3;             //сбросить флаг

		if(cnt < 256){
			DMA2_Channel3->CCR  &=  ~DMA_CCR3_EN;  //если конец файла

			TIM6->CR1 &= ~TIM_CR1_CEN;             //остановить преобразование

			f_close(&file);                        //закрыть файл
		}
	}

}
}
Но все же интересно, почему от DMA не идут прерывания...
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 725
Зарегистрирован: Вт апр 26, 2011 13:58:36
Откуда: Ростовская область

Сообщение amv2000 »

Так вроде DAC_Channel1 закреплен за третьим каналом второго DMA. И еще ПДП передаёт данные при каждом событии таймера, а Вы не пойму, что хотите провернуть?
Последний раз редактировалось amv2000 Ср авг 14, 2013 14:03:57, всего редактировалось 1 раз.
Реклама
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1303
Зарегистрирован: Вс апр 19, 2009 17:20:22
Откуда: г.Ростов-на-Дону/г.Таганрог/г.Геленджик

Сообщение КАШАК »

Ну так у меня 3 канал и работает
Опыт растет прямо пропорционально выведенному из строя оборудованию...
Контактная информация:
Реклама
Мучитель микросхем
Сообщения: 478
Зарегистрирован: Ср окт 15, 2008 09:33:03
Откуда: Воронеж

Сообщение Galizin »

Может быть нужно включать прерывания ДМА до включения самого канала. А после того как канала сконфигурировали возможно менять его состояние нельзя?
Держит паяльник хвостом
Аватара пользователя
Сообщения: 993
Зарегистрирован: Пн сен 18, 2006 11:16:05
Откуда: Тула

Сообщение Neekeetos »

КАШАК писал(а):Ну так у меня 3 канал и работает
Не знаю насколько в тему, но у меня было так, что дма не хотел работать от событий цап, оказалось, что такты на все блоки, которые участвую в такой связке надо включать до конфигурации, иначе события временами не генерятся. В твоем случае строчку

Код: Выделить всё

  RCC->APB1ENR        |=  RCC_APB1ENR_TIM6EN;    //подаем тактирование TIM6
я бы перенес в начало функции.
Информация по RLC mini находится >тут<
Контактная информация:
Ответить

Вернуться в «ARM»