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

 
 
4 страниц V   1 2 3 > »   
Closed TopicStart new topic
> Помогите разобраться с PRINTF, Большой обьем выводимой информации - 5К
Димон Безпарольн...
сообщение Feb 16 2018, 03:26
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Не хочется создавать большой кольцевой буфер для PRINTF. Поступил по - другому. С задержкой.

Посчитав что PRINTF работает через int fputc(int ch, FILE *f), в ней и написал:

Код
int fputc(int ch, FILE *f)                  //Внутри функции реализована задержка заполнения
{                                            //буфера для уменьшения размера буфера.
static unsigned int StreamWaitCnt = 0;        //
    StreamWaitCnt++;                        //Счетчик числа передаваемых байт
    if (StreamWaitCnt > PC_TxBufSize-5)        //Если счеттчик достиг размера буфера
        {                                    //
            StreamWaitCnt = 0;                //Обнулить счетчик
            HAL_Delay(30);                    //Задержка пока буфер улетит в порт
        }                                    //
    return (PC_Putchar(ch));                 //
}                                            //


Т.е. когда буфер заполняется, происходит задержка для ожидания завершения передачи буфера в порт. Передача осуществляется через прерывание:


Код
int PC_Putchar(int ch)                         //Передача. Функция помещает Ch в кольцевой буфер.
{                                             //Указатель головы кольцевого буфера перемещается на
    int tmphead = (PC_TxHead + 1) & PC_TX_BUFFER_MASK; //одну позицию, символ помещается в кольцевой буфер.
    PC_TxBuf[tmphead] = (char)ch;               //Если передача первая после опустошения
    PC_TxHead = tmphead;                    //буфера(переданы все символы), взводится флаг L86_Complete,
        if (PC_Complete==0)                    //Передаваемый символ помещается в передающий регистр порта
        {                                     //(L86_UsartTx();) и инициируется первая передача
            PC_Complete = 1;                //в цепочке - разрешением прерывания.
            PC_UsartTx();                     //Флаг начала цепочки передач
            PC_En_Tranfer_Interrupt;        //Положить первый символ в DR
        }                                     //
    return (ch);                            //
}                                             //



Само прерывание:

Код
void USART2_IRQHandler(void)
{
    if (USART2->ISR & USART_ISR_TC)                 //Bit 6 TC: Transmission complete
    {                                             //
        PC_UsartTx();                             //
    }                                            //
    if (USART2->ISR & USART_ISR_RXNE)             //Bit 5 RXNE: Read data register not empty
    {                                             //
        PC_UsartRx();                            //Функция кладет байт из приёмного регистра в кольцевой буфер
    }                                             //
  HAL_UART_IRQHandler(&huart2);
}



Код
void PC_UsartTx(void)                         //
{                                             //
    if (PC_TxHead != PC_TxTail)                //Check if all data is transmitted
    {                                         //
        PC_TxTail = (PC_TxTail + 1) & PC_TX_BUFFER_MASK;//Перемещение указателя по кольцевому буферу
        USART2->TDR = (int)PC_TxBuf[PC_TxTail];    //Start transmition
    }                                         //
    else                                    //
    {                                        //
        PC_Complete=0;                        //Цепочка передачи окончена
        PC_Dis_Tranfer_Interrupt;            //Запретить прерывание на передачу Bit 6 TCIE:
    }                                        //
}                                             //


Самой задержки (30мс) по идее должно хватать. Т.е. при скорости 115200 за 1 секунду улетает 10килобайт. Примерно. Значит за милисекунду - 10 байт. Итого - 300байт при буфере в 256.

Такой подход по идее должен разрешать иметь любой малый (в разумных пределах) буфер для передачи. На практике же это не работает - часть выводимой информации теряется. И только когда я делаю #define PC_TxBufSize 8192, передача осуществляется без потерь.

Где же я не прав, может кто подскажет?

Сообщение отредактировал Димон Безпарольный - Feb 16 2018, 03:31
Go to the top of the page
 
+Quote Post
mcheb
сообщение Feb 16 2018, 04:24
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 30-05-06
Пользователь №: 17 602



Я бился с такой проблемой, не решил. Сделал так. Отказался от передачи ТХ в прерывании, то есть перешёл на поллинг. В терминальной программе поставил задержку после передачи новой строки на 1 миллисекунду. Увеличение буфера до 8кБ помогает, но не всегда. Причём это в Виндоуз и в Линуксе. А файл 1кБ отлично передавался и с буфером 256 байт.
Go to the top of the page
 
