Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сколько байт можно гарантированно запихивать в UART LPC (UART0 LPC2292) по прерыванию THRE?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Alex03
Будем считать что процедура записи в U0THR мгновеная, а скорость передачи сверхнизкая, т.е. байты улетать не успевают smile.gif

16? Или если ещё и LST_TEMP=1 (но это вряд ли) то и 17?

PS Гады. Ну реализовали они 550 UART но могли бы расширить флагами для статуса FIFO, а то и прерыванием по окончанию передачи из сдвигового регистра.
PPS FIFO понятно включен.
zltigo
Цитата(Alex03 @ Oct 11 2006, 08:38) *
16? Или если ещё и LST_TEMP=1 (но это вряд ли) то и 17?

Естествено 16, поскольку мгновенным ничего не бывает, и скорость передачи не бесконечно низкая, то и пока будете 16 запихивать первый уже в сдвиговый регистр в большинстве реальных приложений попадет, значит 17. 17-тым не пользуюсь, а 16 загружаю.
Alex03
Цитата(zltigo @ Oct 11 2006, 12:17) *
Естествено 16, поскольку мгновенным ничего не бывает, и скорость передачи не бесконечно низкая, то и пока будете 16 запихивать первый уже в сдвиговый регистр в большинстве реальных приложений попадет, значит 17. 17-тым не пользуюсь, а 16 загружаю.


17 - пожалуй перебор.
Такой ситуации практически не бывает на относительно невысоких скоростях передачи.
Время передачи одного/двух бит (стоповый бит) или 7..11 бит (целого слова) часто довольно большое.
Например для B9600 м.б. ~100..1100мкс.
Да и на макс. скорости для 8N1 у проца есть 10*16 тактов, что вполне соизмеримо с временем записи 16 байтиков в U0THR с учётом хорошей оптимизации, задержек на ISR и тормознутой переферии.

А смутил меня попавшийся в двух примерах такой (псевдо)код в ISR:
Код
while (U0LSR & ULSR_THRE)
{
    U0THR = uart0_tx_buffer[uart0_tx_extract_idx++];
}


Т.е. они там по одному (в лучшем случае два) байту за прерывание отправляли, при активированном FIFO.
Сергей Борщ
Цитата(Alex03 @ Oct 11 2006, 10:29) *
А смутил меня попавшийся в двух примерах такой (псевдо)код в ISR:
Код
while (U0LSR & ULSR_THRE)
{
    U0THR = uart0_tx_buffer[uart0_tx_extract_idx++];
}


Т.е. они там по одному (в лучшем случае два) байту за прерывание отправляли, при активированном FIFO.
Ну почему же один? U0LSR читается на каждом проходе цикла, пока FIFO не заполнится ULSR_THRE равен 1 и цикл будет выполняться. Т.е. 16-17 легко.
Alex03
Цитата(Сергей Борщ @ Oct 11 2006, 16:24) *
Ну почему же один? U0LSR читается на каждом проходе цикла, пока FIFO не заполнится ULSR_THRE равен 1 и цикл будет выполняться. Т.е. 16-17 легко.


Вот видимо те авторы так-же думали.

THRE - Transmitter Holding Register Empty
0: U0THR contains valid data.
1: U0THR is empty.
THRE is set immediately upon detection of an empty UART0 THR and is cleared on a U0THR write.
Сергей Борщ
Цитата(Alex03 @ Oct 11 2006, 13:38) *
Цитата(Сергей Борщ @ Oct 11 2006, 16:24) *

Ну почему же один? U0LSR читается на каждом проходе цикла, пока FIFO не заполнится ULSR_THRE равен 1 и цикл будет выполняться. Т.е. 16-17 легко.


Вот видимо те авторы так-же думали.

THRE - Transmitter Holding Register Empty
0: U0THR contains valid data.
1: U0THR is empty.
THRE is set immediately upon detection of an empty UART0 THR and is cleared on a U0THR write.
Так ведь то что в него записано тут же падает в FIFO и пока FIFO не полон THR пуст.
The U0THR is the top byte of the UART0 Tx FIFO. The top byte is the newest character in the Tx FIFO and can be written via
the bus interface. The LSB represents the first bit to transmit.
Alex03
Цитата(Сергей Борщ @ Oct 11 2006, 20:43) *
Так ведь то что в него записано тут же падает в FIFO и пока FIFO не полон THR пуст.
The U0THR is the top byte of the UART0 Tx FIFO. The top byte is the newest character in the Tx FIFO and can be written via the bus interface. The LSB represents the first bit to transmit.


Вы ж сами сказали
Цитата
The U0THR is the top byte of the UART0 Tx FIFO.

Т.е. U0THR это голова FIFO, а не отдельный регистр. И если в FIFO чтото есть то THR не пуст.

ИМХО у Филипса тут дока кривоватая. Все эти THRE (как прерывание и как бит в LSR) THR (как U0THR) и т.д. Вроде всё просто, но понимание приходит со временем.

В общем я уже на практике убедился в своих словах.
zltigo
Код
__irq __arm void uart_isr( void )
{
register int ii;
char ch;
    while( !((ch = (U0IIR&IIR_MASK)) & IIR_IP) )        // Check Pending Bit
    {    // What caused the interrupt?
        switch( ch )
        {
        case IIR_THRE:    // The THR+FIFO is empty. If there is another
                    //    characters in the TX buffer, load its now to FIFO->THR.
            for( ii=0; ( tbuf.tail != tbuf.head )&&( ii < TR_FIFO_SIZE ); ii++ )
                U0THR = tbuf.buf[(tbuf.head++)&(TBUF_SIZE_MSK)];
            break;

        case IIR_RX_TIMEOUT:
           case IIR_RX:
                  ..............
Сергей Борщ
Цитата(Alex03 @ Oct 12 2006, 06:18) *
Цитата(Сергей Борщ @ Oct 11 2006, 20:43) *

Так ведь то что в него записано тут же падает в FIFO и пока FIFO не полон THR пуст.
The U0THR is the top byte of the UART0 Tx FIFO. The top byte is the newest character in the Tx FIFO and can be written via the bus interface. The LSB represents the first bit to transmit.


Вы ж сами сказали
Цитата
The U0THR is the top byte of the UART0 Tx FIFO.

Т.е. U0THR это голова FIFO, а не отдельный регистр. И если в FIFO чтото есть то THR не пуст.
Именно, голова а не хвост. И с точностью до наоборот - пока в FIFO есть место THR пуст.

Цитата(Alex03 @ Oct 12 2006, 06:18) *
В общем я уже на практике убедился в своих словах.
т.е. скорость небольшая (за время записи байта в FIFO он не успевает передаться), вы забили в пустой FIFO 16 байт, вышли из прерывания, получили прерывание THE и снова "не глядя" запихнули в FIFO 16 байт, а на второй стороне шнурка UART вывалилось 32 байта?
"Не верю!" (с)Станиславский.
Alex03
Цитата(Сергей Борщ @ Oct 12 2006, 13:09) *
Именно, голова а не хвост.


По поводу головы я видимо погорячился. Байт который пишут в U0THR конечно же попадает в хвост FIFO.

Цитата
т.е. скорость небольшая (за время записи байта в FIFO он не успевает передаться), вы забили в пустой FIFO 16 байт, вышли из прерывания, получили прерывание THE и снова "не глядя" запихнули в FIFO 16 байт, а на второй стороне шнурка UART вывалилось 32 байта?
"Не верю!" (с)Станиславский.


Верить или нет - это проблемы Станиславского! smile.gif
Поглядите на код zltigo
Попробуйте без всяких прерываний выполнить такой код:

Код
    int n = 0;
    while(U0LSR & ULSR_THRE)
    {
        U0THR = n++;
    }
    printf("n=%d", n);


Думаю результат будет 2. smile.gif
Ну а в прерывании 1.


2 zltigo
Код
    for( ii=0; ( tbuf.tail != tbuf.head )&&( ii < TR_FIFO_SIZE ); ii++ )
        U0THR = tbuf.buf[(tbuf.head++)&(TBUF_SIZE_MSK)];

А tbuf.tail также растёт до бесконечности ( ну или там 2^(8*sizeof(tbuf.tail)) ) ?
Типа задумка такая - чтобы голова и хвост отражали реальное кол-во (по модулю 2^(8*sizeof(tbuf.tail))) прошедших через FIFO данных?

PS. А я что то всегда их циклю! smile.gif
zltigo
Цитата(Alex03 @ Oct 12 2006, 11:49) *
А tbuf.tail также растёт до бесконечности ( ну или там 2^(8*sizeof(tbuf.tail)) ) ?

Сравнение и занесение всегда производится по маскированным значениям, а сами указатели
растут "до бесконечности".
Цитата
Типа задумка такая - чтобы голова и хвост отражали реальное кол-во (по модулю 2^(8*sizeof(tbuf.tail))) прошедших через FIFO данных?

И что еще, что много более полезно - отражали факт переполнения буфера и работали быстрее, нежели в случае:
Цитата
PS. А я что то всегда их циклю! smile.gif

Недостаток всего один - размер степень двойки.
Alex03
Цитата(zltigo @ Oct 12 2006, 18:01) *
Сравнение и занесение всегда производится по маскированным значениям, а сами указатели
растут "до бесконечности".

Наверное вытаскивание и занесение?

Цитата(zltigo @ Oct 12 2006, 18:01) *
И что еще, что много более полезно - отражали факт переполнения буфера и работали быстрее


В каком смысле "факт переполнения буфера"?
Код засовывания примерно тако?
Код
    if((tbuf.tail - tbuf.head) <= (TBUF_SIZE_MSK))
        tbuf.buf[(tbuf.tail++)&(TBUF_SIZE_MSK)] = X;
    else
        ...


Ну и не вижу великой разницы по быстродействию (при размере буфера = 2^x), хотя возможно есть. Будем иметь ввиду! smile.gif
zltigo
Цитата(Alex03 @ Oct 12 2006, 15:41) *
В каком смысле "факт переполнения буфера"?

В самом прямом.
Цитата
Код засовывания примерно тако?
Код
    if((tbuf.tail - tbuf.head) <= (TBUF_SIZE_MSK))
        tbuf.buf[(tbuf.tail++)&(TBUF_SIZE_MSK)] = X;
    else
        ...

Разумеется нет :-)
Код
      tbuf.buf[(bp.tail++)&(TBUF_SIZE_MSK)] = X;

И все!
Прочувствовали разницу и про переполнение стало яснее?
Alex03
Цитата(zltigo @ Oct 12 2006, 18:55) *
Цитата

Код засовывания примерно тако?
Код
    if((tbuf.tail - tbuf.head) <= (TBUF_SIZE_MSK))
        tbuf.buf[(tbuf.tail++)&(TBUF_SIZE_MSK)] = X;
    else
        ...

Разумеется нет :-)
Код
      tbuf.buf[(bp.tail++)&(TBUF_SIZE_MSK)] = X;

И все!
Прочувствовали разницу и про переполнение стало яснее?


Не почуствовал.
Не вижу никакого контроля факта переполнения буфера.

Давайте на примере.
Допустим буфер 16 байт, TBUF_SIZE_MSK=0x0F

Запихиваем больше 16-ти байт, например 17 байт такие 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
Легко, контроля то нет. 17-ый лёг на место первого.

Читающий процесс (как в прерываннии вверху треда) также легко их достаёт, но достаёт он такую последовательнось:
16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16

И чё тут клёвого?
zltigo
Цитата(Alex03 @ Oct 13 2006, 10:37) *
Не почуствовал.

Странно, Вы написали 'кучу' строчек в стиле
"А я что то всегда их циклю.." а тут одна :-)
Цитата
Не вижу никакого контроля факта переполнения буфера.

