Например TDA7294

Форум РадиоКот • Просмотр темы - STM32F0 DMA
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Пн дек 22, 2025 19:41:28

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 15 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 19:44:39 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
Уважаемые коты.
Прикрутил я на STM32F051R8 (короче, на STM32F0Discovery) терминал. Всё работает под FreeRTOS760.
Работают очереди, передаются данные эхом от терминала и от задачки-дёргалки.
Работает буфер приёма - передачи, передаются в очередях ссылки на буферы и их длина. Всё нормально.
Двигаюсь дальше.
Делаю передачу USART1 через DMA, чтобы не отнимать у процессора время.
Вот инициализация канала DMA:
Код:
void vInit_dma (void)
{
   RCC->AHBENR |= RCC_AHBENR_DMA1EN;                  // включить тактирование DMA1
   SYSCFG->CFGR1 |= SYSCFG_CFGR1_USART1TX_DMA_RMP;         // переключить запрос USART1 TXE на канал 4
   DMA1_Channel4->CPAR = (__IO uint32_t)&(USART1->TDR);           // адрес перифериии
   DMA1_Channel4->CMAR = (__IO uint32_t)g.USART1_outbuf;   // адрес памяти
   DMA1_Channel4->CNDTR = DMA_CNDTR_NDT & g.usart1_outlen;   // длина пересылки

   DMA1_Channel4->CCR &= ~DMA_CCR_MEM2MEM;   // не из памяти в память
   DMA1_Channel4->CCR &= ~DMA_CCR_PL;      // приоритет низкий
   DMA1_Channel4->CCR |= DMA_CCR_PL_1;   // приоритет высокий
   DMA1_Channel4->CCR &= ~DMA_CCR_MSIZE;   // размер данных 8 бит
   DMA1_Channel4->CCR &= ~DMA_CCR_PSIZE;   // размер периферии 8 бит
   DMA1_Channel4->CCR |= DMA_CCR_MINC;   // память инкрементировать
   DMA1_Channel4->CCR &= ~DMA_CCR_PINC;   // периферию не инкрементировать
   DMA1_Channel4->CCR &= ~DMA_CCR_CIRC;   // циркулярный режим выключен
   DMA1_Channel4->CCR |= DMA_CCR_DIR;      // направление от памяти в периферию
}

Использую 4 канал ДМА, для этого делаю ремап в SYSCFG.
Инициализация USART1 (только настройки, пины не выкладываю)
Код:
void vInit_usart (void)
{
   USART1->CR1 &= ~USART_CR1_UE;               //Выключаем USART1

   RCC->CFGR3     &= ~RCC_CFGR3_USART1SW;      // PCLK selected as USART1 clock
   RCC->APB2ENR |= RCC_APB2Periph_USART1;      //Включаем тактирование USART1

   USART1->CR1 &= ~USART_CR1_M;                  //Данные - 8 бит
   USART1->CR2 &= ~USART_CR2_STOP;               //1 стоп-бит
   USART1->BRR = (APBCLK+BAUDRATE/2)/BAUDRATE; //скорость usart
   USART1->CR1 |= USART_CR1_TE;                  //Включаем передатчик USART1
   USART1->CR1 |= USART_CR1_RE;                  //Включаем приемник USART1
   USART1->CR1 |= USART_CR1_RXNEIE;          //прерывание по приему данных

   USART1->CR3 &= ~USART_CR3_DMAT;      // запретить передачу через ДМА
   USART1->ICR |= USART_ICR_ORECF;
}


И теперь пытаюсь передать буфер в USART1 через DMA1_Channel4:
Код:
void vUSART1_Send_DMA (uint32_t source, uint16_t len )
{
   //   использование ДМА для передачи строки в USART
   USART1->CR1 &= ~USART_CR1_UE;                  //Выключаем USART1
   DMA1_Channel4->CMAR = (__IO uint32_t)source;   // адрес памяти буфера
   DMA1_Channel4->CNDTR = DMA_CNDTR_NDT & len;   // длина пересылки
   DMA1->IFCR = DMA_IFCR_CGIF4;            // сбросить флаги прерываний ДМА
   USART1->CR3 |= USART_CR3_DMAT;         // разрешить USART1 передачу через ДМА
   USART1->CR1 |= USART_CR1_UE;                     //Включаем USART1
   DMA1_Channel4->CCR |= DMA_CCR_EN;         // разрешить DMA4
}


Запускаю всё это в IAR.
Регистры USART и DMA соответствуют программе, адреса в DMA правильные, а передача не происходит.
В инете есть примеры с использованием через функции SPL, и для 104 контроллера.
Вроде бы всё повторил, но где-то недосмотрел.
Если переключаю программу на вывод по ожиданию в цикле без ДМА, то всё отлично работает.
Где недосмотрел, подскажите.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 21:02:22 
Друг Кота
Аватар пользователя

Карма: 30
Рейтинг сообщений: 156
Зарегистрирован: Пн июл 28, 2008 22:12:01
Сообщений: 3604
Рейтинг сообщения: 0
В нециклическом режиме. Сначала конфигурируем DMA и включаем , только потом включаем периферию.
По отработке DMA, сначала отключаем DMA только потом периферию.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 22:34:59 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
Благодарю за подсказку.
Но в этом примере http://microtechnics.ru/stm32-uchebnyj-kurs-dma/
программа сначала разрешает USART, а затем включает DMA.
Это лажа написана?
Код:
int main()
{
    __enable_irq();
    initAll();
    USART_Cmd(USART1, ENABLE);
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    DMA_Cmd(DMA1_Channel4, ENABLE);
    while(1)
    {
    __NOP();
    }
}


Или 104 камень по другому с DMA работает?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 22:44:36 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
Заодно подскажите ответ на другой вопрос.
Пересылка данных в USART с использованием DMA.
В первый раз DMA свободен, все флаги прерывания равны нулю.
Мы указываем ему переслать пачку данных в USART, а процессор тем временем занимается своим делом.
Но вот понадобилось передать ещё пачку данных.
Определить, закончилась ли предыдущая передача возможно по установленному флагу TCIFx в регистре DMA_ISR.
Но в первый раз у нас регистр был равен нулю, а теперь надо ждать единичку.
Мне что, нужно переменную состояния вставлять для корректной работы?
Или этот вопрос можно решить попроще?


Вернуться наверх
 
Эиком - электронные компоненты и радиодетали
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 22:47:19 
Друг Кота
Аватар пользователя

Карма: 30
Рейтинг сообщений: 156
Зарегистрирован: Пн июл 28, 2008 22:12:01
Сообщений: 3604
Рейтинг сообщения: 1
GARMIN ключевое слово нециклический режим - именно тот что у тебя. Для того что бы переписать количество транзакций , а оно после отработки DMA становиться равным нулю . Нужна последовательность описанная мной .
Ты же это не собираешься использовать единственный раз, как товарищ-учитель по ссылке.
У него еще все впереди ...


GARMIN писал(а):
Мне что, нужно переменную состояния вставлять для корректной работы?


Тебе что нужно ? Посылать буфер через какой то равный промежуток времени или запускать передачу "вручную" ?


Последний раз редактировалось dosikus Вт дек 17, 2013 22:51:29, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 23:10:09 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
Запускать передачу вручную по событию. Приём нужен постоянно - это дуплекс.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 23:13:04 
Друг Кота
Аватар пользователя

Карма: 30
Рейтинг сообщений: 156
Зарегистрирован: Пн июл 28, 2008 22:12:01
Сообщений: 3604
Рейтинг сообщения: 1
dosikus писал(а):
В нециклическом режиме. Сначала конфигурируем DMA и включаем , только потом включаем периферию.
По отработке DMA, сначала отключаем DMA только потом периферию.


Да что бы не было недомолвок. Надеюсь понимаешь что под включаем выключаем DMA здесь имеется ввиду канал

GARMIN писал(а):
Запускать передачу вручную по событию. Приём нужен постоянно - это дуплекс.

Ну дык , событие событию рознь.
Что за событие то ? Это Event'ы подразумеваешь или что то иное ?

Вообщем опишу реальную ситуацию .
Через равные промежутки у меня выплевывает через DMA массив-буфер . Реализовано так:
Канал DMA в нециклическом режиме.
Вся конфигурация DMA и SPI ( для USART таже хрень) кроме разрешения канала DMA и SPI делается до main.
Прерывание от таймера настроено на нужный нам промежуток, который кстати намного больше чем общая длительность всех транзакций.
В прерывании заносим количество транзакций DMA и разрешаем канал DMA , Затем SPI .
В прерывании от окончания передачи DMA (флаг TCIFx) естесно сбрасываем флаг , затем отключаем сначала канал DMA потом SPI.
Да , для SPI там еще хитрость есть. :)))


Последний раз редактировалось dosikus Вт дек 17, 2013 23:27:47, всего редактировалось 3 раз(а).

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Вт дек 17, 2013 23:18:13 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
Благодарю. Утром отпишусь, как получилось.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Ср дек 18, 2013 15:30:42 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
В общем, упёрся я в этот ДМА.
Пробовал сначала разрешать ДМА, затем USART,
пробовал наоборот. Не запускается ДМА.
Вот состояния регистров ДМА:
Изображение
Указаны все адреса, размеры, инкремент, разрешён ДМА
Вот регистры управления USART
Изображение
Разрешена передача, разрешен USART, разрешено ДМА в USART
Регистр статуса USART:
Изображение
Не запускается, блин.
Нашёл более подробное описание однократной работы с USART и DMA:
http://electronics-archive.ru/stm32-dma-%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D1%80%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80%D0%BE%D0%B2.html
В нём расписано, что ДМА пинается вручную.
Код:
void StartDMAChannel4(unsigned int LengthBufer)
{
DMA1_Channel4->CCR  &= ~DMA_CCR4_EN;      //запретить работу канала
DMA1_Channel4->CNDTR =  LengthBufer;      //загрузить количество данных для обмена
DMA1->IFCR          = DMA_IFCR_CTCIF4;  //сбросить флаг окончания обмена
DMA1_Channel4->CCR  |=  DMA_CCR4_EN;      //разрешить работу канала
}


