Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: uart+dma
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Огурцов
как наименьшими телодвижениями организовать приём пакетов ?
пока видится только один вариант - сделать все пакеты одинаковой длины
но даже он не решает полностью - может прийти полпакета или наоборот, больше
после чего остальные пакеты перестанут попадать на границу и прерывание будет вызываться не по концу пакета, а где-то по середине
AHTOXA
Если это STM32, то добавьте прерывание по IDLE.
ViKo
Задавайте в начале каждого пакета его длину.
jcxz
Для любого МК:
При старте rx-DMA, кроме разрешения прерывания по окончанию DMA-транзакции, запустить ещё выдержку времени таймаута, по окончании которого, принудительно останавливать DMA-транзакцию (с определением кол-ва фактически принятых данных).
Таймаут можно отслеживать также в каком-либо периодическом прерывании.
scifi
А лучше без всяких DMA передавать человеческим текстом "var=val" и разделять "\r\n". Так отлаживать удобнее: подцепил терминал - и всё сразу видно.
Огурцов
Цитата(scifi @ Feb 7 2016, 08:36) *
лучше без всяких DMA

на 10 мегабит прерывания уже зашиваются



Цитата(ViKo @ Feb 7 2016, 07:48) *
Задавайте в начале каждого пакета его длину.

т.е. я должен запустить дма, принять второй-третий байт, остановить, дма, перепрограммировать счётчики, запустить дма... ?
за это время уже не один пакет проскочит
и ведь главное, это никак не защищает от битых пакетов и зависоне на ожидании "всех" данных
jcxz
Цитата(scifi @ Feb 7 2016, 13:36) *
А лучше без всяких DMA передавать человеческим текстом "var=val" и разделять "\r\n". Так отлаживать удобнее: подцепил терминал - и всё сразу видно.

a) избыточный траффик;
б) избыточные траты на парсинг.
Да и вопрос был не про уровень протокола, а про уровень взаимодействия с железом.

Цитата(Огурцов @ Feb 7 2016, 14:47) *
на 10 мегабит прерывания уже зашиваются

UART - не лучший выбор для 10-мегабитного потока.
Ещё поди и на STM, где никакого FIFO и в помине нет.....
Огурцов
Цитата(AHTOXA @ Feb 7 2016, 06:52) *
Если это STM32, то добавьте прерывание по IDLE.

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


Цитата(jcxz @ Feb 7 2016, 09:58) *
UART - не лучший выбор для 10-мегабитного потока.

какой же лучший ?

Цитата(jcxz @ Feb 7 2016, 09:58) *
Ещё поди и на STM, где никакого FIFO и в помине нет.....

поди stm
как-то считал, что пара регистров у него таки есть, в один принимает, другой в это время читаем - чем не фифо ?

Цитата(Огурцов @ Feb 7 2016, 10:05) *
а будет ли работать в многопроцессорном режиме ?

а чего бы ему и не работать, надо попробовать
прерывания по смене адреса не хватает, вот тогда бы да
scifi
Можно посмотреть на LIN. Там есть Break.
ViKo
Цитата(Огурцов @ Feb 7 2016, 11:47) *
т.е. я должен запустить дма, принять второй-третий байт, остановить, дма, перепрограммировать счётчики, запустить дма... ?
за это время уже не один пакет проскочит
и ведь главное, это никак не защищает от битых пакетов и зависоне на ожидании "всех" данных

передавайте сначала заголовок пакета, в нем размер. По нему настройте ПДП. А затем передавайте сам пакет.
От зависона спасут таймауты.
mantech
Цитата(Огурцов @ Feb 7 2016, 12:14) *
UART - не лучший выбор для 10-мегабитного потока.

какой же лучший ?


Ethernet? например laughing.gif

ЗЫ. В любом случае даже если это и уарт или спи, в режиме дма, при таких скоростях нужно делать пакетно ориентированную передачу данных с пакетами фиксированной длины, либо передавать несколько пакетов кратной длины.
AHTOXA
Цитата(Огурцов @ Feb 7 2016, 14:14) *
а будет ли работать в многопроцессорном режиме ? когда в один пакет заряжено несколько субпакетов для слейвов ?