В расхождение старших (маскируемых) битов полного 'указателя' отражает
и факт переполнения и количество потерянных буферов/байтов. Причем это может быть проконтролировано в любой момент времени а не только в момент занесения, как в случае принудительного зацикливания.
Цитата
И чё тут клёвого?

Если скорость работы и контроль за фактом переполнения без дополнительных наворотов еще более снижающих скорость не важны, то "ничего клевого".
Alex03
Цитата(zltigo @ Oct 13 2006, 13:58) *
В расхождение старших (маскируемых) битов полного 'указателя' отражает
и факт переполнения и количество потерянных буферов/байтов.


Для контроля переполнения обязательно использовать и младшие биты, т.е. разность индексов головы и хвоста!

Иначе контроль не переполнения, а разбега в +/-размер буфера.
Если равны - хорошо
Если отличаются на единицу (в смысле старшие биты без младших) - то возможно переполнение
Если отличаются более чем на единицу - то точно переполнение

Цитата(zltigo @ Oct 13 2006, 13:58) *
Причем это может быть проконтролировано в любой момент времени а не только в момент занесения, как в случае принудительного зацикливания.


Если у Вас процессы занесения и вытаскивания както синхронизированны, то между ними в любой момент контролировать может и получится.
Если эти процессы полностью асинхронные, то в моменты контроля всё может быть хорошо, но между ними переполнение и соответственно искажение данных на выходе.
Ну и по всей видимости так (бесконтрольно) можно поступать там где выгребание из FIFO гарантированно быстрей чем засовывание туда.


