Перейти 1.12 на Linux 4.19.93 armv6l
. Аппаратное обеспечение представляет собой raspberypi zero w (BCM2835), на котором запущен образ yocto linux.
У меня есть датчик приближения SRF04, управляемый gpio, управляемый драйвером srf04 linux.
Он отлично работает с sysfs и оболочкой busybox.
# cat /sys/bus/iio/devices/iio:device0/in_distance_raw
1646
Раньше я использовал Go с устройствами IIO, поддерживающими триггеры и буферизованный вывод с высокой частотой дискретизации на этой аппаратной платформе. Однако для этого приложения драйвер srf04 не не реализовывать эти функции IIO. Драт. Мне не очень хочется добавлять в драйвер поддержку буфера/триггера (в настоящее время), так как мне не нужна «высокая» частота дискретизации. Для моей цели должно хватить нескольких пингов в секунду. Думаю, я рассчитаю среднее значение и стандартное значение. разв. для скользящего окна точек данных и «выделить» сигнал из шума.
Итак, я был бы совершенно счастлив прочитать байты из опубликованного файла sysfs с помощью Go.
Что подводит меня к сути этого поста. Когда я открываю файл для чтения и пытаюсь выполнить Read() любое количество байтов, я всегда получаю общую ошибку -EIO
.
func (s *Srf04) Read() (int, error) {
samp := make([]byte, 16)
f, err := os.OpenFile(s.readPath, OS.O_RDONLY, os.ModeDevice)
if err != nil {
return 0, err
}
defer f.Close()
n, err := f.Read(samp)
if err != nil {
// This block is always executed.
// The error is never a timeout, and always 'input/output error' (-EIO aka -5)
log.Fatal(err)
}
...
}
Мне это кажется странным поведением. Поэтому я решил возиться с использованием io.ReadFull
. Это дало ненадежные результаты.
func (s *Srf04) Read() (int, error) {
samp := make([]byte, 16)
f, err := os.OpenFile(s.readPath, OS.O_RDONLY, os.ModeDevice)
if err != nil {
return 0, err
}
defer f.Close()
for {
n, err := io.ReadFull(readFile, samp)
log.Println("ReadFull ", n, " bytes.")
if err == io.EOF {
break
}
if err != nil {
log.Println(err)
}
}
...
}
Я закончил тем, что добавил его в цикл, так как обнаружил изменения в поведении от «однократного» чтения до нескольких вызовов чтения, следующих друг за другом. У меня он выходит, если он получает EOF, и неоднократно пытается прочитать иначе.
Результаты откровенно сумасшедшие, ненадежные, по-видимому, возвращающие случайные результаты. Иногда я получаю -5, иногда я читаю от 2 до 5 байтов с устройства. Иногда я получаю байты без файла eof перед EOF. Байты, по-видимому, представляют собой символьные данные для чисел (каждая руна - это руна между [0-9]) - чего я и ожидал.
В стороне: я ожидаю, что это связано с опросом файлов и реализацией ввода-вывода с блокировкой, но я не могу сказать точно.
В качестве временного обходного пути я решил попробовать использовать os.exec, и теперь я получаю ожидаемые результаты.
func (s *Srf04)Read() (int, error) {
out, err := exec.Command("cat", s.readPath).Output()
if err != nil {
return 0, err
}
return strconv.Atoi(string(out))
}
Но Йик. os.exec
. Фу.
os.ModeDevice | os.ModeCharDevice
. - person bvarner   schedule 27.04.2020