Разлеплять склеенные пакеты и собирать пакеты из кусочков - это уже другой уровень. IDLE просто позволяет не зависнуть в ожидании пакета, если байтов поступило меньше, чем ожидается. В принципе, это просто частный случай тайм-аута.
Буфер побольше, прерывания на пол-буфера, на полный буфер, и на IDLE. По любому из этих прерываний - разгребаем принятое.
Вот тут коллега выкладывал пример. Я применял такой подход на скорости 5МБит, сбоев не было. На 10 МБит были редкине сбои, возможно, проблемы линии связи. Выяснять не стал, спустился на 5МБит, хватило. Вот мой вариант.
Огурцов
тут вопрос в другом - будет ли генерироваться idle, если внутри пакета придёт новый адреса слейва ?
было бы правильнее иметь прерывание именно по смене адреса, что абсолютно однозначно указывает на конец пакета


Цитата(mantech @ Feb 7 2016, 14:45) *
Ethernet?

это очень медленный интерфейс с огромных оверхедом
мне надо 62.5 килопакета в секунду, а на эзернете реально получается где-то 25, при 100% загрузке
и ещё его нет в бюджетных камнях

Цитата(mantech @ Feb 7 2016, 14:45) *
фиксированной длины

потенциально это можно, если бы оно только решало


Цитата(ViKo @ Feb 7 2016, 14:30) *
передавайте сначала заголовок пакета, в нем размер. По нему настройте ПДП. А затем передавайте сам пакет.

нет
jcxz
Цитата(Огурцов @ Feb 7 2016, 22:33) *
мне надо 62.5 килопакета в секунду, а на эзернете реально получается где-то 25, при 100% загрузке
и ещё его нет в бюджетных камнях

SPI спасёт отца русской демократии?
Спокойно работает на десятках МГц на бюджетных CM3/4.
AHTOXA
Цитата(Огурцов @ Feb 7 2016, 21:33) *
тут вопрос в другом - будет ли генерироваться idle, если внутри пакета придёт новый адреса слейва ?
было бы правильнее иметь прерывание именно по смене адреса, что абсолютно однозначно указывает на конец пакета

Так включите и это прерывание, одно другому не мешает.
zltigo
QUOTE (Огурцов @ Feb 7 2016, 18:33) *
это очень медленный интерфейс с огромных оверхедом

Это потрясающая новость! Можно сказать открытие!!!
Вообще то Ethernet и какая нибудь взятая Вами без разбору кривая реализация IP, есть РАЗНЫЕ вещи.
Огурцов
Цитата(AHTOXA @ Feb 7 2016, 18:45) *
Так включите и это прерывание, одно другому не мешает.

так я не нашёл

в общем, попробую три варианта
если idle принимается каждым слейвом, независимо от текущего адреса, буду генерить его один раз в конце пакета
если idle относится только к текущему слейву, буду генерить его на каждый субпакет
если уж совсем ничего не поможет - придется дополнительно задействовать прерывание exti спаду сигнала data_valid, который я совсем упустил

Цитата(jcxz @ Feb 7 2016, 17:37) *
SPI

синхронизироваться сложно


Цитата(zltigo @ Feb 7 2016, 18:46) *
кривая

будете сравнивать вес uart c ethernet ?
mantech
Цитата(Огурцов @ Feb 7 2016, 19:33) *
это очень медленный интерфейс с огромных оверхедом
мне надо 62.5 килопакета в секунду, а на эзернете реально получается где-то 25, при 100% загрузке
и ещё его нет в бюджетных камнях


Опа! Что-то не то в датском королевстве biggrin.gif

Что означает 62килопакета, в граммах - непонятно, пакет-то какой длины будет?? В езернете есть ограничения только на макс. длину, 64кб и минимальную, то-ли 64 байта или 48 не помню уже laughing.gif

Причем вся обработка пакета, т.е. преамбула, CRC и т.д. делается самим контроллером, с дма и всякими плюшками...

И не путайте протокол(IP) и интерфейс. rolleyes.gif Кстати, IP можно и по уарту гнать, как и просто пакеты по эзернету

В бюджетных камнях нет, только зачем 10 мегабит в бюджетке??

ЗЫ. И да, есть еще CAN. Тоже встроенный обработчик пакетов, приличные скорости...
Огурцов
дюжина байт войдёт
был бы ещё uart хотя бы на 25 мегабит - вообще супер
почему нет - кнопочку нажал, лампочку включил
а десятка - на камеру, при том, что физика общая, не тянуть же по зданию десятки линий
can == 1 мегабит, это очень небыстро
zltigo
QUOTE (Огурцов @ Feb 7 2016, 20:42) *
будете сравнивать вес uart c ethernet ?

Не умеете работотать с uart используейте ГОТОВЫЙ пакетный интерфейс. Размеры чипов не отличаются, как и их вес sm.gif


QUOTE (mantech @ Feb 7 2016, 20:48) *
минимальную, то-ли 64 байта или 48 не помню уже laughing.gif

Зачастую и его можно обойти, причем совершено безболезненно при соединении точка-точка, где нет коллизий.
Tarbal
Я бы сделал циклический буфер, заполняемый DMA, с прерыванием по наполовину заполненному буферу и таймаут на случай недостаточно длинного пакета. В приемнике обрабатывать как непрерывный поток.
Таймаут от прерывания таймера считать. Ну это очевидно.

Ну разумеется второе (вернее основное) назначение таймаута -- синхронизация на начало пакета.

Недостаток по сравнению с прерыванием на каждый принятый байт -- необходимость иметь более длинный таймаут. Без DMA на 115200 одной миллисекунды достаточно.
evgen2
Цитата(Огурцов @ Feb 7 2016, 01:18) *
как наименьшими телодвижениями организовать приём пакетов ?


О, а у меня противоположный вопрос - как с наименьшими движениями организовать передачу по DMA из памяти в uart на lpc17xx.
Пример из code.bundle работает замечательно, но сцуко, только до 16 байт.
Пример из новейшего супер-пупер cmsis \lpc175x_6x_cmsis_driver_library\Examples\UART\DMA\uart_dma_test.c
вообще напрочь как-то не адаптируется под вариант "послать на uart3" - не происходит прерывания DMA_IRQ, хотя вроде бы всё такое же..
Может у кого есть работающий пример?
jcxz
Цитата(Огурцов @ Feb 8 2016, 00:42) *
синхронизироваться сложно

А вот вопрос - что это за бюджетный камень такой у STM позволяющий 10МБит/с по UART??? Озвучьте!
10 МБит/с - это ведь как минимум 160МГц тактовой на входе UART-периферии.
Или у Вас оверсэмплинг = 8? Но всё равно...

Цитата(evgen2 @ Feb 8 2016, 03:24) *
О, а у меня противоположный вопрос - как с наименьшими движениями организовать передачу по DMA из памяти в uart на lpc17xx.

А что именно вызывает затруднения? Поставить бит в SSP.DMACR и написать 5 строчек инициализации DMA-канала???
Подсказка: чтобы хоть что-то организовать, надо первым делом открыть даташит. Или этот шаг пропустили и сразу в примеры полезли?
Огурцов
Цитата(jcxz @ Feb 8 2016, 03:53) *
Или у Вас оверсэмплинг = 8?

конечно

mantech
Цитата(jcxz @ Feb 8 2016, 06:53) *
10 МБит/с - это ведь как минимум 160МГц тактовой на входе UART-периферии.


Разогнал наверно biggrin.gif

ЗЫ. Вообще посмотрел соседнюю тему, товарищ Огурцов вообще интересными вещами занимается, например, езернет без мак контроллера, по спи... Так что 10 мег по уарту уже не удивляет laughing.gif

Сам считаю, что для каждой задачи нужно свое решение, если нужен эзернет - так и надо брать мк с ним, а если мегабитные скорости - ИМХО уарт не для этого был разработан...
zltigo
QUOTE (mantech @ Feb 8 2016, 09:20) *
ЗЫ. Вообще посмотрел соседнюю тему, товарищ Огурцов вообще интересными вещами занимается, например, езернет без мак контроллера, по спи... Так что 10 мег по уарту уже не удивляет laughing.gif

Не занимается, а есть к русском языке хорошее слово - мается. Он еще на 100% умолчал, что ему все это "нужно" в количестве 999 точек на 9999 метров. В общем в обычном своем стиле sad.gif писать что попало.
evgen2
Цитата(jcxz @ Feb 8 2016, 06:53) *
А что именно вызывает затруднения? Поставить бит в SSP.DMACR и написать 5 строчек инициализации DMA-канала???
Подсказка: чтобы хоть что-то организовать, надо первым делом открыть даташит. Или этот шаг пропустили и сразу в примеры полезли?

Зачем мне для передачи из памяти в uart ставить бит в SSP.DMACR ? нелогично вроде.
Кстати, SSP.DMACR - read/write регистр, а UnFCR, куда нужно писать соответствующие биты для DMA - write only, что придает некоторую сексуальность в сравнении "тут работает, тут не работает".

И на 5 строчек тоже как-то не хватает, но пофиг, пусть будет больше, лишь бы работало
Код
/* зовем один раз */
  LPC_SC->PCONP |= (1 << 29);    /* Enable GPDMA clock */
  LPC_SC->DMAREQSEL = 0x0000;  /* Select primary function(UART0/1/2/3) in DMA channels,  secondary is timer 0/1/2/3. */
/*.....*/
/* str - строка для передачи в uart длиной len */
/* всё работает , если len <= 16, если больше - в порт уходит только 16 байт */
   DMA_Init( M2P, str, 0, len);
   LPC_GPDMACH0->DMACCConfig |= 0x08001|0x380;    /* Enable channel and IE bit */
/* [b]UPDATE[/b]: а так всё работает, как надо (chanel tranfer type был установлен в memory to memory)  */
   LPC_GPDMACH0->DMACCConfig |= 0x08001|0x380|(1<<11);    /* Enable channel and IE bit */
/*.....*/        

int DMA_Init( int DMAMode, char *src_addr, char *dest_addr, int dsize)
{
    if ( DMAMode == M2P ) {

      /* Ch0 set for M2P transfer from mempry to UART. */
      LPC_GPDMACH0->DMACCSrcAddr  = (uint32_t) src_addr;
      LPC_GPDMACH0->DMACCDestAddr = (uint32_t) LPC_UART3_BASE;

      /* The burst size is set to 1, source and dest transfer width is 32 bits(word), Terminal Count Int enable */
      LPC_GPDMACH0->DMACCControl = (dsize & 0x0FFF)|(0x00 << 12) |(0x00 << 15)
        |(0x00 << 18)|(0x00 << 21) | (1 << 26)| (0 << 27) | 0x80000000;
    }        
    LPC_GPDMA->DMACConfig = 0x01;    /* Enable DMA channels, little endian */
    while ( !(LPC_GPDMA->DMACConfig & 0x01) );    

   NVIC_EnableIRQ(DMA_IRQn);
   return (TRUE);
}
Огурцов
Цитата(mantech @ Feb 8 2016, 07:20) *
Разогнал

нет, затормозил

Цитата(mantech @ Feb 8 2016, 07:20) *
10 мег по уарту

не только 10, в не самом бюджетном камне от 40..50 до 100 должно
ещё тут недавно тема была, про нейросети, точнее про сотни бюджетных камней на одной плате, как им общаться ?

Цитата(mantech @ Feb 8 2016, 07:20) *
если нужен эзернет

нам такой футбол не нужен http://electronix.ru/forum/index.php?showt...t&p=1402440

Цитата(mantech @ Feb 8 2016, 07:20) *
ИМХО уарт не для этого был разработан...

а для чего ? а для чего был телефон придуман, для adsl, наверно ?
jcxz
Цитата(evgen2 @ Feb 8 2016, 14:21) *
Зачем мне для передачи из памяти в uart ставить бит в SSP.DMACR ? нелогично вроде.
Кстати, SSP.DMACR - read/write регистр, а UnFCR, куда нужно писать соответствующие биты для DMA - write only, что придает некоторую сексуальность в сравнении "тут работает, тут не работает".

Фу-ты - конечно UART.FCR. Просто думал параллельно об SSP.

Цитата(evgen2 @ Feb 8 2016, 14:21) *
...
NVIC_EnableIRQ(DMA_IRQn);

А где установка регистра channel.config? А, вижу.
А где установка UART.FCR? И зачем |= для LPC_GPDMACH0->DMACCConfig?

Вот моя инициализация DMA для UART.tx (перед этим ещё устанавливается UART.FCR, SYSCFG.DMAREQSEL, DMA.SYNC и DMA.CFG):
Код
static void SetTxDMA(void *data, uint n)
{
  DMA.IntTCClr = 1 << DMA_CH_bt;
  DMA.IntErrClr = 1 << DMA_CH_bt;
  HwRegsDMA::T_CH volatile *ch = &DMA.CH[DMA_CH_bt];
  ch->DST = (void *)&concatAB(UART, nUART_bt).THR;
  ch->SRC = data;
  ch->LLI = NULL;
  ch->CTL = n | 0 << 15 | B26 | B31;
  __DMB();
  ch->CFG = B0 | (DMA_REQ_bt_TX >> 4) << 6 | 1 << 11 | B14 | B15;
}
evgen2
Цитата(jcxz @ Feb 8 2016, 11:55) *
Вот моя инициализация DMA для UART.tx (перед этим ещё устанавливается UART.FCR, SYSCFG.DMAREQSEL, DMA.SYNC и DMA.CFG):
Код
  ch->CFG = B0 | (DMA_REQ_bt_TX >> 4) << 6 | 1 << 11 | B14 | B15;

Нашел.
Всё дело в волшебных пузырьках битиках. 1 << 11
Это transfer type. Если 0 - то memory to memory, если 1 - memory to peripheral. Если поставить 0, то всё работает до размера 16 байт (или, возможно, длины FIFO?, FIFO у меня 16 байт)
Огурцов
погонял idle - ерунда, работает не так, как мне надо, кроме того нельзя просто постоять покурить
lin не работает на 9 бит
jcxz
Цитата(evgen2 @ Feb 8 2016, 15:53) *
Нашел.
Всё дело в волшебных пузырьках битиках. 1 << 11
Это transfer type. Если 0 - то memory to memory, если 1 - memory to peripheral. Если поставить 0, то всё работает до размера 16 байт (или, возможно, длины FIFO?, FIFO у меня 16 байт)

1 - как я понимаю говорит DMA-контроллеру обращать внимание на сигнал UART.THRE от UART. Это директива - использовать флов-контроль от периферии.
Если стоит 0 - DMA-контроллер не обращая внимания на UART.THRE, зафигачивает весь пакет в FIFO. Так как для mem->mem флов-контроль не нужен. Естественно в этом случае всё после 16-го байта теряется.
Читать юзермануал надо внимательнее.
scifi
Цитата(Огурцов @ Feb 10 2016, 15:55) *
погонял idle - ерунда, работает не так, как мне надо, кроме того нельзя просто постоять покурить
lin не работает на 9 бит

Вместо Idle можно использовать Break.
Огурцов
break работает только с lin
или не только ?
scifi
Цитата(Огурцов @ Feb 10 2016, 18:55) *
break работает только с lin
или не только ?

Мануал говорит, что не только.
Огурцов
а не получилось
вероятно, остановлюсь на любимом frame error, ибо работает так как надо и реакция и так и так одинаковая - проверить поступивший пакет, перазапустить приём
только размер пакета в начало придется таки добавлять - пока происходит прерывание, дма ещё накидывает в буфер неопределённое количество мусора/данных, так что границу нужно знать заранее
хотя да, это происходит только при работе с пк, трафик с мк идёт чистый
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.