Цитата(zltigo @ Oct 13 2006, 13:58) *
Странно, Вы написали 'кучу' строчек в стиле
"А я что то всегда их циклю.." а тут одна :-)


Под циклю я понимал то, что у меня старшие биты индексов всегда нулевые.
И Ваш вариант их использования мне понравился, но только в плане количественной оценки прошедших через FIFO данных. Потому я и спросил, вдруг ещё чего я не увидел.

PS Впрочем это всё уже оффтопик.
zltigo
Цитата(Alex03 @ Oct 13 2006, 11:54) *
Если у Вас процессы занесения и вытаскивания както синхронизированны, то между ними в любой момент контролировать может и получится.

Получится, читаем еще раз внимательно что контролировать - "факт переполнения буфера".
Без всяких "может".
Цитата
Ну и по всей видимости так (бесконтрольно) можно поступать там где выгребание из FIFO гарантированно быстрей чем засовывание туда.

Или, что гораздо боее часто - система с отказами и пиковая/аварийная нагрузка гарантировано забьет FIFO. Или в случае, если источник торможению по своей природе не поддается. Достаточно 'если'?
Кроме того, даный механизм не отвергает и прикручивание контроля наличия места в буфере перед
занесением, причем сие тоже делается проще и быстрее одним действием, нежели вычисление размера по двум 'коротким' указателям и размеру кольцевого буфера.

Цитата
И Ваш вариант их использования мне понравился, но только в плане количественной оценки прошедших через FIFO данных. Потому я и спросил, вдруг ещё чего я не увидел.

Таки не увидели.
Цитата
PS Впрочем это всё уже оффтопик.

Да, Sapienti Sap
Сергей Борщ
Цитата(Alex03 @ Oct 12 2006, 06:18) *
Вы ж сами сказали
Цитата
The U0THR is the top byte of the UART0 Tx FIFO.

Т.е. U0THR это голова FIFO, а не отдельный регистр. И если в FIFO чтото есть то THR не пуст.

ИМХО у Филипса тут дока кривоватая. Все эти THRE (как прерывание и как бит в LSR) THR (как U0THR) и т.д. Вроде всё просто, но понимание приходит со временем.

В общем я уже на практике убедился в своих словах.
Не поверив провел эксперимент. Действительно этот флаг сбрасывания при засовывании первого же байта. Обратился к прародителю, т.е. к TL16C550. Там расписано более подробно, и вот что нашлось:
Цитата
In the FIFO mode, this bit is set when the transmit FIFO is empty; it is cleared when at least 1 byte is written to the transmit FIFO.
Теперь все сходится, но осталось некоторое недоумение - внимательно перечитав доку на 550 я так и не нашел индикатора "в FIFO есть место". Получается если у меня есть один байт на передачу я его могу положить только в пустое FIFO, в противном случае никаких гарантий что я порушу предыдущие байты в FIFO. Выходит не только у филипса дока кривоватая, но и реализация у прародителя крива :-(
zltigo
Цитата(Сергей Борщ @ Oct 13 2006, 15:20) *
Выходит не только у филипса дока кривоватая, но и реализация у прародителя крива :-(

Реализация не 'крива', она просто сбалансировано-минималистична и ввиду этого является
индустриальным стандартом работающим многие годы и несущим на себе в том числе и совместимость в линейке 50->450->550x.
Да было-бы иногда не плохо узнать о факте наличия места в FIFO, а потом и о размере этого места а
потом и FIFO побольше, а потом....
В принципе столь небольшое FIFO в большинстве случаев просто не годится на роль заменителя буфера передачи :-(, посему внешний программный организовывать надо, ну а при внешнем - не слишком накладно, (а во многих случаях и быстрее, нежели лезть по 8bit к шине к медленной железке ) организовать подпитывание FIFO фиксированными проциями по прерыванию THRE.
Если-бы FIFO у нее было, например, 512 байт, то я первый-бы назвал ее кривой и вопрошал-бы -
ну где хоть "FIFO полупустое!"
А так в общем совершенно нормальная железка со сбалансированными возможностями.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.