Прерывание по окончанию передачи DMA разрешено, но оно не выполняется, так как нет окончания передачи.
Надо где-то покопать. :?
Пока, чтобы не останавливаться, сделаю передачу USART на прерываниях самого USART. Это лучше, чем просто ждать окончания передачи.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Ср дек 18, 2013 15:41:07 
Друг Кота
Аватар пользователя

Карма: 30
Рейтинг сообщений: 156
Зарегистрирован: Пн июл 28, 2008 22:12:01
Сообщений: 3604
Рейтинг сообщения: 1
GARMIN , SYSCFG_CFGR1

Изображение


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Ср дек 18, 2013 16:04:40 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
Вообще-то это вторая строчка в первом сообщении.
Я сразу сказал, что использую 4-й канал DMA и ремаплю его.

Ага, ничего в этом регистре не меняется. одни нули.
Короче, не было тактирования
Код:
   RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;               // включить тактирование SYSCFG

Уже на терминале кучка нулей вылезла.
Дальше разберусь. :)) :)) :))


Последний раз редактировалось GARMIN Ср дек 18, 2013 16:15:16, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Ср дек 18, 2013 16:09:27 
Друг Кота
Аватар пользователя

Карма: 30
Рейтинг сообщений: 156
Зарегистрирован: Пн июл 28, 2008 22:12:01
Сообщений: 3604
Рейтинг сообщения: 0
Хорошо , вечером железо освободится ,посмотрю.

GARMIN писал(а):
Короче, не было тактирования


Слона то и не приметили . :))) :)))


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Ср дек 18, 2013 16:29:26 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
Спрашивается, зачем системному регистру управление тактированием?
Чтобы было? :o


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Ср дек 18, 2013 16:31:53 
Друг Кота
Аватар пользователя

Карма: 30
Рейтинг сообщений: 156
Зарегистрирован: Пн июл 28, 2008 22:12:01
Сообщений: 3604
Рейтинг сообщения: 0
Думается для снижения потребления .


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 DMA
СообщениеДобавлено: Ср дек 18, 2013 21:55:38 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 205
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 936
Откуда: от туда
Рейтинг сообщения: 0
DMA отлично работает.
У меня сделано так:
Инициализация
Код:
   vInit_gpio_pin ();   // инициализировать ножки   
   vInit_dma ();      // инициализировать DMA   
    vInit_nvic ();      // инициализировать прерывания
    vInit_usart ();      // инициализировать USART
    vInit_perem ();      // инициализировать переменные
    __enable_irq ();   // разрешить прерывания

Начало передачи DMA :
Работаю только с DMA, USART включён постоянно, его не трогаю.
Код:
inline void vUSART1_Send_DMA (uint32_t source, uint16_t len )
{
   xSemaphoreTake (g.xDMA4Semaphore, portMAX_DELAY);   // ожидать отдания семафора
   DMA1_Channel4->CMAR = (__IO uint32_t)source;   // адрес памяти буфера
   DMA1_Channel4->CNDTR = len;                  //загрузить количество данных для обмена
   DMA1_Channel4->CCR |= DMA_CCR_EN;            //разрешить работу канала
}

команду xSemaphoreTake можно заменить циклом ожидания флага готовности DMA
Разрешено прерывание окончания передачи DMA, где разрешается новый цикл передачи:
Код:
void DMA1_Channel4_5_IRQHandler (void)
{
   portBASE_TYPE    xWoken = pdFALSE;
   if (DMA1->ISR & DMA_ISR_GIF4)         // прерывание по окончанию вывода в USART1
   {
      DMA1_Channel4->CCR &= ~DMA_CCR_EN;   // запретить DMA4
      DMA1->IFCR = DMA_IFCR_CGIF4;      // сбросить все флаги прерывания ДМА4
      xSemaphoreGiveFromISR (g.xDMA4Semaphore, &xWoken);   // отдаём флаг готовности DMA4
      portYIELD_FROM_ISR (xWoken);   
   }
}

здесь команду xSemaphoreGiveFromISR можно заменить на команду установки флага готовности DMA

Работает всё чётко. :))
Дальше прикручу LCD дисплей 16х1, который давно этого ждёт.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 15 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: Zikon и гости: 18


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y