Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Простой вопрос про Nios II UART
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
Reanimator++
Собственно, добрался до минимальной глючащей программы.

Код
#include "unistd.h"
#include "fcntl.h"
#include "stdio.h"
#include "system.h"
#include "sys/alt_irq.h"

int main (void)
{
    int  uart_descriptor;

    alt_u32 i, timer;
    alt_u8 command = 0x85;
    alt_u32 recieved;

    alt_irq_context  aaa;

    printf ("Vezuviy UART Test Program");

    uart_descriptor = open ("/dev/uart_board_0", O_RDWR|O_NONBLOCK|O_NOCTTY|O_SYNC);
    if (uart_descriptor)
    {
        printf ("Device_open success!\n");

        while (1)
        {
            timer = alt_nticks ();
            write (uart_descriptor, &command, 1);
            recieved = 0;


            while (alt_nticks() < (timer + 100) && (recieved != 95))
            {
                tmp = read (uart_descriptor, NULL, 1000);
                if (tmp > 0)
                    recieved += tmp;
            }

            printf ("%ld\n", recieved);

        }



    }
    else
        printf ("Device_open fail!\n");


}


Есть устройство, которое подключено к NIOS по UART, в ответ на команду запроса оно возвращает ответ - ровно 95 байтов (проверено, 100%).
А Nios почему-то иногда получает меньше. Теряется случайный байт в середине пакета, либо несколько байт подряд.

Если перестать постоянно пытаться забрать имеющиеся данные из буфера, а подождать некоторое время а потом прочитать, то данные всегда приходят целыми. Т.е. такой код работает:

Код
        while (1)
        {
            timer = alt_nticks ();
            write (uart_descriptor, &command, 1);
            recieved = 0;


            while (alt_nticks() < (timer + 100) )
                   ;


            recieved = read (uart_descriptor, NULL, 1000);
            

            printf ("%ld\n", recieved);

        }



Зы, система простая, содержит несколько UART, один системный таймер, PIO и epcs_controller.
В BSP выбраны полные не уменьшенные быстрые драйвера для UART.. (работающие через прерывания)

Корявый драйвер не запрещает прерывания при чтении?
Или я что-то делаю не так?
vadimuzzz
Цитата(Reanimator++ @ Apr 27 2011, 22:56) *
Корявый драйвер не запрещает прерывания при чтении?
Или я что-то делаю не так?

скорее второй вариант. вряд ли так часто дергать read безопасно. если уж есть какая-то необходимость таскать по 1 байту, то от hal лучше отказаться, имхо. второе решение выглядит элегантнее.
Reanimator++
Нет, это не решение а синтетический тест )
Я написал программу на 20 тыщ строк которая крутится в суперцикле и одним из ее действий является чтение данных из UART.
Получается если я хоть раз вызываю read до того как ответ получен, то есть вероятность потери байтов. Т.е. фактически он бесполезен и UART-ом пользоваться нельзя...

зы. нашел драйвер, просмотрел код, запрещения прерываний при чтении не обнаружил.. как он вообще работает? (там есть действия связанные с семафорами, вот они расставлены грамотно, но я так понимаю что это будет работать только если я микриум задействую..)
vadimuzzz
Цитата(Reanimator++ @ Apr 28 2011, 12:43) *
Получается если я хоть раз вызываю read до того как ответ получен, то есть вероятность потери байтов.

можно использовать блокирующее чтение. либо DMA
Reanimator++
Блокирующее не вариант, не дай бог байтик не дошел и все, девайс завис. Ладно бы был вариант чтения с таймаутом.. Да все-равно, UART-ов несколько, обслуживать все надо.
В общем я расстроен, так надеялся что не надо будет драйвер делать самому, думаю - как здорово, альтера уже написала все...

Попробую переписать на свой.

А DMA это интересно, там конфликт чтение/запись разруливается на уровне шины? И ограничений на количество DMA нету?
vadimuzzz
Цитата(Reanimator++ @ Apr 28 2011, 15:05) *
А DMA это интересно, там конфликт чтение/запись разруливается на уровне шины? И ограничений на количество DMA нету?

главное там - прерывание по приему всего пакета. ограничений на кол-во каналов нет.
Reanimator++
Упростил драйвер UART-а до четырех строчек, запретил прерывания во время чтения, не помогло.

Опытным путем выяснил что проблема связана с JTAG UART. Когда отключаешь Nios II JTAG UART Console, а потом снова включаешь то приходят данные в количестве размера буфера JTAG UART из printf ("%ld\n", recieved); с верным числом байт в пакете. А потом снова начинаются потери. Видимо там есть что-то надолго блокирующее прерывания, буду читать дальше код..
iosifk
Цитата(Reanimator++ @ Apr 28 2011, 14:47) *
Опытным путем выяснил что проблема связана с JTAG UART.


Так может просто в JTAG происходит сбой? Там все импульсы проверены? Может скорость обмена по этому порту понизить?
Reanimator++
Дык сбой там или нет, зачем же прерывания-то тормозить? Наполнил буфер и сиди жди пока интерфейс отпустит ) Как-то не по-русски сделано.
Попробую пересобрать систему без использования JTAG UART и распаяю еще один RS-232, перенаправив на него stdout..
Reanimator++
Попробовал с железным RS-232 - все работает нормально. В общем JTAG UART - пользоваться осторожно...
Reanimator++
Продолжение..
После исключения JTAG UART и возврата к большой программе потери байтов повторились.
При прогоне кода в самом начале топика я добавил счетчик - а сколько раз он успевает вызвать read. Оказалось что всего 64 раза. Т.е. выходит что большую часть времени процессор находился в прерывании. Суть - он тормоз, uart на 115200 для него уже почти предел ) программа исполняется из SDRAM, процессор средний - NiosII/e, частота 54 МГц. Не думал что это будет настолько медленно...
В общем замена процессора на NiosII/f помогла и байты теряться перестали (как я понимаю, процедура прерывания стала попадать в кэш и исполняться быстро).
Так что все-таки правильным был вариант "я что-то делаю не так", vadimuzz, как всегда точен sm.gif

А как бы вы оценивали сколько процентов времени процессор проводит в прерывании?
зы. теперь понимаю почему гугль так часто выдавал мне темы про Fifo-ed UART..
Stewart Little
Цитата(Reanimator++ @ Apr 28 2011, 20:00) *
... программа исполняется из SDRAM, процессор средний - NiosII/e, частота 54 МГц. Не думал что это будет настолько медленно...

NiosII/e - это минимальная конфигурация (Economy), это действительно тормоз, особенно с прерываниями (кстати, для саморазвития почитайте, как там организована обработка прерываний wacko.gif ).
Средняя конфигурация называется Standard, и, соответственно, /s.
А если используете Fast, то имеет смысл добавить VIC - тогда с прерываниями вообще хорошо станет.
Reanimator++
Пардон, ошибся, это был Standard - /s.
А про VIC где прочитать что это, в Nios II Processor Reference Handbook и в Nios II Software Developer's Handbook что-то не разглядел..
Stewart Little
Цитата(Reanimator++ @ Apr 28 2011, 20:14) *
Пардон, ошибся, это был Standard - /s.
А про VIC где прочитать что это, в Nios II Processor Reference Handbook и в Nios II Software Developer's Handbook что-то не разглядел..

Vectored Interrupt Controller
Примеры
Reanimator++
Спасибо за поддержку!
Serhiy_UA
Цитата(Reanimator++ @ Apr 28 2011, 17:26) *
Попробовал с железным RS-232 - все работает нормально. В общем JTAG UART - пользоваться осторожно...

Была аналогичная ситуация, пришел к такому же выводу. Т.е. исключил JTAG UART и далеее работал только со своим UART. Где-то там есть накладки, разбираться не стал, не было времени...
В моем проекте NiosII/f, частота 100 МГц, правда скорость UART пониже, а основные потоки через Ethernet-100.
Fynjisx
Цитата(Reanimator++ @ Apr 27 2011, 18:56) *
Код
while (alt_nticks() < (timer + 100) && (recieved != 95))
}

Извините что вклиниваюсь, но хотел бы узнать Вы точно уверены что единицы измерения timer - ns?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.