воскресенье, 10 апреля 2016 г.

CMSIS RTOS - Модель работы приложения с аппаратным ресурсом

Я проснулся с мыслью, что если никто в ближайшее время не отсканирует и не выложит в свободный доступ тонны книг по физике, физику просто забудут. Мне кажется последние 20 лет  физика умирает, двадцать лет назад казалось, что физика умирает уже 10 лет. За это время уже умерли физики, которые хоть что-то могли донести из своих знаний. Страшный сон.
Мне кажется современные физики не способны понять, что температура в степени 3/2 в уравнениях появляется только в случае, если одно уравнение подставлять в другое уравнение.


Модель работы приложения с аппаратным ресурсом.
Это не относится напрямую к RTOS. Я пытаюсь осмыслить, как работать из приложения с ресурсами контроллера, чтобы оставаться в рамках API.
Обычно в таких случая действует метод: вот вам объект, у него есть методы, если методов не хватает, дописываем. Если их число избыточно, некоторые методы не используются, от них можно отказаться. Плохой метод.

Я пригласил Кешу и рассказал про свои успехи в реализации операционки. Спросил, как он предпочитает использовать вызовы "драйвера": open-close, read write ... должны ли быть вызовы блокирующие или нет. Решили реализовать только неблокирующие вызовы, чтобы не плодить сущности.
В нашей концепции инициализация драйвера (аппаратного ресурса) происходит на другом уровне, до входа в приложение, вне приложения, до вызова main. Приложению достается уже полностью настроенный ресурс, к которому можно подключаться и выполнять операции чтения/записи.

Порядок действий такой:
1) _open(fd, Notify, data); -- подключиться к драйверу по идентификатору ресурса. Драйвер вызывает функцию Notify(data) c параметром data. Когда происходит событие, вызывается функция Notify. Логично, но не нравится. Что может быть альтернативой обратным вызовам? Не хочется использовать обратные вызовы в прерываниях.В CMSIS есть механизм синхронизации через сигналы. Который поддерживается в планировщике.
Рекомендуется передавать в качестве параметра data ссылку на сигнал osSignalRef(ThreadId, signal) и идентификатор процесса. Вызов osSignalRef() используется в пользовательском процессе, чтобы выразить ссылку на сигнал данного приложения. Ссылка предназначена для атомарного обращения к сигналу. В качестве функции уведомления можно использовать системный вызов - osThreadNotify. Обе функции osSignalRef() и  osThreadNotify() не являются частью CMSIS. Эти вызовы мы придумали, чтобы реализовать синхронизацию драйвера с приложением. Обработка данных происходит в пользовательском процессе. Вызов osThreadNotify происходит из прерывания, чтобы указать планировщику задач, что было бы разумно передать управление сразу указанному процессу.
2) Неблокирующий запрос: read/write(fd,...)
3) Ожидание завершения операции, например, ждем сигнала: osSignalWait(signal_mask, timeout); Ожидать можно сразу несколько сигналов по маске.
4) close(fd); завершаем работу с ресурсом.

Обработка исключений
В драйвере устройства, при выполнении операции может происходить ошибка аппаратуры или ошибка обработки данных, или ошибка в формате данных. Сообщения об ошибках как-то должны передаваться приложению. Используется метод принятый в POSIX и C11. Код ошибки можно передать через errno. Не думаю, что это самая удачная идея, но пока использую ее.
Возврат в приложение по ошибке не отличается от возврата по завершению. Мы точно также получаем свой сигнал, и уже в приложении проверяем статус завершения операции. Прокол данного метода может быть в ситуации, когда ожидаем сразу несколько вариантов событий, и по нескольким событиям происходит ошибка. Возможно стоит уйти от errno и сделать статус завершения операции атрибутом драйвера. Следующая идея статус завершения частью объекта "Трансфер", который описывает параметры запроса read/write. Сложность в том, что Transfer для разных драйверов имеет различный состав переменных: буфер ввода, быфер вывода, размер, адрес и пр.

Комментариев нет:

Отправить комментарий