Решено с помощью mlockall () - символы Ascii с определенным значением не читаются через последовательный порт - PullRequest
0 голосов
/ 30 июня 2019

Я установил удаленный микроконтроллер, подключенный к моему ПК с Linux, который выдает непрерывную строку символов.Я настроил порт, используя screen (выполнив screen / dev / ttyS0 57600).

Я проверил данные командой od и получил то, что ожидал.Данные следуют как 8-битные шестнадцатеричные значения ...

    0006040 03 01 09 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006100 00 00 00 00 00 00 00 00 00 00 00 06 0b a5 00 03
    0006120 01 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006160 00 00 00 00 00 00 00 00 00 00 06 0b a5 00 03 01
    0006200 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006240 00 00 00 00 00 00 00 00 00 06 0b a5 00 02 01 09
    0006260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006320 00 00 00 00 00 00 00 00 0f 0c a5 00 02 01 09 00
    0006340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006400 00 00 00 00 00 00 00 0f 0c a5 00 02 01 09 00 00
    0006420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006460 00 00 00 00 00 00 0f 0c a5 00 01 01 09 00 00 00
    0006500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006540 00 00 00 00 00 05 0c a5 00 01 01 09 00 00 00 00
    0006560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006620 00 00 00 00 05 0c a5 00 01 01 09 00 00 00 00 00
    0006640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0006700 00 00 00 05 0c a5 01 08 01 09 00 00 00 00 00 00

Затем я создаю простую программу на C, чтобы попытаться прочитать те же данные, но все, что я получаю из моей программы на C, это следующий вывод:

  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 a5:1 
  a5:1

Исходя из этого вывода, кажется, что функция чтения действительно возвращает чтение одного байта, но каждый раз возвращаемое значение равно a5, то есть байту флага, который микро посылает на ПК, чтобы указать новыйпоток данных фиксированного размера.

Таким образом, моя программа правильно перезаписывает существующее значение "A" в буфере чтения, но ей необходимо постоянно обновлять правильные данные (будь то 00 или 01), но не только a5

Что я делаю не так?

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

  #include <stdio.h>
  #include <stdlib.h>
  #include <fcntl.h>
  #include <time.h>
  #include <unistd.h>

  #define TIMEOUT 5

  int main(){
    char inb[3];  //our byte buffer
    int nread=0;  //number bytes read from port
    int n;        //counter
    int iosz=128; //Lets get 128 bytes
    int fd=open("/dev/ttyS0",O_NOCTTY | O_RDONLY | O_SYNC); //Open port
    for(n=0;n<iosz;n++){
      int s=time(NULL); //Start timer for 5 seconds
      while (time(NULL)-s < TIMEOUT && nread < 1){
        inb[0]='A'; //Fill buffer with bad data
        inb[1]='B';
        inb[2]='C';
        nread=read(fd,inb,1); //Read ONE byte
        if (nread < 0 || time(NULL)-s >= TIMEOUT){
            close(fd); //Exit if read error or timeout
            return -1;
        }
      }
      printf("%x:%d ",inb[0] & 0xFF,nread); //Print byte as we receive it
    }
    close(fd); //program ends so close and exit
    return 0;
  }

Ответы [ 2 ]

0 голосов
/ 02 июля 2019

Я наконец понял это!

После нескольких дней мучительных размышлений я нашел окончательный ответ.

Да, я реализовал ввод / вывод на последовательном порту с большим количеством байтов за раз вместо одного байта за раз, но это не помогло.

То, что в буквальном смысле решали вещи, было двумя предметами:

  1. Мне нужно, чтобы эта программа имела высокий приоритет, поскольку последовательная синхронизация является строгой (1 символ каждые 173 мкс при 56 КБ). Для этого я добавил это в начале основной функции:

    const struct sched_param schedp = {99}; sched_setscheduler (0, SCHED_FIFO, и schedp);

и я также добавил это во включенные:

#include <sched.h>

Это позволило программе иметь приоритет, но, что удивительно, первое место занял блокировка памяти вокруг секций, которые должны были быть критическими, и эти критические секции читали и записывали из / в порт .

    mlockall(MCL_CURRENT);  
    //use read() or write() in here with file descriptor as serial port
    munlockall();

и я также добавил это во включенные:

#include <sys/mman.h>

Я рассмотрел использование MCL_FUTURE в качестве параметра, но это означает запрос блокировки дополнительных ресурсов в памяти, но после того, как я обнаружил, что в этом нет необходимости, я буду использовать MCL_CURRENT.

И мне все равно, если остальные процессы в моей системе блокируются на 5 секунд, но, по крайней мере, теперь ввод / вывод данных работает на 100% лучше на последовательном порту.

0 голосов
/ 01 июля 2019

Символы Ascii при определенном значении не читаются через серийный номер

Это фиктивный анализ недостатков вашей программы.
Как оказывается по некоторому совпадению, наибольшее полученное значение кажетсяравным 0xA5, и небольшой выборочный дамп, кажется, всегда предшествует этому байту либо с 0x0B, либо с 0x0C.
Если бы в дампе отображалось больше данных, в конечном итоге 0x0D (возврат каретки) предшествовал бы байту 0xA5?

Так, если активен канонический режим (который обычно является режимом по умолчанию) и ему предшествует 0x0D (то есть символ разделителя строк), то 0xA5 будет первым символом строки.
Так какваша программа запрашивает только один символ за раз, каноническое read () вернет только первый символ строки.

Что я делаю не так?

В вашей программе есть две существенные ошибки.

Во-первых, ваша программа пренебрегает настройкой последовательного терминала, поэтому вы не знаете, использует ли ваша программа канонический или неканонический режим.,

Во-вторых, ваша программа печатает одни и те же результаты только одного read () .
Ваш анализ того, что считываются только определенные значения, является неточным, потому что только результатна самом деле печатается read () .
printf () выходит за рамки цикла , в то время как (который выполняет чтение), поэтомуВаша программа не печатает то, что получил каждый read () , а печатает только то, что first успешно read () .
После этого первогоуспешное read () , переменная nread имеет значение 1, а сравнение nread < 1 для цикла , в то время как всегда будет иметь значение FALSE.
Следовательно, не более read () s будет происходить после первого успешного, но результаты первого будут неоднократно печататься из-за цикла для .

Так что если неКанонический режим активен, когда вы запустили свою программу, и «0xA5» как раз и является первымt read () , то это то, что будет напечатано (много раз) вашей программой.


Поскольку полученные данные являются двоичными, а не текстовыми ASCII, вам необходимо настроить последовательный терминал для неканонического (он же необработанного) режима.
Тогда вы сможете продолжать неэффективно читать один байт привремя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...