+Quote Post
adnega
сообщение Feb 16 2018, 05:39
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Димон Безпарольный @ Feb 16 2018, 06:26) *
часть выводимой информации теряется.

А вы уверены, что теряет не приемная сторона?
Go to the top of the page
 
+Quote Post
mcheb
сообщение Feb 16 2018, 05:51
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 30-05-06
Пользователь №: 17 602



Цитата(adnega @ Feb 16 2018, 09:39) *
А вы уверены, что теряет не приемная сторона?

Я делал USB-UART на STM32F103 и на CC2511. RX замкнут на TX. На CC2511 нормально работало до 1 МГц, на STM32F103 после 9600 были сбои на длинных файлах. Так и не разобрался.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Feb 16 2018, 06:10
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(mcheb @ Feb 16 2018, 07:24) *
Я бился с такой проблемой, не решил. Сделал так. Отказался от передачи ТХ в прерывании, то есть перешёл на поллинг. В терминальной программе поставил задержку после передачи новой строки на 1 миллисекунду. Увеличение буфера до 8кБ помогает, но не всегда. Причём это в Виндоуз и в Линуксе. А файл 1кБ отлично передавался и с буфером 256 байт.

Вы правы. В случае поллинга все работает исправно.

Код
USART2->TDR = ch;
if(UART_WaitOnFlagUntilTimeout(&huart2, UART_FLAG_TC, RESET, 100) != HAL_OK)
    {

    }




Но поллинг накладывает временные ограничения на выполнение. Я пишу код MBED TLS и в этом случае не проходит даже handshake. Либо в моем софте еще один глюк...

Видимо без буфера не обойтись.

Цитата(mcheb @ Feb 16 2018, 08:51) *
Я делал USB-UART на STM32F103 и на CC2511. RX замкнут на TX. На CC2511 нормально работало до 1 МГц, на STM32F103 после 9600 были сбои на длинных файлах. Так и не разобрался.

У меня были сбои на 460800 пока я не перешел на кварц. Хотя на 9600 смещение частоты вряд ли скажется...

Цитата(adnega @ Feb 16 2018, 08:39) *
А вы уверены, что теряет не приемная сторона?

Уверен что приемная сторона нипричем. Сделал поллинг - вывод сработал исправно.
Go to the top of the page
 
+Quote Post
adnega
сообщение Feb 16 2018, 06:16
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(mcheb @ Feb 16 2018, 08:51) *
на STM32F103 после 9600 были сбои на длинных файлах. Так и не разобрался.

Я при помощи STM32F103C8 гнал поток 2.25 Мбод (RX замкнут с TX). Ни один байт не потерялся за значительное время.
Go to the top of the page
 
+Quote Post
x893
сообщение Feb 16 2018, 06:55
Сообщение #7


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

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Цитата(adnega @ Feb 16 2018, 09:16) *
Я при помощи STM32F103C8 гнал поток 2.25 Мбод (RX замкнут с TX). Ни один байт не потерялся за значительное время.

Конечно не будет теряться, если код написан правильно.
Я на 926000 тоже нормально гонял на другое устройство.
Go to the top of the page
 
+Quote Post
adnega
сообщение Feb 16 2018, 07:05
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(x893 @ Feb 16 2018, 09:55) *
Конечно не будет теряться, если код написан правильно.

Я писал так
Код
void USART2_IRQHandler(void)
{
    if(USART2->ISR & (1 << USART_ISR_TXE))
    {
        if(con.tx_t != con.tx_b) USART2->TDR = bl_export.bl_sp_tx_pop(&con);
        else USART2->CR1 &= ~(1 << USART_CR1_TXEIE);
    }
    if(USART2->ISR & (1 << USART_ISR_ORE))
    {
        USART2->ICR = (1 << USART_ISR_ORE);
    }
    if(USART2->ISR & (1 << USART_ISR_RXNE))
    {
        con.rx_tm = 0;
        bl_export.bl_sp_rx_push(&con, USART2->RDR);
    }
}

push и pop помещают и извлекают байты из кольцевых буферов tx и rx.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 16 2018, 07:36
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Димон Безпарольный @ Feb 16 2018, 05:26) *
Самой задержки (30мс) по идее должно хватать.

Задержки - типичный ардуино-подход, дилетантский.
Для вывода в поток с помощью printf() никаких задержек вообще не нужно. И размер буфера может быть абсолютно любым, хоть 1 байт. Буфер только даёт возможность более эффективно использовать быстродействие CPU - в среднем уменьшает загрузку CPU.
Если у Вас что-то не работает из-за изменения размеров буфера или требует каких-то задержек - правьте консерваторию.
Go to the top of the page
 
+Quote Post
x893
сообщение Feb 16 2018, 08:18
Сообщение #10


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

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Я делал совсем по простому
2 буфера линейных
ПДП
таймер
всё пузЫрилось на ура.
Go to the top of the page
 
+Quote Post
Эдди
сообщение Feb 16 2018, 08:23
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Проверяйте в функции отправки сообщения статус возврата! Если ошибка — либо пропускайте (сообщение некритичное), либо ждите подтверждения отправки.
Соответственно, функция, заполняющая буфер просто будет возвращать OK если место есть и ошибку, если буфер полностью заполнен и надо подождать, пока "уедет".

Если используете линейный буфер (тогда удобней делать двойную буферизацию), отправка реализуется при помощи DMA, а буферы меняются местами по флагу, выставленному в прерывании по окончании DMA.
Если буфер кольцевой, придется в обработчике прерывания TXE выполнять основную работу.

Но в любом случае ни в коем случае не надо лепить паузы! Это же не абдурина!!! Если буфер заполняется слишком быстро, либо повышайте скорость передачи, либо увеличивайте буфер.
Go to the top of the page
 
+Quote Post
mcheb
сообщение Feb 16 2018, 09:27
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 30-05-06
Пользователь №: 17 602



Очень может быть, что сбои (потери) байтов из-за плохой трассировки печатной платы. Изменение буферов, скоростей, поллинга-прерываний изменяют наводки от фронтов Rx-Tx и уменьшение скорости тогда единственный выход.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Feb 16 2018, 09:44
Сообщение #13


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(jcxz @ Feb 16 2018, 10:36) *
Задержки - типичный ардуино-подход, дилетантский.
Для вывода в поток с помощью printf() никаких задержек вообще не нужно. И размер буфера может быть абсолютно любым, хоть 1 байт. Буфер только даёт возможность более эффективно использовать быстродействие CPU - в среднем уменьшает загрузку CPU.
Если у Вас что-то не работает из-за изменения размеров буфера или требует каких-то задержек - правьте консерваторию.

Интересная точка зрения. Ну допустим буфер 128 байт. Кольцевой. За пару милисекунд проц настрочил 5кб текста и выплюнул все это в кольцевой буфер. А с одним байтом будет еще прикольнее. Наверно только первый байт от 5кб и попадет в терминал. Мож и не первый...
Go to the top of the page
 
+Quote Post
Эдди
сообщение Feb 16 2018, 10:18
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Цитата(Димон Безпарольный @ Feb 16 2018, 12:44) *
За пару милисекунд проц настрочил 5кб текста и выплюнул все это в кольцевой буфер.

Сам он это не выплюнет, он сделает так, как ему разработчик велел. И если разработчик не проверяет коды возврата из процедур, это его личные проблемы!
Если хочется использовать printf (хотя эта штука ну слишком уж жирная!), то она, если что, тоже возвращает количество принятых символов. И вместо фиксированного времени ожидания можно лишь подождать, пока буфер не освободится и закинуть в него критическое сообщение. Некритическое же вообще можно опустить (но для этого придется дописать простой макрос, возвращающий количество свободных символов в буфере).
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Feb 16 2018, 10:50
Сообщение #15


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(Эдди @ Feb 16 2018, 13:18) *
Сам он это не выплюнет, он сделает так, как ему разработчик велел. И если разработчик не проверяет коды возврата из процедур, это его личные проблемы!
Если хочется использовать printf (хотя эта штука ну слишком уж жирная!), то она, если что, тоже возвращает количество принятых символов. И вместо фиксированного времени ожидания можно лишь подождать, пока буфер не освободится и закинуть в него критическое сообщение. Некритическое же вообще можно опустить (но для этого придется дописать простой макрос, возвращающий количество свободных символов в буфере).

printf использует библиотека MBEDTLS, нужен форматирванный вывод.

Суть во всем это одна -

Цитата
можно лишь подождать, пока буфер не освободится


Я так и делал, но другим способом - наблюдая за головой и хвостом.

В данном случае это ПОКА неприемлимо. Сервер выкидывает HandShake, следом сертификаты. Так вот. С выводом debug информации не получается успевать декодировать первое сообщение - его затирает втрое.

Сообщение отредактировал Димон Безпарольный - Feb 16 2018, 10:52
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th April 2024 - 20:49
Рейтинг@Mail.ru


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