По работе пришлось портировать обычное приложение VisualDSP++ на библиотеку VDK. Приложение было довольно сложным, и портирование происходило в поиске приемлемого компромисса в удобстве управления системными ресурсами для решения нескольких задач, и удобстве программирования. И конечно хотелось изучить новую для себя рабочую среду. Здесь просто хочется высказать общие впечатления от работы библиотеки VDK.
[Что такое VDK, для чего это надо]
VDK это просто библиотека от Analog Devices (далее буду называть эту компанию сокращенно ADI, как она сама себя любит называть), поставляемая в комплекте со средой программирования VisualDSP++. Совместно с другими библиотеками этой компании библиотека VDK претендует на создание для приложения многозадачной среды выполнения задач с поддержкой реального времени. Короче говоря это RTOS (Real-Time Operating System), операционная система реального времени (по-русски ОСРВ). Отличается она от других RTOS в лучшую сторону только тем, что изначально рассчитана и оптимизирована на процессоры ADI, и поэтому вероятно задачи будут выполняться эффективнее (хотя это никто не проверял), и Вы из коробки получаете (с небольшими оговорками) самый широкий контроль над аппаратными ресурсами процессоров.
Что пользователь получает от VDK? Перечислю самые основные возможности, которые рекламирует сама компания ADI, и то, что мне самому понравилось (подробнее см. [1] и официальную документацию).
Управление процессором. Если Вы хорошо читали даташит на процессор, и досконально (почти, потому что все равно невозможно охватить все тонкости сложной аппаратуры) знаете его возможности и аппаратуру, то с VDK Вы удивитесь, что как мало знали процессор, для которого пишете программы. Короче говоря, Вы научитесь намного лучше распоряжаться тем, что имеется в наличии.
Единообразие доступа к ресурсам. В наборе библиотек VDK, SSL, драйверов устройств сделана попытка уйти от славянского базара с аппаратными ресурсами и процессорами. Имеется в виду, что процессоров стало довольно много, и даже в пределах одного процессора программируются все аппаратные устройства по-разному. Даже система настройки приоритетов прерываний и каналов DMA устроена довольно заумно, с первого раза разобраться довольно трудно.
С VDK и сопутствующими библиотеками программист одинаково работает со всеми аппаратными ресурсами процессора - с периферией (SPI, UART, и т. п.) и даже с DMA и системой прерываний. Поэтому (при условии хорошего знания API библиотек) программирование значительно упрощается, и переход программирования от одного периферийного устройства к другому, и даже от одного процессора к другому значительно облегчается.
Упрощение портирования. Если приложение основано на VDK и других библиотеках ADI, то при наличии достаточно количества ресурсов приложение намного проще перенести с одной модели процессора на другую.
Разделяй и властвуй. Этот принцип соблюдается наиболее полно при использовании многозадачной системы VDK. Ты видишь каждую задачу по отдельности, и одновременно есть в голове четкий образ всей системы целиком. Видно, как задачи взаимодействуют друг с другом, что вообще происходит в системе, и при этом можно программировать каждую задачу отдельно, на время забыв про другие проблемы. Это позволяет проще программировать, сосредотачиваясь на решении конкретных задач, как каждой по отдельности, так и на предоставление роли каждой задачи в пределах всей системы в целом.
Когда программист работает с обычной, не многопоточной средой, он пытается в принципе сделать то же самое, но другими, кустарными способами. С помощью основного контекста (вызовы подпрограмм в бесконечном цикле main), прерываний и их приоритетов, флагов, глобальных буферов и переменных программист пытается решить ту же задачу, что и решает RTOS. И получается это не всегда хорошо, особенно если программа сложная.
[Проблемы, которые возникают с VDK]
Конечно, когда получаем все эти вкусные плюшки, обязательно будет что-то не так, как мы ожидали. Так не бывает, что всегда все хорошо, обязательно за новые возможности мы должны чем-то заплатить. То же самое нас ждет и с VDK, грабли есть, их никто не отменял, весь вопрос в том, чтобы наступить на них наименее болезненно. Ниже перечислю те проблемы (условно из можно назвать недостатками), с которыми придется столкнуться при использовании VDK, пределах убывания важности (это чисто моё ИМХО).
Громоздкое API. На то, чтобы запустить первое VDK-приложение, которое крутит пару-тройку задач и весело мигает светодиодом, у Вас уйдет от силы несколько дней, может быть неделя. Но радоваться будете недолго. Когда попытаетесь решать реальные задачи, и начнете применять API, то придется изучить гору документации (начиная с "VisualDSP++ VDK (Kernel) User’s Guide"), которая намного объемнее, чем даташит на процессор. Не факт, что Вы это выдержите.
Повышенные требования к объему SRAM. VDK активно использует SRAM для собственных нужд. Имеется в виду именно внутренняя, самая быстрая память L1 процессора. Для создания задач VDK используется системная куча (system heap), именно в ней размещается контекст задачи (стек, локальные переменные, блоки TCB). По умолчанию системная куча организована именно в SRAM, и простыми способами увеличить её размер нельзя. Системная куча может быстро опустошиться, когда вы создадите много задач, активно используя в них локальные переменные.
Для использования VDK обязательно должна быть также в наличии память SDRAM, в которой можно создать альтернативные кучи, где также может быть размещен код программы, буферы и переменные. Иначе полноценно использовать VDK не получится, Вы быстро столкнетесь с нехваткой памяти.
Проблему кучи при наличии SDRAM также можно решить путем создания альтернативных куч - ценой правки LDF, изучения документации, рационального размещения в памяти кода и всех буферов и переменных. И конечно нужно внимательно следить за размером стека каждой задачи, и экономно выделять память для каждой.
Отход от привычной модели программирования. Взаимодействие с аппаратурой, обмен данными между периферийными устройствами и программой, обмен данными между отдельными задачами теперь должен быть организован по-другому. Для этого нужно использовать драйверы, обработку событий, семафоры, сообщения, очереди, функции обратного вызова (callback-и), менеджер их отложенного вызова, блокировку задач, т. е. средства операционной системы VDK и других библиотек ADI. Хотя можно использовать и старые традиционные способы - глобальные буферы и флаги и их опрос в бесконечном цикле каждой задачи, но не уверен, что это будет эффективное решение. Если Вы ранее имели дело с какой-то другой RTOS, то освоиться будет проще.
Некоторые вопросы программирования нельзя решить только средствами VDK. Например, если Вам нужно строго синхронно по времени запустить два совершенно разных периферийных устройства, то исключительно средствами драйверов ADI это не получится. Дело в том, что код драйверов универсален, и довольно велик по объему. Из-за наличия конвейера, кэширования кода и данных время выполнения кода драйвера невозможно заранее совершенно четко спрогнозировать, поэтому синхронного запуска двух аппаратных устройств с помощью вызовов API не получится. Это критичный недостаток, когда Вы хотите заставить работать 2 аппаратных устройства совершенно синхронно - например, канал передачи SPORT должен формировать сигнал выборки АЦП синхронно с работой канала DMA на канале приема SPORT.
К счастью, эту проблему обычно можно обойти, правда не совсем честным с точки зрения всей концепции API ADI. Сначала нужно настроить всю аппаратуру, которая должна работать синхронно, штатными вызовами API, после чего в критической секции кода записью в регистры запретить настроенную аппаратуру и тут же запустить заново.
Дополнительные затраты на место под код. Когда я по объему памяти сравнил старое, не VDK приложение, с аналогичным приложением, построенным на основе VDK, то выяснил, что объем кода вырос примерно на 64 килобайта. Не мне судить, много это или мало - все в этом мире относительно. Если у Вас в наличии 512 килобайт и более, то проблема лишних затрат памяти программ может быть несущественной. Если же наблюдается дефицит памяти, то следует выбрать систему с большим объемом памяти для загрузки, либо придется отказаться от использования VDK.
Немного по-другому строится процедура отладки. Конечно, старый принцип пошаговой отладки работает, но в многозадачной среде пользоваться им не очень удобно. Придется изучить дополнительные средства, которые специально для VDK предоставляет среда программирования VisualDSP++ (инструментальные сборки, окно состояния приложения VDK, окно истории и т. п., подробнее см. [3, 4]).
Очень помогает текстовый канал вывода в отладочную консоль. Однако имейте в виду, что штатная консоль VisualDSP++, которая доступна по умолчанию, работает, но делает это очень медленно, и будет замедлять работу приложения. Поэтому намного лучше использовать для вывода отладочных сообщений аппаратное устройство, например UART [5].
Мало рабочих примеров кода. Примеры готовых проектов есть, но их можно найти только в составе примеров, поставляемых вместе с VisualDSP++. Создается такое впечатление, что если про VDK программисты знают, то только в весьма узком, и причем закрытом кругу. По крайней мере, в Интернете проектов с использованием VDK не найдете. Скорее всего это касается не только именно VDK, а просто примеров программ с использованием процессоров DSP компании ADI.
[Ссылки]
1. Обзор VisualDSP++ Kernel RTOS (VDK). 2. VDK FAQ. 3. Конфигурирование и отладка проектов VDK. 4. EE-312: построение сложных LwIP-приложений на основе VDK Blackfin. 5. Blackfin: форматированный вывод в окно терминала через UART. |