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

 
 
 
Reply to this topicStart new topic
> Прикрутить программный FIFO для UART LPC17XX, Как лаконично организовать?
kt368
сообщение Oct 11 2013, 21:11
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 13-10-10
Из: Киев
Пользователь №: 60 135



Здравствуйте! Вывожу в UART с помощью printf(), предварительно подправив Retarget.c, в функцию fputc() внес следующее:
Код
int fputc(int c, FILE *f) {
    UART_SendByte(LPC_UART0, c);
    return (c);}
Когда я предаю по UART длинные строки при помощи printf, то реально передаётся только первая часть строки, это по-идее происходит из-за наличия в модуле UART 16-и байтового аппаратного FIFO. Хочу подправить функцию fputc(), введя в неё программный FIFO, дабы иметь возможность передавать одной командой printf() большие строки. Можно, конечно, ввести в fputc() проверку освобождения аппаратного FIFO, но тогда процессор будет тратить такты впустую, чего не хочется. Подскажите, как бы его так сделать, чтобы между printf() и модулем UART'a был программный FIFO, и в то же время этот FIFO со как-то освобождался, то-ли по прерыванию от таймера, то-ли ... Как правильнее это реализовать?
Go to the top of the page
 
+Quote Post
Lagman
сообщение Oct 11 2013, 21:21
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Что то Вы тут все в кучу свалили, каким образом printf знает что у вас 16 байтовый аппаратный фифо, вроде как через fputc по одному символу выдается? Какой длины не влезает строка, а какой влезает? Даже 8 битники нормально printf обрабатывают.
Смотрите на UART_SendByte(), скорей всего там ошибка. И кажется надо править putc() а не fputc() (зависит не только от компилятора, про который вы ни слова не сказали, а может вы вызываете fprinf()). Но проверка нужна будет обязательно т.к. вы не узнаете что буфер освободился, ставьте RTOS пусть она в задачах сама переключает, либо через прерывания. А можно через sprintf выводить в буфер и уже его по прерыванию выдавать на UART.
Go to the top of the page
 
+Quote Post
kt368
сообщение Oct 11 2013, 21:30
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 13-10-10
Из: Киев
Пользователь №: 60 135



Не до конца объяснил. printf действительно про фифо ничего не знает, вот и гонит в UART_SendByte() по байтику всю строку, а UART_SendByte() вот такая:
Код
void UART_SendByte(LPC_UART_TypeDef* UARTx, uint8_t Data)
{
    UARTx->THR = Data & UART_THR_MASKBIT;
}

То есть эта функция просто вносит в регистр передаваемых данных ещё один байт, не проверяя есть ли свободная ячейка в аппаратном фифо.
....Хм, пересмотрел код, у меня, кажется, аппаратный фифо был выключен. Попробую его включить, завтра получу доступ к железу - протестирую как теперь будет работать printf() с большими строками и отпишусь.
Go to the top of the page
 
+Quote Post
Lagman
сообщение Oct 11 2013, 21:36
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(kt368 @ Oct 12 2013, 01:30) *
Не до конца объяснил. printf действительно про фифо ничего не знает, вот и гонит в UART_SendByte() по байтику всю строку, а UART_SendByte() вот такая:
Код
void UART_SendByte(LPC_UART_TypeDef* UARTx, uint8_t Data)
{
    UARTx->THR = Data & UART_THR_MASKBIT;
}

То есть эта функция просто вносит в регистр передаваемых данных ещё один байт, не проверяя есть ли свободная ячейка в аппаратном фифо.
....Хм, пересмотрел код, у меня, кажется, аппаратный фифо был выключен. Попробую его включить, завтра получу доступ к железу - протестирую как теперь будет работать printf() с большими строками и отпишусь.

Так в этом случае не то что длинные строки, любая строка должна выводиться абракадаброй т.к. THR постоянно перезаписывается новыми данными, а что в сдивговый регистр попадет никто не узнает пока не увидит результат вывода на экран. (общий рецепт может не иметь ничего общего с LPC17XX)
Go to the top of the page
 
+Quote Post
_pv
сообщение Oct 11 2013, 22:42
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Код
#ifndef __FIFO_H_
#define __FIFO_H_

#include "type.h"

template <u8 size, typename T = u8> class Fifo{
  T buf[size];
  u8 _count;
  u8 _first;
  u8 _last;
public:
  Fifo(){ _count = _last = _first = 0; }
  void clear(){ _count = _last = _first = 0; }
  u8 count(){ return _count; }
  u8 free(){ return size - _count; }

  void push(T item){
    if(_count == size) return;
    _count++;
    buf[_last++] = item;
    if(_last >= size) _last = 0;
  }

  T pop(){
    if(_count == 0) return 0;
    _count--;
    T item = buf[_first++];
    if(_first == size) _first = 0;
    return item;
  }

  u8 write(T * data, u8 num){
    if (num > (size - _count)) num = size - _count;
    u8 n = num;
    while (num--) push(*data++);
    return n;
  }

  u8 read(T * data, u8 num){
    if (num > _count) num = _count;
    u8 n = num;
    while (num--) *data++ = pop();
    return n;
  }

  T at(s16 index){
    s16 i = index + (index < 0) ? _last : _first;
    while (i < 0) i += size;
    while (i >= size) i -= size;
    return buf[i];
  }
};

#endif /* __FIFO_H_ */



Fifo <64> txFifo;

соответственно в
UART_SendByte(char data){
txFifo.push(data);
__UART_TX_INTERRUPT_ENABLE();
}

а в прерывании передатчика
if (txFifo.count()) UARTx->THR = txFifo.pop();
else __UART_TX_INTERRUPT_DISABLE();
Go to the top of the page
 
+Quote Post
mdmitry
сообщение Oct 12 2013, 19:11
Сообщение #6


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Цитата(_pv @ Oct 12 2013, 02:42) *
[code]
template <u8 size, typename T = u8> class Fifo{
...
}

Уважаемый _pv, с какой целью жестко ограничена глубина FIFO 255 элементами? Пакеты могут быть и длиннее, чем 255 байт (протокол WAKE, например).

Уважаемый kt368, пример кольцевого буфера можно найти в usrlib.* из scmRTOS. И смотрите внимательно на умолчания шаблона.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
_pv
сообщение Oct 12 2013, 20:41
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(mdmitry @ Oct 13 2013, 01:11) *
Уважаемый _pv, с какой целью жестко ограничена глубина FIFO 255 элементами? Пакеты могут быть и длиннее, чем 255 байт (протокол WAKE, например).

скопировано оттуда где пакетов больше 255 быть не может, а делать еще и задание типа для хранения индексов было лень.
кому сильно надо может поменять на template <int size, typename idxT = u8, typename T = char>
жаль нельзя сделать template <idxT size, typename idxT = u8, typename T = char>. было бы совсем красиво.
Go to the top of the page
 
+Quote Post
kt368
сообщение Oct 12 2013, 21:56
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 454
Регистрация: 13-10-10
Из: Киев
Пользователь №: 60 135



Все, разобрался. Включил аппаратный FIFO, также добавил свой программный буфер, по примеру _pv. Ещё зачем-то хочется сделать динамическое выделение памяти под это FIFO, но сейчас не до этого.
Всем спасибо!
Go to the top of the page
 
+Quote Post
SSerge
сообщение Oct 13 2013, 11:21
Сообщение #9


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

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



В функциях push и pop есть инкремент и декремент счётчика _count.
Это не безопасно.
Например, если во время исполнения в функции push() оператора _count++ произойдёт прерывание по готовности передатчика. И случится это как раз после чтения из памяти старого значения счётчика, но до записи в память нового, увеличенного.
В обработчике прерывания будет вызов pop(), а в ней есть декремент счётчика.




--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 09:58
Рейтинг@Mail.ru


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