DMA вообще и в частности

    Знал бы где упадешь, соломки подстелил бы

    О существовании DMA (Direct Memory Access) — русскоязычное ПДП (Прямой Доступ к Памяти) многие разработчики встроенных устройств слышали, но вот применяют его гораздо реже, чем он (ПДП) этого заслуживает. Кстати, я буду упоминать именно эту аббревиатуру, но не потому, что я такой упрямый патриот и противник англоязычных заимствований, а всего лишь от того, что мне лень лишний раз переключать раскладку клавиатуры.

    Основных причин недостаточного использования ПДП в программах для МК три: 1) относительная сложность данного устройства, которая вместе с 2) непониманием выгод его применения приводит к нежеланию данное устройство изучать и осваивать (как говорят в таких случаях, старшая сестра не велит — для тех, кто в танке — это про лень, котороая раньше нас родилась), отягощенному 3) отсутствием хороших и понятных примеров применения ПДП в поставляемых с МК руководствами. И если первые две причины носят явно субъективный характер, то третья несомненно объективна и внутри меня просыпается параноик и настойчиво утверждает, что это сделано специально с целью не допустить отечественных разработчиков МК на продвинутые уровни, где-то выше 60 (то, что при этом страдают и остальные разработчики по всему миру, параноиком игнорируется, поскольку либо 1) за пределами России распространяются правильные примеры, либо 2) ради великой цели не допустить вставания, сами понимаете кого, с колен буржуины готовы пойти на любые жертвы).

    Тем не менее без шуток, действительно, в примерах в лучшем случае лежит модуль настройки отдельно взятого канала ПДП, а увязанную систему с ПДП драйвером Вы в примерах применений не найдете (даже в CMSIS не найдете, ну тут действительно есть объективная причина — напишу пост про него — упомяну). Почему так на самом деле — я не знаю, но разработчикам кристаллов виднее, единственное разумное обоснование, которое мне приходит в голову — это то, что ПДП довольно таки специфичны, поэтому «нельзя просто так взять и » перенести код из другого источника, а ввиду малой востребованности ПДП в реальных разработках отсутствие таких примеров не считается существенным недостатком. Восполнить указанный мной пробел в знаниях и предназначен настоящий пост (нескромное заявление, но если сам себя не похвалишь, весь день ходишь как оплеванный), поэтому те, кого я заинтриговал, могут нажать на кнопочку.

    Тем не менее, должен предостеречь нетерпеливого читателя, что он не найдет тут серебряной пули, которую можно смело включать в свои разработки, а всего лишь (но и это немало) обнаружит некоторые мысли и подходы, которые облегчат ему построение своих собственных систем на МК с применением ПДП. То есть я поставлю флажки в тех местах, где точно лежат грабли, но не гарантирую, что непомеченных граблей не останется, что, впрочем, не мешает Вам повыкидывать флажки на фиг и пройтись по граблям самостоятельно. Вообще, те, кто читал мои посты, наверняка обратили внимание, что я делаю упор не на то, ЧТО следует сделать и КАК именно, а на то, ПОЧЕМУ я рекомендую сделать именно так.

    Итак, ПДП — это часть аппаратуры МК, которая позволяет производить пересылку данных между различными составными частями данного МК (и системы с его участием) без привлечения ресурсов процессора (точнее говоря, с минимальным привлечением, поскольку делать что либо в МК системе вообще БЕЗ участия процессора — мысль смелая и далеко заводящая).

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

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

    Встречалась картина (например в ДВК), когда одно ВУ работало по ПДП, а второе — по прерываниям или даже в цикле опроса (драйвер MX, если кто помнит). Когда появились первые МК, в которых память интегрирована в чип, создание внешних по отношению к кристаллу устройств с ПДП стало весьма нетривиальной задачей и, естественно, ПДП перекочевало внутрь МК и стало частью его архитектуры. Этот процесс не имел линейного поступательного характера и можно встретить как МК на основе 51й архитектуры с поддержкой ПДП, так и МК на основе Cortex-M3 с богатым набором периферии, но без поддержки ПДП (например, Stellaris). Тем не менее, в бОльшей части современных МК на основе ARM ПДП присутствует и можем перейти к их изучению и для начала остановиться на рассмотрению их особенностей.

    Как было сказано выше, основное назначение ПДП — передача данных между разными устройствами с минимальным привлечением процессора. Как правило, одним из этих устройств является основная память МК, хотя иногда возможны как передачи между двумя внешними устройствами, так из памяти в память. Некоторые ПДП поддерживают такие возможности, некоторые нет, и это следует учитывать при выборе МК.

    Следующей важной характеристикой является количество одновременно обслуживаемых каналов передачи — в том смысле, конечно, что в каждый момент времени по шине может передаваться только одна порция данных, но может быть несколько запросов, которые будут обслуживаться поочередно, опять таки при минимальных затратах ресурсов процессора. Естественно, минимальное количество каналов ПДП -1 (меньшие количество каналов едва ли будут работоспособны), максимальное — практически неограничено, реальным ограничением может быть количество внешних устройств+1(для запросов типа память-память), но ничто (кроме стоимости) не может помешать сделать нам сколь угодно много каналов ПДП.

    Следующей особенностью можно считать механизм обслуживания запросов в одном канале. Остановимся на этом моменте поподробнее и разберем в общих чертах работу одного запроса одного канала ПДП.

    Для того, чтобы совершить передачу, нам следует сообщить ПДП о своих намерениях, то есть откуда мы хотим передавать данные, куда их следует направить, сколько именно данных следует передать, режимы передачи (об этом чуть позже), и, возможно, служебная информация. Поместить данную информацию мы можем либо в регистры, ответственные за работу ПДП (устаревший способ и дальше мы поймем, почему) либо в оперативную память системы, причем в последнем случае это должна быть либо специальная выделенная область памяти, чтобы ПДП знал, откуда надо взять информацию, либо в какой то регистр ПДП должна быть помещена информация о том, где именно в оперативной памяти лежат данные (говоря привычным языком, мы должны поместить ссылку). Именно последний метод и используется, поскольку он имеет следующие преимущества: оперативная память МК — ценный ресурс и сегментировать ее на детерминированные блоки не есть хорошая практика.

    Так вот, после того, как заданная передача будет произведена, мы получим сигнал об окончании передачи (скорее всего в виде прерывания) и нам вполне может потребоваться как можно быстрее начать следующую передачу. Если мы задаем параметры передачи в регистрах, то либо мы не можем их модифицировать до окончания текущей передачи, либо делать теневые регистры. Если же в регистре хранится ссылка на данные, определяющие передачу (TCB — Transfer Control Block — Блок Управления Передачей -БУП), то мы можем во время выполнения одной передачи заранее настроить БУП для следующей и по окончанию текущей передачи изменить всего лишь ссылку в регистре ПДП.

    На практике встречаются разнообразные комбинированные схемы, в основном с целью экономии аппаратуры МК — указатель на область памяти, в которой размещаются 2 или более БУП, циклически переключающиеся по мере исполнения, указатель на следующий БУП в служебном поле текущего БУП, иерархический доступ, когда БУП содержит указания на последовательность БУП, которые собственно и выполняются и так далее.

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

    Теперь перейдем от рассмотрения ПДП вообще к рассмотрению конкретной реализации, а именно к МК фирмы «Миландр» 1986ВЕ1Т.

    Почему именно к нему? Ну, во-первых, я с ним работаю, во-вторых, у него достаточно богатый по возможностям ПДП, а в-третьих, у него богато фич (это не баг это фича такая — да да именно из этого разряда), которые делают работу с МК увлекательным занятием, после которого работа с аналогами от известных производителей покажется легкой и простой.

    Сначала о хорошем — ПДП поддерживает 32 независимых канала доступа — по одному на каждое внешнее устройство в составе МК и еще один для пересылок память-память. Кроме того, как вы уже поняли из предыдущего предложения, ПДП поддерживает все возможные режимы пересылки, а именно: регистры ВУ-память, регистры ВУ-регистры ВУ, память-память, и если вам кажется, что так и должно быть, то это совсем не так, и разные режимы функционируют слегка по-разному и не везде реализованы.

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

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

    И здесь нас ждет:

    ЗАСАДА №1 от разработчиков — прерывание от окончания передачи не проявляются в внешних устройствах. То есть у нас есть один вектор прерывания по окончанию транзакции от любого из запрограммированных каналов. Более того, нет никакого регистра, в котором хранился бы номер канала, завершившего транзакцию, либо хотя бы битовый регистр с флагами. То есть единственный способ определить номер завершившего передачу канала — перебирать все каналы и смотреть соответствующие поля TCB, и это нам придется делать в обработчике прерывания, который должен занимать минимальное время. Напрашивающееся решение — перенести поиск канала в нижнюю половину драйвера обработки не проходит, поскольку нас ожидает:

    ЗАСАДА № 2 от разработчиков — прерывание является потенциальным и прекратить работу верхней половниы, не сбросив его явным образом, мы не можем. Более того, есть еще и

    ЗАСАДА № 3 от них же — мы не можем сбросить прерывание путем манипуляции реистрами ПДП, а должны проводить сброс разрешения выработки запросов в регистрах внешнего устройства. Да да, именно так, драйвер ПДП должен что то знать о составе регистров обслуживаемых устройств, более чудовищного нарущения принципа инкапсуляции (а он справедлив и для проектирования аппаратуры) трудно себе представить. Я не знаю, что курили разработчики ПДП, но, как написано у Гайдука, «что то очень интересное». То есть, вы можете не верить, но если мы запретим прохождение запросов соостветствующего канала и запретим его обработку, то прерывание мы все равно НЕ СБРОСИМ.
    Что-то получилось больше букв, чем было запланировано, поэтому оставим читателей размышлять о сложной ситуации, в которой оказался главный герой истории, что особенно актуально в пятницу вечером, а сам напишу Продолжение следует…
    Поделиться публикацией

    Похожие публикации

    Комментарии 26
      +17
      Что-то в этой статье не так
        +1
        Повсеместное ПДП
          +1
          Последствия использования отечественных микросхем)))
            +1
            Оптимизация и экономия во всем. Верстка недостойна потраченных на нее ресурсов!
            +9
            Возможно, дело в том, что изнеженные дифференциацией дефиса, минуса и тире хипстеры привыкли к рыхлым текстам с раскидистыми ветвями комментариев.
            Теперь же вид настоящего, прямоугольного, монолитного блока текста вызывает неподдельный ужас.
            Автор даже сжалился и оставил целую(!) пустую строку.
              0
              Это случайно получилось, я не хотел )
              0
              Хм, похоже ее кто то отредактировал у меня не было так много пустых строк.
              Спасибо неизвестному доброжелателю, если так действительно удобнее, то я не против.
              +1
              Надо больше картинок! Надо больше картинок!
                +1
                Либо хотя-бы человеческое форматирование
              • НЛО прилетело и опубликовало эту надпись здесь
                  +2
                  DMA контроллер от Миландра не лучший вариант для первого знакомства. Излишне навороченный, тормозной и косячный.
                  Большинство импортный МК имеют гораздо более гуманный DMA
                    –2
                    А вот у нас в конторе кроме миландровской продукции, а также продукции некоторых иных российских производителей, попавших в ограничительный перечень, ничего другого не применяют. Потому что запрещено. Так что, если знакомиться, то сразу уж и жениться. А то на импортном научишься, а они ничего подобного так и не сделают. Переучивайся потом.
                      +1
                      У нас тоже на многих проектах ограничительные перечни действуют, но вы лучше подумайте об основной аудитории данного сайта — указанный процессор большинство даже при желании пощупать не сможет, т.к. во-первых в розницу его частнику еще найти надо, а во-вторых стоит недешево.
                      Я сам с удовольствием почитаю о том, как автор борется с проблемами, с которыми самому, возможно, еще только предстоит столкнуться. Но для большинства читателей это будет чисто теоретический экскурс.
                        0
                        Да, все так. Российские производители выпускают не слишком качественные но достаточно дорогие процессоры. При этом не особенно заморачиваются с их поддержкой и продвижением. Из плюсов разве что только то что вся документация полностью на русском языке.
                          0
                          в Вашей статье "Документация явно переводная, есть и ошибки перевода, которые сильно искажают смысл, есть и весьма невнятно описанные места".
                          Что это? Писатель документации на российский микроконтроллер слямзил доку с иностранного оригинала?
                            0
                            У них есть IP-блоки собственной разработки, а есть покупные и DMA один из таких. Естественно документация на покупные блоки была исходно на английском. И мне, кстати, неизвестно ни одного иностранного МК использующего подобный контроллер DMA.
                            +1
                            вообще-то интересно взаимодействие программистов firmware и разработчиков чипа — вообще эта связь существует или нет? Или производитель Миландр почивает на лаврах — «все равно МО купит»?
                            Как мне представляется исправить описанные Вами аппаратные проблемы наверное очень просто при желании? Или нет желания?
                              +1
                              Это не моя статья, но мы тоже пользуем российские процессоры. Сам я скорее аналоговый схемотехник, специалист по антеннам и СВЧ, чем по процессорам. Программы пишу только небольшие, типа, чтобы не беспокоить по пустякам «настоящих» программистов. Поэтому, DMA в разработках не пользовал, но есть опыт общения с миландровскими разработчиками по поводу их CAN контроллера 1886ВЕ5, и по мылу с ними переписывался, и на их форуме вопросы задавал. Они там накосячили с этим CAN интерфейсом, сообщения принимались через раз, присылали подпрограмму на ассемблере чтобы закрыть вопрос, но все равно пришлось как-то изгаляться, не помню уже как именно. На форуме спрашивал, почему тактовый генератор не запускался и еще что-то, с генератором оказалось нога какая-то не заземлена, при включении контроллер был в sleep режиме. Нормально разъяснили, достаточно быстро, форум они отслеживают.
                                0
                                Глюки бывают у всех производителей. Помню сколько было косяков у новых чипов LPC в своё время. Но ребята не только работали на форуме но регулярно правили документацию, выпускали ерраты, что очень облегчало жизнь. К сожалению наши разработчики уделяют документации и её своевременной доработке крайне мало времени, возможно потому, что их изделия предназначены для очень узкого круга клиентов, в основном связанных с ВПК и проще решать проблемы при личном общении в форумах.
                                  0
                                  Вот за форум и поддержку Миландру респект и уважение — действительно грамотные спецы и оперативно работают. Но все-таки вопрос — может все таки надо больше внимания уделить разработке и документирования и нагрузка на поддержку упадет? Хотя им, конечно, виднее.
                                  +1
                                  К исправлению ошибок они подходят примерно по следующему принципу:
                                  Критические ошибки, которые делают невозможным использование МК или его ключевых функций, исправляются в новой ревизии чипа.
                                  Некритические ошибки, которые снижают характеристики или имеют возможность программного обхода исправляются «как повезет». Если МК прошел уже несколько ревизий и не имеет критических ошибок — ничего исправляться не будет.

                                  Справедливости ради отмечу, что не только Миландр так работает. У тех же ST косяки кочуют не только из одной ревизии в другую, но и в новые версии МК, которые они регулярно выпускают.
                                0
                                Ну он не такой уж и дорогой.
                                Версия в пластике 400 рублей.
                                Есть отладочные платы с коммерческим аналогом от фирмы «LDM» — стоят окол 100 грина — не даром, конечно, но и не так чтоб очень много.
                              0
                              Косячный да, тормозной — под вопросом, а вот навороченность, по-моему, скорее плюс, чем мину для углубленного изучения.
                                0
                                тормозной — под вопросом

                                Не менее 8 тактов с момента возникновения запроса до его фактического исполнения, за 6 обращений к системной шине. Причем 8 тактов это в идеале, на деле больше, т.к. обращение к регистрам периферии на этом проце занимает по несколько тактов. Это ли не тормозной?

                                Тормознутость вообще обеспечивается как раз тем, что вы записали в достоинства — постоянным размещением TCB в RAM. В более прогрессивных DMA контроллерах TCB временно размещается в RAM, и копируется в регистры перед началом исполнения (DMA со связными списками). Что дает экономию по сравнению с Миландром по 4 такта на каждый обмен.

                                Эти «особенности» архитектуры приводят к весьма странному формату разработки: часто заранее очень трудно сказать, что выйдет быстрее по тактам — задействовать DMA или передать данные с использованием ядра. В итоге приходится в коде критичном ко времени исполнения по два варианта писать и проверять экспериментально.
                              +1
                              Советы автору.
                              Уделяйте больше внимания визуальному материалу, причём не только фотографиям. Для того чтобы понять как работает DMA очень нелишними были бы функциональные схемы устройства. Лично мне было бы интересно посмотреть на внешний вид описанного автором чипа или он настолько секретен что это военная тайна? Ещё немного странно что Вы в начале поста обещаете о том, что статья будет посвящена основным принципам применения DMA, но вскоре почему то скатываетесь на описание фич, а скорее недостатков, крайне специфического микроконтроллера, да ещё бросаете статью на полуслове — перечислении этих странностей.
                              Наверно для телесериала такой подход хорош, чтобы заинтересовать зрителя, но для разъяснения принципов работы DMA вряд ли.
                              Стоило бы поподробнее описать проблему в общем.
                              Затем привести функциональную схему и рассказать об части архитектуры типичного представителя АРМ ядра которая задействована в этом сложном процессе.
                              Ну а только затем переходить к описанию конкретной реализации.
                              В обучающем материале всё таки стоит придерживаться традиционной подачи информации, ну а главное делать паузу не после того как исчерпал лимит буковок, а по окончанию очередной смысловой части, чтобы мысль была закончена.
                              P.S. Не смотря на критику я поставил плюсик за статью просто потому, что приятно видеть попытку выйти за границы ардуино и разобраться в тонкостях архитектуры, пусть и не совсем удачную, но на ошибках учатся! Надеюсь продолжение статьи будет интереснее, нагляднее и полезнее.
                                0
                                Спасибо за критику, сам понимаю что картинок (хотя бы и без котиков) было бы неплохо, но у меня громадные проблемы с креативностью, то есть изложить свои мысли в более-менне связном виде еще могу, а вот снабдить иллюстративным материалом — для меня это проблема. А что касается внешнего вида — на сайте Миландра они все есть, надо бы ссылку дать, но опять таки не умею, ну да Гугл Вам в помощь.

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое