176 Отредактировано Voldemar0 (02-05-2024 20:14)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Запустил FTP на плате. Работает.
Количество задач растёт, но их размер/сложность стремительно уменьшается. Поэтому составил ToDo-list.
Выглядит конспектом - поэтому под катом, но это реальный список, по которому сейчас работаю, поэтому пусть будет. Знак "+" в начале строки означает, что задача решена. Знак "-" не означает ничего :)

Spoiler

0) Подключение и отключение внешних накопителей (SD, USB). Сейчас делаю вручную, но давно уже есть кнопка на плате и светодиод и они должны быть программно связаны.


почему клавиатура в инсталяторе не работает ? (не нужна, но всё таки...)


MAIN: command invalid 2 ('')


uninitialized urandom read


уменьшить число инодов на cfg и storage
на storage изменить владельца на 6502


3) Инсталятор. Сейчас ПО работает с внешней SD-карты, инсталятор должен уметь закидывать ПО внутрь SoM.
Вроде бы я его когда-то начинал делать, но так и не попробовал - работает он или нет.
Проверил: я его не доделал :)


4) На плате должен быть SSH-сервер. Вообще-то сейчас там стоит какой-то лайтовый SSH, он пускает без проблем, но он, вроде бы, не умеет строить туннели. Туннель нужен для того, чтобы техподдержка платы могла зайти на устройство даже в случае его работы за домашним NAT. Т.е. устройство само строит туннель до сервера техподдержки, а ТП заходит на сервер и затем, через туннель, ныряет на плату. И там уже можно апдейтить софт, поглядеть журналы ошибок, потестировать запуск отдельных прог вручную и даже использовать встроенный отладчик. Эта задача видится сейчас как наиболее неопределённая по времени, но, в целом, ясно, что нужно брать OpenSSH и пытаться его скомпилировать под наше железо и встроить в прошивку.
    кстати, в этом ssh как раз есть поддержка туннелей. да и openssh тоже уже скомпилирован. Осталось только настроить.



web-интерфейс: главная странциа
    + управление кнопками
    + накопители
    - синхро номера и шаблона


web-интерфейс:
    установка времени / отключение/включ ntp
    установка IP / DHCP
    удаление снятых образов
    mount/umount storages
    перезапуск операционки
    остановка операционки


спектрограмма: заголовок для web


скорость 140 - хотя бы пусть без скорости, но позиционер головки нужен
    - нужно на мелкий экран хотя бы номер трека выдавать
    + нужно отвязать фразы от 840 ("нет сигнала от датчика"...)


зависон при остановке и libtherad_db
    + ! рекурсивный вызов ui_client ! понятно почему, не ясно как избежать
Error 'UI client: lock semaphore' in ui-clientl.c: ui_client:164: Inappropriate ioctl for device
Error 'UI client: lock semaphore' in ui-clientl.c: ui_client:164: Inappropriate ioctl for device


kill -9 из web


зомби шелла


1) Всё отладить и потестить. Там сложного ничего, но само количество точек тестирования приличное (поработать с разными дисководами, проверить создание, удаление образов, с платы и с web-...) - именно не каждую отдельную часть, а в комплексе. Это тест не только на технические ошибки, но и usability.


+2) Нужно воткнуть для начала ftp-сервер. Это самый быстрый способ забирать готовые образы с платы. Либо нужно выдёргивать флешку и читать её на компе. Собранный ftp у меня уже есть, так что только слить в прошивку и прошерстить конфиги, чтобы работал анонимный доступ.

177

Re: Мост # 3 - специализированный компьютер для чтения дискет

Каждый выпуск на youtube получается длинный.  И выходят выпуски с большими интервалами.
Всё время хочется сократить и период и размер, но не получается.

Начинаю пилить фичу A. Сейчас закончу, сделаю короткий ролик по ней. Но в процессе выясняется, что для A неплохо было бы доделать фичу B. Но B тянет за собой ещё и C, D и E.

Всё это вырастает параллельно, в итоге ролик оказывается загружен от A до E.
И даже в сюжете их сложно разъединить, чтобы набранный материал оформить как два отдельных ролика.

--

Закончил главную страницу web-сайта, сделал страницу управления временем (часами) платы.

Не стал делать поддержку ntp (синхронизация часов по сервисам Интернет). В ПО платы есть ntp, но ntp получает универсальное скоординированное время (UTC), чтобы из UTC получить локальное время нужны файлы тайм-зон (описатели часовых поясов), нужно управление ими (т.е. селектор на web-интерфейсе) и т.д. Решил пока на это не заморачиваться.

Инсталлятор тоже работает уже. Инсталлятор здесь - это возможность залить на новую плату всё ПО устройства без программаторов и паяльников, за пару минут.

178 Отредактировано Voldemar0 (24-05-2024 10:18)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Сделал управление накопителями, можно подключать-отключать.
Из визуально-видного: пока нельзя просмотреть список снятых образов (на web "Файлы на Мосту").

А так, для этапа 0, всё выглядит окончательно. Можно смотреть тут:
http://............../
Будет доступно до 11 мая примерно.

Заметки:
1) Скорость на 140ке считается неправильно: висит константа около 195 мс/оборот: там сама архитектура измерения неправильная, позднее буду переписывать, но там будет много работы.

2) Можно менять IP-шник, но после смены верните обратно :) Иначе после перезагрузки устройство исчезнет из вида.

3) Операционку можно перезагружать, но только если IP-ник правильный. Иначе после перезагрузки устройство исчезнет из вида.

4) Устройсво нельзя выключать. Сам обратно не включится.

Остальное можно. Даже отключать-подключать накопители (отключение тут - операция обратимая без механических действий).

USB-флешка воткнута, но она тормозная и, возможно, с ней съём будет идти медленнее.
Но можете поэкспериментировать :)

Часики идут по томскому времени, можете перевести на своё, если хотите.

Текущий ToDo:

Spoiler

почему клавиатура в инсталяторе не работает ? (не нужна, но всё таки...)


4) На плате должен быть SSH-сервер. Вообще-то сейчас там стоит какой-то лайтовый SSH, он пускает без проблем, но он, вроде бы, не умеет строить туннели. Туннель нужен для того, чтобы техподдержка платы могла зайти на устройство даже в случае его работы за домашним NAT. Т.е. устройство само строит туннель до сервера техподдержки, а ТП заходит на сервер и затем, через туннель, ныряет на плату. И там уже можно апдейтить софт, поглядеть журналы ошибок, потестировать запуск отдельных прог вручную и даже использовать встроенный отладчик. Эта задача видится сейчас как наиболее неопределённая по времени, но, в целом, ясно, что нужно брать OpenSSH и пытаться его скомпилировать под наше железо и встроить в прошивку.
    кстати, в этом ssh как раз есть поддержка туннелей. да и openssh тоже уже скомпилирован. Осталось только настроить.


web-интерфейс:
    +установка времени
    +установка IP / DHCP
    удаление/список снятых образов
    +mount/umount storages
    +перезапуск операционки / остановка операционки


зависон при остановке и libtherad_db
    + ! рекурсивный вызов ui_client ! понятно почему, не ясно как избежать
Error 'UI client: lock semaphore' in ui-clientl.c: ui_client:164: Inappropriate ioctl for device
Error 'UI client: lock semaphore' in ui-clientl.c: ui_client:164: Inappropriate ioctl for device


kill -9 из web


порезать раздать всем внутренним файлам права и удалить _хвосты


? глюки у дисплейчика ?


ftp проверить особо


1) Всё отладить и потестить. Там сложного ничего, но само количество точек тестирования приличное (поработать с разными дисководами, проверить создание, удаление образов, с платы и с web-...) - именно не каждую отдельную часть, а в комплексе. Это тест не только на технические ошибки, но и usability.


----


+2) Нужно воткнуть для начала ftp-сервер. Это самый быстрый способ забирать готовые образы с платы. Либо нужно выдёргивать флешку и читать её на компе. Собранный ftp у меня уже есть, так что только слить в прошивку и прошерстить конфиги, чтобы работал анонимный доступ.
+зомби шелла

+3) Инсталятор. Сейчас ПО работает с внешней SD-карты, инсталятор должен уметь закидывать ПО внутрь SoM.
+Вроде бы я его когда-то начинал делать, но так и не попробовал - работает он или нет.
+Проверил: я его не доделал :)

+MAIN: command invalid 2 ('')
+уменьшить число инодов на cfg и storage
+на storage изменить владельца на 6502

+uninitialized urandom read

+скорость 140 - хотя бы пусть без скорости, но позиционер головки нужен
    + нужно на мелкий экран хотя бы номер трека выдавать
    + нужно отвязать фразы от 840 ("нет сигнала от датчика"...)

+web-интерфейс: главная странциа
    + управление кнопками
    + накопители
    + синхро номера и шаблона

+спектрограмма: заголовок для web

+0) Подключение и отключение внешних накопителей (SD, USB). Сейчас делаю вручную, но давно уже есть кнопка на плате и светодиод и они должны быть программно связаны.
    +переписать cgi-bin/storage , чтобы он понимал маски, а не точные имена устройств
    +не забыть про кнопку и светодиод

179

Re: Мост # 3 - специализированный компьютер для чтения дискет

Снятие образа 840К:

Работа программы завершена
Не удалось определить главный формат диска :((
Bridge3: get floppy image
Package version 0.97 (Trollholmsund)
DRIVE CONTROL: 0.008 ms for move the head to the zero track
DRIVE CONTROL: wait for 991556 mks for drive up
Open /dev/spidev1.0 device
SPI mode 0x0, 32 bits per word, 20000000 Hz max
Control keys: 's' - skip track / phase, 'q' - skip phase / quit.
DRIVE CONTROL: 199.46 ms per turn
DRIVE CONTROL: this drive has 87 cylinders
Check '/storages/internal/Bridge3/' access... Success
Config variable only140 not found !
FIN

Печалька :(
Снятие образа 140К ведет себя так же.
Но спектрограммы показываются.

Управление позиционером:

0 трек, 72 оборотов, время мгновенное: 199.55 мс, время среднее: 202.2558 мс

Уровень на линии Density - низкий (пин 2), примерная скорость - 360 об/мин

Кажется, значение "примерная скорость" не зависит от снимаемых показаний. Но если потыкать кнопки, то 360 меняется на 300. Я не понял, как это должно работать :(

Там же:

The head is on the track   0,   30 turn(s), instant time 199.48 ms, average time 199.4710 ms
The head is on the track   0,   31 turn(s), instant time 398.94 ms, average time 205.9055 ms
The head is on the track   0,   32 turn(s), instant time 199.48 ms, average time 205.7045 ms
The head is on the track   0,   33 turn(s), instant time 199.47 ms, average time 205.5156 ms
The head is on the track   0,   34 turn(s), instant time 199.47 ms, average time 205.3379 ms
The head is on the track   0,   35 turn(s), instant time 199.48 ms, average time 205.1704 ms
The head is on the track   0,   36 turn(s), instant time 398.94 ms, average time 210.5529 ms
The head is on the track   0,   37 turn(s), instant time 199.47 ms, average time 210.2535 ms
The head is on the track   0,   38 turn(s), instant time 199.48 ms, average time 209.9700 ms

Кажется, по-прежнему есть пропуски сигнала индекса.

После перезагрузки попытка снять образ показывает вот это.

Ошибка подключения к статусу 840кб
Ошибка подключения к журналу 840кб

Спустя какое-то время работа восстанавливается. Видимо, до этого момента операционка просто не готова, но понять это нельзя (интерфейс-то работает!).

180 Отредактировано avivanov76 (11-05-2024 00:27)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Пара мелких замечаний по английскому:

0.042 ms for move the head to the zero track

Тут нужен предлог to: 0.042 ms to move

It is successfull final.

Тут пропущен артикль, плюс в слове successful только одна буква l. Но главное - фраза какая-то странная. Не понятно, а что тут по-русски должно было быть? Final - это последняя серия в сериале, последняя игра в турнире. А тут финал чего?
Если имелось в виду "Обработка завершена успешно", то можно было написать "Processing completed successfully".

181 Отредактировано Voldemar0 (11-05-2024 18:58)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Английский поправлю, спасибо!
Для меня использование for вместо by или to - не редкость. Я не совсем понимаю разницу между for (для ?) и to (у которого куча значений направления, включая и "для")...

It is successfull final.
Я имел ввиду: "Это успешное завершение."

В программе есть ещё два варианта:
It's final. But I couldn't detect a main format :((
It is successfull final. The main format detected and read without errors.
It is good final. The main format detected, but %d error(s) encountered while reading.

--

По прогам:

> Config variable only140 not found !

Это мне пару раз встречалось - ошибка странная, я пока не понял, в каких случаях она возникает.
В файле конфига нет одной переменной (или почему-то её не находит процедура поиска).
Надо чинить.

Workaround: щёлкнуть галочку "Использовать такой же шаблон для образов 840кб дисков:"
Само значение галочки не важно, но при её изменении этот параметр пересоздаётся.


> Снятие образа 140К ведет себя так же.
Прога одна и та же (снятие 840 и 140), переменная тоже одна. Т.е. это та же ошибка.

> "примерная скорость"

Это такая величина, которая измеряется при запуске привода 840 (для 140ки она - константа) и при смене уровня Density. Измеряется по сигналам индекса, но используется не для программы "скорость", а для сохранения в eim3-файл, чтобы потом декодеры могли понимать, какую поправку на скорость чтения делать. Важно, что эта величина может быть только либо 300 либо 360.
Примерно так: if RealSpeed > 330 then speed = 360 else speed = 300.

А дальше уже играет эта проблема:

> The head is on the track   0,   36 turn(s), instant time <b>398.94</b> ms, average time 210.5529 ms

И вот откуда эта штука возникает - я пока не понял. Выглядит так, как будто пропущен один index.
Вроде бы, это бывает не с любыми дисководами. Это надо будет проверять и искать причину.
Сейчас подключен привод 3.25'', но бОльшую часть отладки я вел на разных 5.25''. Вроде бы там не было этой проблемы.

> Ошибка подключения к статусу 840кб

Это не совсем ошибка, тут причина вот в чём:
журналы и статусы - это просто файлы на RAM FS.
Т.е. после перезагрузки ОС они теряются. Пока не запустишь какую нибудь программу, журналов нет.
После запуска любой из прог журнал появляется.
Каждый новый запуск прог журнал переписываются.


{
...можно создавать пустые журналы при запуске ОС...
Или с какой нибудь фразой, вроде "Информации пока нет"....
}

182

Re: Мост # 3 - специализированный компьютер для чтения дискет

Voldemar0 пишет:

to (у которого куча значений направления, включая и "для")

To еще используется для обозначения результата действия или процесса. У for такого значения нет.

Voldemar0 пишет:

Я имел ввиду: "Это успешное завершение."

Я вот думаю - это все какие-то расплывчатые формулировки: "успешное", "хорошее". Может, указать конкретный результат, типа "образ создан/не создан"?

Voldemar0 пишет:

It's final. But I couldn't detect a main format :((

Немного выбивается из общего стиля. В остальных фразах местоимений нет, а тут вдруг "Я".
Предлагаю так:

The disk image has not been created. The main format could not be detected.

И остальные фразы (passive voice тут обязателен, потому что не "формат определил", а "формат был определен"):

The disk image has been created. The main format was detected and read without errors.
The disk image has been created. The main format was detected, but %d error(s) were encountered while reading.

183 Отредактировано Voldemar0 (22-05-2024 17:55)

Re: Мост # 3 - специализированный компьютер для чтения дискет

О паре заметок в ToDo:

"? глюки у дисплейчика ?"

Мелкий дисплейчик на плате начал подглючивать: картинка иногда ломалась. Сперва лениво кивал на глюки самого дисплейчика, но сейчас на тестах две платы и когда глюки стали стабильными, причём на обеих платах, пришлось занести это в ToDo.

Сперва поискал вопрос об аппаратном сбросе, нашел его на плате дисплейчика, но он не выведен на гребёнку. Просто на плате есть RC-цепочка сброса и всё. А программного сброса в даташите не нашлось (ssd1306).
Но раньше же глюков не было ?

Поиски начал со здорового электролита, напаянного прямо на ноги дисплейчика. Не помогло.
Потом осцилографом порылся по шине i2c - там вполне прямоугольники, да и частота шины не высокая - 92 КГц примерно.
Потом был логический анализатор шины. Тут бага и нашлась. Но какая!

Контроллер дисплейчика умеет принимать растр либо команды по шине.
Чтобы отличать одно от другого имеется префиксный байт. Четыре варианта: команда в один байт, растр в один байт, команды до условия I2C-STOP, растр до этого же условия.

В драйвере (самописном) есть три процедуры: отправить растр (несколько байт), отправить команду (1 байт), отправить команду (массив). Команды бывают как из одного байта так и из нескольких.

Многие команды имеют размер 1 байт. Я их все отправлял процедурой отправки однобайтной команды.
Но когда был реализован основной функционал, я добавил команду управления яркостью дисплейчика. Она содержит два байта. И по привычке я их отправлял как две однобайтовых команды (copy-paste ж). И - что интересно - контроллер дисплея это вполне переваривал, несмотря на то, что в таком случае два байта (опкод + уровень яркости) приходили в отдельных I2C-транзакциях.

Яркость можно менять резко (просто задать любую нужную) или плавно крутить цикл от минимальной к максимальной или назад. Программно крутить, конечно. Я так и сделал. А поскольку это занимает около секунды, вынес эту операцию в отдельный тред - чтобы не задерживать исполнение других команд.
Пока всё было хорошо.

Но, когда дело шло к завершению разработки, я внёс запуск шелла в автозагрузку. И получилось следующее: рисуется заставка, экранчик плавно зажигается до максимума и затем плавно снижает яркость до минимума (но картинку ещё видно). Ещё до того, как игры с яркостью завершились, уже запускается шелл и начинает рисовать меню.
И вот тут команды управления курсором (от шелла) начинают смешиваться с командами управления яркостью (из скриптов ЛОГО): ЯРКОСТЬ.ОПКОД ... КУРСОР.КООРДИНАТА  ... ЯРКОСТЬ.ЗНАЧЕНИЕ.

Естесно, контроллер дисплея сходил с ума - координата становилась яркостью, яркость - недокументированным опкодом.

Решение же простейшее: отправлять команду яркости как одну двухбайтовую команду. Тогда она не может быть разорвана на шине.

184

Re: Мост # 3 - специализированный компьютер для чтения дискет

+ ! рекурсивный вызов ui_client ! понятно почему, не ясно как избежать

Тоже любопытный программный случай.

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

Но если прога зависла, мы идём в Диспетчер Программ и там нажимаем "завершить". В этом случае сперва программа также получает мягкое предупраждение, но затем ОС может закрыть её и принудительно.

В *NIX этот механизм я знаю немного лучше. Там есть понятие "Сигнал" - это некое асинхронное сообщение, которое одна программа или ядро ОС может передать другой программе. Но отличие "сигнала" от прочих механизмов в том, что ещё до запуска программы операционка (или LibC ?) уже предоставляет программе обработчики сигналов. Причем некоторые сигналы программа не может игнорировать совсем, а на другие может повесить свой обработчик. Больше половины обработчиков по умолчанию завершают работу программы.

Это немного напоминает агатовский УПР-СБР: по умолчанию его проигнорировать сложно, но можно попробовать сменить заранее вектор, тогда шанс есть.

Есть довольно любопытные сигналы, например SIGSTOP - полностью приостанавливает программу. Совершенно не спрашивая её согласия :) Потом можно вновь разрешить работать, послав сигнал SIGCONT. Мне в винде этого, порой, не хватает (Какой-то процесс выжрал все рессуры, но закрывать его не хочется, а нужно вот сейчас сделать другую работу. Что делать?).
А ещё SIGKILL - классный сигнал безусловного мгновенного закрытия программы. Программа не может его игнорировать.

Так вот в Мосту3 есть два способа завершить программу:

1) Нажать на плате большую кнопку старт-стопа или в web-интерфейсе нажать 'Q'. Это мягкое завершение - программа получает сообщение о том, что пользователь просит её завершится и завершает работу, когда   ей будет удобно и как ей будет удобно.

2) Нажать в web-интерфейсе кнопку запуска проги. Если прога уже запущена, ей будет отправлен сигнал завершения SIGTERM. Это сигнал мягкий - прога может его игнорировать. Но, по умолчанию, обработчик этого сигнала завершает программу. Этот вариант нужен, например, на случай зависания программы.

Поскольку прога может обработать этот сигнал, она не закрывается сразу. Прерывается текущая исполняемая процедура (сигналы - механизм асинхронный!), после чего, кроме прочего, вызывается группа процедур atexit. В эти процедуры складываются всевозможные действия, которые программист считает нужным выполнить независимо от причин, по которым программа завершает работу. В случае моста3 там собраны всевозможные сообщения (на web-интерфейс, на дисплейчик платы, на кнопки с подсветкой) о завершении программы.

И вот тут возникала коллизия:
если сигнал прерывает процедуру обмена с ui-server остаётся заблокирован семафор обращения к ui-серверу. Он должен разблокироваться при завершении процедуры, но её прервали и код завершения не выполнен. А atexit нужно обратится к ui-server'у, чтобы сообщить о завершении проги. И он лезет в ту же процедуру, попадает на закрытый семафор и .. всё зависает. Открыть семафор некому.
В процессе поиска истоков проблемы я поменял тип семафора, чтобы в такой ситации он не блокировал всё, а сообщал об ошибке. Но саму проблему это не решает: сообщение о завершении работы пользователю не отправлено.

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

Пришлось засесть за статьи по менеджменту сигналов. Важно не просто запретить прерывание обращения к ui-server, но и не запретить его во всех остальных случаях. Прога же может попасть в какой-то бесконечный цикл в декодерах, где-то ещё, она не будет проверять при этом мягкие просьбы из п1. И важно, чтобы хотя бы по п2 её можно было завершить.

Spoiler

Для тех, кто запутался в семафорах и процедурах :)
Пришла в голову простая аналогия:
Есть ж/д депо. В него может заехать только один паровоз. У всех паровозов есть уникальные номера. На въезде в депо стоит чувак в форме и если депо свободно, он открывает семафор. Если депо занято - закрывает семафор. Но чувак в форме сообразительный и если вдруг депо занято паровозом N 5, а на въезде стоит ещё один паровоз N 5, чувак бежит к телефону и сообщает об ошибке в системе.
Либо просто держит семафор закрытым. Это зависит от должностной инструкции.

Почему он может увидеть тот же самый паровоз, который хочет заехать, но ещё не выезжал ? Потому что у депо есть второй выезд и в особых исключительных случаях паровоз может выехать через него. Исключительный случай - тот самый асинхронный SIGNAL.

185

Re: Мост # 3 - специализированный компьютер для чтения дискет

Voldemar0 пишет:

И вот тут возникала коллизия:
если сигнал прерывает процедуру обмена с ui-server остаётся заблокирован семафор обращения к ui-серверу.

Хм. А код на чистом C написан? Я просто не представляю, как обработку управления ресурсами делать без try finally.
Когда есть блок finally, то он в любом случае выполняется и в нем можно разблокировать все ранее заблокированное.
Но для этого нужен C++.

Вроде есть какие-то костыли для эмуляции try catch https://stackoverflow.com/questions/105 … ments-in-c, но сам я этого не пробовал.

186 Отредактировано Voldemar0 (23-05-2024 06:28)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Чистый C.
Я не знаю внутренности LibC, но, судя по поведению прог, сигнал прерывает выполнение любого кода в любом месте и, даже если я напишу какую-то обёртку, она не будет выполнена дефолтным обработчиком.

Возможно, в C++ ставится свой обработчик сигнала в RTL, который может позволить выполнится finally, а уже после этого завершает программу. Т.е. сперва он прерывает текущий код, потом, используя какой-то стек текущих finally, передаёт управление на них и потом уже завершает прогу.

> Я просто не представляю, как обработку управления ресурсами делать без try finally.

f2() {
  action1();
  if action2() < 0 then return; // сбой на каком-то этапе
  action3();
  // успешно всё выполнили
}

f1() {
  allocate(что нибудь);
 f2();
  free(что нибудь)
}

Речь об этом ?

187

Re: Мост # 3 - специализированный компьютер для чтения дискет

Voldemar0 пишет:

Речь об этом ?

Да, об этом. Тут проблема в том, что сбои в f2 могут быть устранимые, типа деления на ноль, нехватки памяти, отсутствия файла и т.д. А могут быть неустранимые, например, переполнение стека, обращение к недопустимому адресу памяти или получение внешнего сигнала.
И если устранимых сбоев можно избежать, обложив весь код проверками, то со вторыми ничего поделать нельзя. Во всяком случае в C.
Кроме того, еще же есть библиотечные вызовы. Свою функцию можно как-то защитить проверками, а когда код чужой, то не факт, что его разработчик сделал все по фен-шую и вызов не уронит всю программу.

Мне кажется, стоит попробовать sigaction https://stackoverflow.com/questions/338 … gterm-in-c

188 Отредактировано Voldemar0 (24-05-2024 10:19)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Ну да, верно: если нужно как-то обработать исключения уровня "доступ к памяти запрещён" или что-то такое, то нужен свой обработчик сигналов.

В моём случае я использовал sigprocmask(). Это маскировка сигналов, причем пришедший сигнал не отбрасывается, он запоминается как необработанный. Как только маскировка снимается, сигнал будет обработан (в моём случае - обработчиком по умолчанию).

Т.е. полностью f1() у меня выглядит так:

void ui_client(char * msg_in, char * msg_out, int msg_out_max) {
  int r;

/* Так как вход в этому процедуру закрывается семафором, не следует допускать возможность её прерывания.
   Иначе семафор не будет открыт, а повторый вызов этой же функции из процедур группы atexit() приведёт чему нибудь плохому */
  sigset_t curset, oldset;
  sigemptyset(&curset);
  sigaddset(&curset, SIGINT);   // Ctrl-C, # 2
  sigaddset(&curset, SIGTERM);  // kill, # 15
  r = sigprocmask(SIG_BLOCK, &curset, &oldset);
  fatal(r, "UI client: sigprocmask set");
    
  r = pthread_mutex_lock(&io_mutex);
  fatal(r, "UI client: lock semaphore");

  ui_client_int(msg_in, msg_out, msg_out_max);
  
  r = pthread_mutex_unlock(&io_mutex);
  fatal(r, "UI client: unlock semaphore");

  r = sigprocmask(SIG_SETMASK, &oldset, NULL);
  fatal(r, "UI client: sigprocmask restore");
}

-----

Когда оставлял на выходные мост в доступе, предупреждал, что диск в 840ке долго обрабатывается.
Я думал дело  в тормозящей флешке, но проанализировал снятые образы и нашел причину:
позиционер флопика иногда пропускал шаг головки (причём только от края к центру, как правило где-то в районе нулевого трека). Странно, он это любит делать при недостатке питания, но сейчас он был воткнут напрямую в БП, даже минуя плату моста.

Дальше было так: всё это мост пытается декодировать, но получает от декодера ошибки. Соответственно, логика управления декодерами пытается перебирать параметры, настройки. Трек же не прочитался нормально, а что именно ненормально - её не беспокоит (обычно 1-2 сектора, залетевшие с чужого трека, особенно на 140-ке, особенно при программном "покачивании" головки - явление вполне привычное).

Но где-то в районе 30 цилиндра, по программе, есть обязательная рекалибровка. После неё голова встаёт на своё место и дальше все треки декодируются быстро. А поскольку после пробега от 0 к 160-му цилиндру идёт ещё пробег обратно, то младшие цилиндры читаются снова на обратном проходе. Логика декодеров видит, что они прочитались успешно и, следовательно, обзорного прохода достаточно.

В результате программа резюмирует "всё успешно прочиталось, ошибок нет, дочитывание не требуется".
А почему она тогда так тормозила и не узнаешь, пока не копнёшь поглубже.


Тут как раз тот случай, когда проще перечитать, чем тратить процессорное время на попытки выковырять то, чего нету. Но и "не шагающий" дисковод (кстати - трёхдюймовка) - тоже явление редкое... Надо ли тут что-то менять в коде ?

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

---

Доделал последний кусок в web-интерфейсе: удаление снятых образов. Заодно там же сделал возможность скачать образ или группу сразу в виде zip-архива. Не быстро (проца не хватает, чтобы быстро), но где-то 1 МБайт/секунду качается (компрессия налету, самая лёгкая, примерно 3:1). По FTP можно без компрессии можно забирать где-то 10 МБайт/секунду.

189 Отредактировано Voldemar0 (24-05-2024 20:58)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Кажись, я понял почему программа "Скорость" иногда сообщала о 399 мс на оборот.

Время измеряется подсистемой GPIO, которая в ядре линуха. Она сообщает о времени (некоем внутриядерном) изменения уровня на пине. Т.е. что-то вроде очереди событий, каждое из которых содержит таймштамп и описание события (RISING/FALLING). На первый взгляд было бы логично, если бы эти события выстраивались в какой нибудь FIFO и оттуда выгребались программой.

Но, похоже, авторы этой подсистемы решили, что FIFO - это скучно. И не ясно - какого размера его делать ? Или вообще динамически выделять память (если программа сейчас ничего не читает - на сколько может распухнуть такой стек буквально за секунды, если частота воздействия на лапку будет, например, 100 КГц  ?)
Поэтому они сделали по простому: сообщают только время последнего события каждого типа.
Т.е. не успел выгрести из очереди очередной импульс - получишь тот, который успеешь. Т.е. последний. Сколько пропустил - неизвестно.

Проблема в том, что в зависимости от того, какая страница включена на OLED, отрисовка идёт либо в память ui_server либо отправляется ещё и на физический OLED. Ну и, возможно, какой-то ещё вывод на интерфейсы требует некоторого времени. Плюс опрос клавиатуры на плате (которая не умеет работать по прерываниям). В сумме это занимает где-то те же 200 мс. Т.е. иногда импульсы просто терялись.

Решение: сперва запрашиваем новые события без ожидания. Если ОС сразу вернула что-то, то ставим флаг enable_io = 0 и выполняем всю математику и учёт, но всевозможные printf предваряем конструкцией "if (enable_io)".

Если же ОС ничего не вернула по запросу, тогда уже повторяем запрос, но с разрешенным ожиданием события в 250 мс. И сразу ставим enable_io = 1.

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

И оно заработало нормально :)

Spoiler

The head is on the track   0,   10 turn(s), instant time 199.55 ms, average time 199.5376 ms
The head is on the track   0,   11 turn(s), instant time 199.54 ms, average time 199.5378 ms
The head is on the track   0,   13 turn(s), instant time 199.54 ms, average time 199.5379 ms
The head is on the track   0,   15 turn(s), instant time 199.54 ms, average time 199.5385 ms
The head is on the track   0,   17 turn(s), instant time 199.56 ms, average time 199.5400 ms
The head is on the track   0,   19 turn(s), instant time 199.54 ms, average time 199.5393 ms
The head is on the track   0,   21 turn(s), instant time 199.55 ms, average time 199.5394 ms
The head is on the track   0,   22 turn(s), instant time 199.54 ms, average time 199.5394 ms
The head is on the track   0,   24 turn(s), instant time 199.55 ms, average time 199.5396 ms
The head is on the track   0,   25 turn(s), instant time 199.54 ms, average time 199.5396 ms
The head is on the track   0,   27 turn(s), instant time 199.54 ms, average time 199.5397 ms
The head is on the track   0,   29 turn(s), instant time 199.54 ms, average time 199.5400 ms

190

Re: Мост # 3 - специализированный компьютер для чтения дискет

Супер! 👍

191 Отредактировано Voldemar0 (30-06-2024 05:05)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Восьмая часть, завершение первого сезона:
https://youtu.be/3E0ZFm4zCFs

192 Отредактировано Voldemar0 (30-06-2024 05:28)

Re: Мост # 3 - специализированный компьютер для чтения дискет

Мне удалось решить баг с битой переменной only140 и это оказалось тоже довольно любопытной историей.

Суть её в том, что firefox имеет странное поведение, не совпадающее с Chrome, например.
Когда FF восстанавливает вкладки при открытии браузера (если выставлен соответствующий режим),
он восстанавливает также значения полей в формах. Но похоже, что при этом, в интерпретаторе javascript,
автоматически синтезируется событие onchange.

Получается странная коллизия: мы ещё не запросили (или не получили ответ, например, если Мост3 сейчас выключен) конфиг-файл с шаблонами и номерами имён образов, но уже вынуждены их сохранить (onchange автоматически вызывает процедуру сохранения).
Ну хорошо, допустим, FF всё вытащил из своих хранилищ и прощелкал по всем полям onchange и всё ушло на сохранение в Мост3. Но вот что интересно: текстовые поля ввода восстанавливаются и синтезируют соответствующие поля конфига в памяти JS правильно, но не поле checkbox. На него события нет. Получается, что на сохранение в устройство уходит файл без only140, который как раз является checkbox.

Тут немного обсуждают эту штуку:
https://stackoverflow.com/questions/307 … ab-restore
и даже вроде как признали это багом, пока не исправили.

А тут оказывается, что вопрос про сохранение значений checkbox пока открытый:
https://wiki.mozilla.org/Session_Restor … o_be_saved

---

А когда-то мне довелось (в другом проекте) довольно долго бороться с тем, что некоторые браузеры пытаются даже синтезировать некоторые поля форм там, где этого совсем не требуется. Однажды у меня браузер решил, что очередное поле ввода является логином пользователя. И упорно делал автозаполнение. Попытки запретить autocomplete аттрибутом поля ни к чему не привели, также как и попытки явно задать значение поля пустым.
пришлось поставить таймер на одну секунду и через секунду после загрузки страницы, когда браузер уже выполнил автозаполнение, очищать поле.

===

На этом разработка Мост3 завершена.
В первое сообщение темы добавил все ссылки на видео и user manual.

Дальнейшее покажет опытная эксплуатация.