реклама на сайте
подробности

 
 
> Кто как организует повтор обмена данными по UART'у через DMA?, LPC1768, IAR Embedded 5.4
sambotey
сообщение Sep 8 2011, 15:53
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 25-08-11
Пользователь №: 66 868



Вопрос может показаться нелепым, но я на нем застрял. rolleyes.gif
Если между сеансами передачи данных организовать хотя бы небольшую задержку, то проблем никаких нет. Но если по окончании одного сеанса необходимо тут же начать новый, то второй почему-то зависает. Сразу приходит мысль о том, что по окончании первого сеанса был некорректно закрыт канал, но ни один из вариантов не увенчался успехом. За основу был взят алгоритм из даташита UM10360. LPC17xx. User manual:

Код
  
DMACC0CONFIGURATION_bit.H         = 1;   //any future DMA requests will be ignored
while (DMACC0CONFIGURATION_bit.A);      // wait, while channel FIFO has any data
DMACC0CONFIGURATION_bit.E         = 0;   //channel 0 disabled
while (DMACENBLDCHNS & 0x1);                //wait, while channel 0 is enabled


Но всевозможные очистки очереди запросов прерываний (DMACINTTCCLEAR), отключения DMA для UART'a (U1FCR), отключения каналов DMA (DMACCONFIGURATION = 0) и прочие не помогли.

На всякий случай приведу один из вариантов кода инициализации канала DMA:
Код
// Clear ALL DMA interrupt and error flag
DMACINTTCCLEAR = 0xFF;
DMACINTERRCLR = 0xFF;
DMACC0SRCADDR = 0x40010000;
DMACC0DESTADDR = (unsigned long)srcAddress;
DMACC0CONTROL = (size & 0x0FFF) //TransferSize
                             | (5 << 12)        //Source burst size is 32 bit
                             | (5 << 15)        //Destination burst size is 32 bit
                             | (0 << 18)        //Source transfer width is 1 byte
                             | (0 << 21)        //Destination transfer width is 1 byte  
                             | (0 << 26)        //Source address is NOT incremented              
                             | (1 << 27)        //Destination address is incremented    
                             | 0x80000000;   //The terminal count interrupt is enabled.
DMACCONFIGURATION = 0x01;       // Enable DMA channels, little endian      
DMACC0CONFIGURATION = (1  <<  0) //CHANNEL 0 ENABLE
                                       | (11 <<  1) //Source peripheral is UART1 Rx
                                       | (0  <<  6) //Destination peripheral is memory                          
                                       | (2  << 11) //Transfer type is "peripheral to memory"
                                       | (1  << 14) //Error interrupts are NOT masked out
                                       | (1  << 15) //Terminal count interrupts are NOT masked out
                                       | (0  << 18);//Enable DMA requests
while(!(DMACENBLDCHNS));
DMACINTTCCLEAR = 0x0F;



Однако мне интересно прежде всего, как Вы инициализируете и заканчиваете организацию передачи по UART'у через DMA. В частности, какие регистры и в какой последовательности при этом задействуете, а какие инициализируете в начале программы и не трогаете при повторении инициализации очередного сеанса.
Ни в даташите, ни в интернете, ни в примерах ИАР'а я не нашел однозначного ответа. В частности, из даташита не понятно, для чего нужны регистры, указывающие состояние передачи до маскирования (DMA Raw Error Interrupt Status register и DMA Raw Terminal Count Status register). Ведь мы маскируем прерывания еще до начала сеанса и какая может быть передача до этого момента?

В качестве обработчика прерываний я использую обработчик из примера.
Код
DWORD regVal;

__enable_interrupt();  

regVal = DMACINTTCSTATUS;
if ( regVal )
{
  DMATCCnt++;
  DMACINTTCCLEAR = regVal;
}

regVal = DMACINTERRSTAT;
if ( regVal )
{
  DMAErrCnt++;
  DMACINTERRCLR = regVal;
}

NVIC_ClrPend(NVIC_GP_DMA);


Вроде бы этого достаточно для определения окончания передачи, но судя по тому, что между передачами требуется задержка, о которой я писал в начале, складывается ощущение, что на этом передача не заканчивается.
Хотелось бы узнать, есть ли здесь какие-то "подводные камни". Может кто поделится секретом? rolleyes.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
KRS
сообщение Sep 8 2011, 20:06
Сообщение #2


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Вы уверены что вам для UART нужен DMA?
для начала попробуйте настроить burst в 1 байт и ширину в 1 байт и для памяти и для уарта.
Go to the top of the page
 
+Quote Post
sambotey
сообщение Sep 9 2011, 04:52
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 25-08-11
Пользователь №: 66 868



Да, DMA очень нужен. Потому и приходится биться с ним уже сколько времени.
А рекомендуемую настройку я уже применял:

Код
DMACC0CONTROL = (size & 0x0FFF) //TransferSize
                | (2 << 12)        //SBSize. Source burst size is 8 bit
                | (2 << 15)        //DBSize. Destination burst size is 8 bit
                | (0 << 18)        //SWidth. Source transfer width is 1 byte
                | (0 << 21)        //DWidth. Destination transfer width is 1 byte  
                | (0 << 26)        //SI. Source address is NOT incremented              
                | (1 << 27)        //DI. Destination address is incremented    
                | 0x80000000;   //I. The terminal count interrupt is enabled.


Что касается burst size, то в даташите такое описание "indicates the number of transfers..." из которого не понятно, в каких единицах вычисляется это число - в байтах или битах. Впрочем, я перебрал все варианты этих параметров. Данные передаются лишь при SWidth=0, DWidth=0, SBSize=[3..7], DBSize=[3..7]. Но чему бы ни были равны SBSize и DBSize в указанных пределах, эффект не меняется при изменении этих параметров от 3 до 7 - передача идет, но между сеансами нужна задержка. При SBSize и DBSize равных 0, 1 и 2 данные не передаются вообще. Непонятно почему, ведь при SBSize и DBSize равных 0 по SPI нет проблем вообще.

Сообщение отредактировал sambotey - Sep 9 2011, 04:57
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 9 2011, 10:15
Сообщение #4


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(sambotey @ Sep 9 2011, 08:52) *
то в даташите такое описание "indicates the number of transfers..." из которого не понятно, в каких единицах вычисляется это число - в байтах или битах.

что непонятного - в пересылках, т.е. и не в битах и не в байтах, а в еденицах пересылки, которые вы задали в ширине шины.
А UART правильно настроен, там же надо trigger level у фифо в соотв. с барстом подбирать.
Go to the top of the page
 
+Quote Post
sambotey
сообщение Sep 9 2011, 13:21
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 25-08-11
Пользователь №: 66 868



KRS, спасибо за подсказки. Сейчас пробую новые настройки уарт'а.

А интересно, возможна ли корректная работа DMА при разных значениях SBSize и DBSize в DMACC0CONTROL? Вроде бы нежелательно, чтобы эти значения отличались друг от друга, но зачем тогда было вводит два разных параметра? Достаточно было ввести один "BSize", который применялся бы и к источнику, и к приемнику.
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 9 2011, 19:29
Сообщение #6


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(sambotey @ Sep 9 2011, 17:21) *
А интересно, возможна ли корректная работа DMА при разных значениях SBSize и DBSize в DMACC0CONTROL? Вроде бы нежелательно, чтобы эти значения отличались друг от друга, но зачем тогда было вводит два разных параметра?

Возможно конечно! DMA должен сам перепаковать и т.п. у него же свой фифо есть!
Еще можно попробовать flow controller ом назначить UART (хотя у nxp в даташите это reserved)
Go to the top of the page
 
+Quote Post
sambotey
сообщение Sep 13 2011, 06:52
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 25-08-11
Пользователь №: 66 868



Увы, так я от необходимости задержки между сеансами и не избавился... В итоге, отложил эту проблему. Этот обмен данными выполняется однократно лишь в начале моей программы (этап инициализации), потому, по большому счету, все же не критично. Я так долго занимался этой проблемой, потому что мне казалось, что она тесно связана с действительно критичной проблемой, описанной мною в этом топике. Ее решением оказались следующие настройки:
UART: U1FCR = 0xCF
DMA: SBSize = DBSize = 0

Хотя и тут не обошлось без "танцев с бубнами", потому что мой этап инициализации программы при burst size = 0 уже не работает, ему burst size нужне не менее 3 (т.е., учитывая, что одна передача содержит 14 байт (U1FCR=0xCF), burst size = 3 означает передачу 16*14=224 байта, хотя у меня происходит обмен данными по 6 байт. Или я ошибаюсь в расчетах?)

Парадокс... Надеюсь, найду время попозже вернуться к нему.

Кстати, вышеприведенные настройки все же не приводят к желаемой скорости обмена данными, но работает более-менее стабильно. А вот желаемую скорость я смог получить при SBSize = DBSize = 7, и SWidth = 2 (32байта), но вот работа была нестабильной - через несколько сеансов не могу дождаться ответа от периферии.

KRS, спасибо большое за помощь.
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 13 2011, 07:36
Сообщение #8


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(sambotey @ Sep 13 2011, 10:52) *
хотя у меня происходит обмен данными по 6 байт.

В таком случае DMA не нужен, FIFO более чем достаточно!
Честно говоря вообще сомнительно использование DMA c UART.

DMA к UARTу особенно с переменным числом байтов в пакете проблематично цеплять, а у NXP судя по описанию он вообще криво подцеплен - там же только Burst Request подцеплен. А еще в описании UART таймаут тоже генерирует запрос к DMA, а т.к. подцеплен только барст то сколько байт по таймауту выгребет неизвестно если burst > 1. По идее таймаут к last линии должен быть подключен и flow контроллером должен быть UART но NXP данную конфигурацию не поддерживает!
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 04:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01455 секунд с 7
ELECTRONIX ©2004-2016