@communistic_sistema
Биохимик, но в программировании немного шарю

Как исправить ошибку буфера с UART?

Был написан код на system verilog для ПЛИС. Схема является UART.
На С++ был написан компорт.
Метод записи:
DWORD ComIface::write(byte* data, int count) {
    DWORD NumOfWritten, status;
    OVERLAPPED overlap = { 0 };
    overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!overlap.hEvent) {
        printf("CreateEvent failed with error %d.\n", GetLastError());
        return 0;
    }
    if (!WriteFile(port_handle, data, count, &NumOfWritten, &overlap)) {
        status = GetLastError();
        if (status != ERROR_IO_PENDING) {
            printf("WriteFile failed with error %d.\n", status);
            CloseHandle(overlap.hEvent);
            return 0;
        }
        if (!GetOverlappedResult(port_handle, &overlap, &NumOfWritten, TRUE)) {
            NumOfWritten = 0;
        }
    }
    CloseHandle(overlap.hEvent);
    return NumOfWritten;
}

Метод чтения
DWORD ComIface::read_block(byte* buffer, int size) {
    DWORD NumberOfBytesRead = 0, status = 0;
    OVERLAPPED overlap = { 0 };
    overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!overlap.hEvent) {
        printf("CreateEvent failed with error %d.\n", GetLastError());
        return 0;
    }
    hpet rt;
    while (get_stats().cbInQue < size) {
        if (!SetCommMask(port_handle, EV_RXCHAR)) {
            printf("SetCommMask failed with error %d.\n", GetLastError());
            return NumberOfBytesRead;
        }
        WaitCommEvent(port_handle, &status, &overlap);
        WaitForSingleObject(overlap.hEvent, read_delay);
        if (rt.get_ms_dt_weak().count() > read_delay * size) {
            return NumberOfBytesRead;
        }
    }
    ReadFile(port_handle, buffer, size, &NumberOfBytesRead, &overlap);
    return NumberOfBytesRead;
}

Проблемы были 2:
1. ONESTOPBIT ломало передачу блока в 1024 байта на 533ем, где происходило запоздание на 1 байт, а затем вообще cc вместо нужных байт. Ее решение это костыль, а именно ONE5STOPBITS.
2. При передачи 1024 байт все передавалось успешно, но начиная с 33575 или 33525 (просто увеличили кол-во передаваемых байт) буфер ком порта вел себя не особо понятно, в нем шло запоздание на 25 позиций. Они зависели от заполнения данных на передачу, но они всегда отставали именно на 25 позиций. А вперед, перед ними, вклинивались данные как будто с конца.
Такого не было если передавалось 67кб. То есть 64, или еще что-то выдает ошибки, а именно такие объемы нет.
Я предполагаю, что это проблема на стороне ПК.

ПК-ПЛИС соединены usb через переходник для пинов. На коротком расстоянии, без помех, плохой контакт КРАЙНЕ маловероятен.

BaudRate был установлен в 115200, PARITY_NONE, DATABITS_8, SetComm был установлен с запасом.

Какие проблемы приводят к такому и как это чинить?
  • Вопрос задан
  • 221 просмотр
Пригласить эксперта
Ответы на вопрос 2
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
ONESTOPBIT ломало передачу блока

Передачу откуда куда?

DWORD ComIface::write(byte* data, int count)

Что конкретно эта функция должна делать? Если это просто запись count байтов, то зачем так сложно?

DWORD ComIface::read_block(byte* buffer, int size)

Что конкретно эта функция должна делать?


hpet rt;
    while (get_stats().cbInQue < size) {
        if (!SetCommMask(port_handle, EV_RXCHAR)) {
            printf("SetCommMask failed with error %d.\n", GetLastError());
            return NumberOfBytesRead;
        }
        WaitCommEvent(port_handle, &status, &overlap);
        WaitForSingleObject(overlap.hEvent, read_delay);
        if (rt.get_ms_dt_weak().count() > read_delay * size) {
            return NumberOfBytesRead;
        }
    }


Что здесь происходит?

Какие проблемы приводят к такому и как это чинить?

Чтобы что-то чинить нужно это сначала понять.
Ответ написан
@res2001
Developer, ex-admin
Зачем так сложно читаете в read_block?
Возможно из-за того что у вас возвращаемое ReadFile значение никак не обрабатывается и случаются эти пропуски.
Если у вас в буфере приема порта что-то лежит - это не значит, что ReadFile гарантированно завершиться синхронно.

Я бы сделал синхронный ReadFile в цикле с проверкой количества прочитанных байт.
Учитывая, что и запись и чтение в вашей реализации по сути синхронные, то нет смысла усложнять асинхронщиной.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы