Процессор использует прямой доступ к памяти (direct memory access, DMA) для передачи данных между областями памяти или между областью памяти и периферийным устройством. Процессор может задать операции перемещения данных и вернуться к нормальному потоку вычислений. При этом перенос данных полностью берет на себя встроенный контроллер DMA, работая независимо от ядра процессора.
Примечание: здесь приведен перевод раздела даташита Analog Devices [1], посвященного DMA Blackfin ADSP-BF538. Все непонятные сокращения и термины, встречающиеся в тексте, см. в разделе "Словарик" статьи [3].
В процессоре есть две подсистемы DMA: DMA контроллер 0 и DMA контроллер 1. Эти контроллеры DMA одинаковые в смысле описания, которое представлено в этой статье.
К двум контроллерам DMA привязаны определенные периферийные устройства, т. е. каждый из контроллеров имеет свой набор обслуживаемых периферийных устройств, которые поддерживаются функцией DMA. Привязка эта жесткая, и её нельзя перепрограммировать, она зависит только от типа используемого процессора.
Подробнее про привязки периферийных устройств см. врезку "Регистры DMAx_PERIPHERAL_MAP, MDMAx_yy_PERIPHERAL_MAP", таблицы 9-7 и 9-8.
Контроллеры DMA могут выполнять несколько типов передач данных:
• Между памятью и памятью DMA (MDMA), подробнее см. раздел "DMA для пересылок по памяти". • Между памятью и SPI, подробнее см. [2]. • Между памятью и последовательным портом (SPORT), подробнее см. [4]. • Между памятью и портом UART, подробнее см. [5]. • Между памятью и параллельным периферийным интерфейсом (PPI), подробнее см. "Parallel Peripheral Interface" [1].
В системе есть 14 DMA-совместимых периферийных устройств, включая контроллеры памяти DMA (MDMA0–1).
Примечание переводчика: я не смог насчитать 14 периферийных устройств, у меня получается только 13: PPI, SPORT0, SPORT1, SPORT2, SPORT3, SPI0, SPI1, SPI2, UART0, UART1, UART2, MDMA0, MDMA1. Похоже, в даташите [1] в этом месте опечатка.
Есть всего 28 каналов DMA, см. таблицу 9-1.
Примечание переводчика: похоже, что тут снова опечатка: в таблице 9-1 не 28 каналов, а 26.
Таблица 9-1. Каналы DMA.
PDMA: прием/передача PPI
PDMA: UART0 передача
PDMA: SPORT0 прием
PDMA: UART1 прием
PDMA: SPORT0 передача
PDMA: UART1 передача
PDMA: SPORT1 прием
PDMA: UART2 прием
PDMA: SPORT1 передача
PDMA: UART2 передача
PDMA: SPORT2 прием
MDMA0: stream0 передача (место назначения)
PDMA: SPORT2 передача
MDMA0: stream0 прием (источник)
PDMA: SPORT3 прием
MDMA0: stream1 передача (место назначения)
PDMA: SPORT3 передача
MDMA0: stream1 прием (источник)
PDMA: прием/передача SPI0
MDMA1: stream0 передача (место назначения)
PDMA: прием/передача SPI1
MDMA1: stream0 прием (источник)
PDMA: прием/передача SPI2
MDMA1: stream1 передача (место назначения)
PDMA: UART0 прием
MDMA1: stream1 прием (источник)
Примечание: PDMA означает DMA периферийных устройств, MDMA означает DMA на памяти.
В этой статье описаны функции, общие для всех каналов DMA, и также описано, как настроить операции DMA. Подробности, относящиеся к каждому периферийному устройству, см. в соответствующем разделе даташита, посвященном этому периферийному устройству (например для SPI см. [2]). Информацию по быстродействию и арбитражу шины для операций DMA можно найти в разделе "DAB, DCB, and DEB Performance" [1].
Примечание: DAB означает DMA acces bus, DCB означает DMA core bus, DEB означает DMA external bus.
DMA-передачи в процессоре могут быть на базе дескриптора или на базе регистра. Передачи DMA, основанные на дескрипторе, требуют настройки параметров, сохраненных в памяти, чтобы инициировать последовательность DMA. Этот вид передач позволяет соединить в цепочку несколько последовательностей DMA. При функционировании DMA на основе дескриптора канал DMA может программироваться для автоматической настройки и запуска другой передачи DMA, после того как текущая последовательность завершилась.
Передачи DMA на основе регистра позволяют процессору напрямую программировать регистры управления DMA для инициации передачи DMA. По завершению управляющие регистры могут быть автоматически обновлены своими оригинальными значениями настройки для продолжении передачи, если это необходимо.
[DMA и регистры MMR DMA]
Для удобства обсуждение в этой статье использует стандартные (не привязанные к какой-то определенной аппаратуре) имена для регистров DMA и памяти DMA.
Стандартные имена регистров перечислены в таблице 9-2. Стандартные имена регистров памяти DMA перечислены в таблице 9-4. При использовании в программе стандартные имена дополняются префиксами, обозначающими канал DMA (например, START_ADDR будет именоваться как DMA3_START_ADDR или DMA4_START_ADDR, и т. п.).
Регистры DMA попадают в 3 категории:
• Текущие регистры, такие как DMAx_CURR_ADDR и DMAx_CURR_X_COUNT. • Регистры параметров, такие как DMAx_CONFIG и DMAx_X_COUNT. • Регистры состояния и управления, такие как DMAx_IRQ_STATUS и DMAx_PERIPHERAL_MAP.
Буква x в именах DMAx представляет отдельное периферийное устройство, которое поддерживает DMA. Например, для DMA с привязкой канала по умолчанию DMA6_CONFIG представляет регистр DMA_CONFIG для периферийного устройства приема UART0. Для привязок по умолчанию каналов DMA см. таблицы 9-5 и 9-7 во врезке "Регистры DMAx_PERIPHERAL_MAP, MDMAx_yy_PERIPHERAL_MAP" (привязка может быть перепрограммирована через регистры DMAx_PERIPHERAL_MAP, MDMAx_yy_PERIPHERAL_MAP).
Только регистры параметров могут быть напрямую загружены из элементов дескриптора; элементы дескриптора перечислены в таблице 9-3.
В таблице 9-2 перечислены стандартные (без префиксов DMAx) имена регистров DMA. Для каждого регистра таблица также показывает смещение MMR, краткое описание регистра, категорию регистра и значение после сброса.
Таблица 9-2. Стандартные имена регистров MMR для DMA.
Смещение MMR
Имя
Описание MMR
Категория регистра
Знач. после сброса
0x00
NEXT_DESC_PTR
Указатель связи на следующий дескриптор.
Параметр
0x0000 0000
0x04
START_ADDR
Начальный адрес текущего буфера.
Параметр
0x0000 0000
0x08
DMA_CONFIG
Регистр конфигурации DMA, включая бит разрешения DMA.
Параметр
0x0000
0x0C
зарезервировано
0x10
X_COUNT
Счетчик внутреннего цикла.
Параметр
0x0001
0x14
X_MODIFY
Инкремент адреса внутреннего цикла в байтах.
Параметр
0x0002
0x18
Y_COUNT
Счетчик внешнего цикла (только для режима 2D).
Параметр
0x0001
0x1C
Y_MODIFY
Инкремент адреса внешнего цикла в байтах.
Параметр
0x0002
0x20
CURR_DESC_PTR
Указатель текущего дескриптора.
Текущее значение
0x24
CURR_ADDR
Текущий адрес DMA
Текущее значение
0x28
IRQ_STATUS
Регистр статуса прерывания. Содержит состояние завершения, состояние ошибки прерывания и состояние канала (передает данные/выборка дескриптора/пауза).
Управление
0x2C
PERIPHERAL_MAP
Отображение периферийного устройства на канал DMA. Содержит 4-битное значение, указывающее, к какому периферийному устройству привязан канал DMA (для каналов MDMA это поле только для чтения, т. е. привязку менять нельзя).
Управление
0x30
CURR_X_COUNT
Текущий счетчик (1D) или внутренний X-счетчик строки (2D), считает вниз от X_COUNT.
Текущее значение
0x34
зарезервировано
0x38
CURR_Y_COUNT
Текущий счетчик строк (только для 2D), считает вниз от Y_COUNT.
Текущее значение
0x3C
зарезервировано
Все регистры DMA доступны как 16-битные ячейки памяти. Однако следующие регистры могут быть доступны как 32-разрядные регистры: NEXT_DESC_PTR, START_ADDR, CURR_DESC_PTR, CURR_ADDR. Когда к этим четырем регистрам осуществляется доступ как к 16-битным ячейкам, то доступны их младшие 16 бит.
[По какому принципу именуются регистры DMA MMR]
Чтобы не перепутать имена элементов дескриптора и стандартные имена регистров DMA, в этой статье используется следующий принцип именования в таблице 9-3, где:
• Стандартные имена в левом столбце не привязаны в действительности к ресурсам процессора. • Средний столбец перечисляет специфическое имя MMR. Только специфические имена MMR отображены на ресурсы процессора. • В DMAx буква x обозначает номер канала DMA. Например, DMA3_IRQ_STATUS является IRQ_STATUS MMR для канала DMA номер 3. • Номер канала может быть назначен по умолчанию, либо может быть запрограммирован (через регистры DMAx_PERIPHERAL_MAP, MDMAx_yy_PERIPHERAL_MAP). Номера каналов DMA и привязку по умолчанию см. в таблицах 9-5 и 9-7 (врезка "Регистры DMAx_PERIPHERAL_MAP, MDMAx_yy_PERIPHERAL_MAP"). • Последний столбец перечисляет макросы, назначенные каждому элементу дескриптора в памяти. • Имя макроса в последнем столбце нужно только для ясности, чтобы понятнее обсудить принцип работы подсистемы DMA. • В левом столбце перечислены стандартные имена MMR, которые используются в обсуждении основного функционирования подсистемы DMA.
Таблица 9-3. Принципы именования DMA MMR и элементов дескриптора.
Общее имя
Полное имя PDMA MMR (x = номеру канала)
Имя соответствующего элемента дескриптора в памяти
DMA_CONFIG
DMAx_CONFIG
DMACFG
NEXT_DESC_PTR
DMAx_NEXT_DESC_PTR
NDPH (старшие 16 бит), NDPL (младшие 16 бит)
START_ADDR
DMAx_START_ADDR
SAH (старшие 16 бит), SAL (младшие 16 бит)
X_COUNT
DMAx_X_COUNT
XCNT
Y_COUNT
DMAx_Y_COUNT
YCNT
X_MODIFY
DMAx_X_MODIFY
XMOD
Y_MODIFY
DMAx_Y_MODIFY
YMOD
CURR_DESC_PTR
DMAx_CURR_DESC_PTR
-
CURR_ADDR
DMAx_CURR_ADDR
-
CURR_X_COUNT
DMAx_CURR_X_COUNT
-
CURR_Y_COUNT
DMAx_CURR_Y_COUNT
-
IRQ_STATUS
DMAx_IRQ_STATUS
-
PERIPHERAL_MAP
DMAx_PERIPHERAL_MAP
-
[По какому принципу именуются регистры памяти DMA]
Имена регистров памяти DMA (т. е. MDMA) несколько отличаются от имен других регистров DMA (т. е. PDMA). Потоки памяти DMA не могут быть переназначены на разные каналы, в то время как периферийные устройства, связанные с DMA, могут быть привязаны к любому каналу DMA от 0 до 21.
У процессора есть 2 контроллера DMA. Каждый контроллер содержит 2 потока памяти DMA. Буква x обозначает, к какому контроллеру DMA принадлежит канал, а у букв yy может быть 4 возможных значения:
• S0, источник памяти DMA потока 0 • D0, место назначения памяти DMA потока 0 • S1, источник памяти DMA потока 1 • D1, место назначения памяти DMA потока 1
В таблице 9-4 показано соглашение по именованию для регистров памяти DMA.
Таблица 9-4. Принцип именования регистров памяти DMA.
Общее имя
Полное имя MDMA MMR (x = 0 или 1, обозначает контроллер DMA; yy = S0, S1, D0 или D1)
Имя соответствующего элемента дескриптора в памяти
Регистр следующего указателя дескриптора NEXT_DESC_PTR задает, где найти начало следующего блока дескриптора, где описана активность DMA, когда завершится выполнение текущего блока дескриптора. Этот регистр используется только в режимах дескриптора моделей малого и большого списка. В начале дескриптора выбираются любой из этих режимов, 32-бита NEXT_DESC_PTR копируются в CURR_DESC_PTR. Затем, во время выборки дескриптора, регистр CURR_DESC_PTR инкрементируется после каждого прочитанного элемента в дескрипторе.
В режимах дескриптора моделей малого и большого списка регистр NEXT_DESC_PTR, но не CURR_DESC_PTR, должен быть напрямую запрограммирован через MMR-доступ перед началом работы DMA.
В режиме массива дескрипторов регистр следующего указателя дескриптора игнорируется, и выборка управляется только через регистр CURR_DESC_PTR.
Рис. 9-1. Next Descriptor Pointer Register (DMAx_NEXT_DESC_PTR / MDMAx_yy_NEXT_DESC_PTR).
Для этого регистра доступен доступ на чтение и запись до разрешения канала, и после разрешения канала доступен доступ только для чтения.
Регистр конфигурации DMA_CONFIG, показанный на рис. 9-3, используется для настройки параметров и режимов работы DMA. Имейте в виду, что запись в регистр DMA_CONFIG во время работы DMA приведет к ошибке DMA независимо от того, что в бит DMA_EN записывается 0.
Примечание: серым цветом помечены не используемые биты.
Для этого регистра доступен доступ на чтение и запись до разрешения канала, и после разрешения канала доступен доступ только для чтения.
FLOW[2:0] (Next Operation). Определяет следующую операцию DMA, которая начнется за текущей:
0x0 - Stop, остановка активности DMA на этом канале. Когда текущий рабочий блок завершится, канал DMA остановится автоматически, после сигнализации прерыванием (если прерывание разрешено). Бит состояния DMA_RUN в регистре DMAx_IRQ_STATUS поменяется от 1 к 0, бит DMA_EN в регистре DMAx_CONFIG останется неизменным. В этом состоянии канал находится на паузе. Прерывания периферийного устройства все еще отфильтровываются блоком DMA. Канал может быть перезапущен просто другой записью в DMAx_CONFIG с указанием следующего рабочего блока, в котором DMA_EN установлен в 1.
0x1 - режим автобуфера. В этом режиме не используются дескрипторы в памяти. Вместо этого DMA выполняет постоянные круговые проходы по буферу, основанные на запрограммированные пользователем настройки DMAx MMR. При завершении рабочего блока регистры параметров перезагружаются в текущие регистры, и DMA немедленно возобновится без участия процессора. Режим автобуфера может быть остановлен записью пользователем 0 в бит DMA_EN регистра DMAx_CONFIG.
0x4 - массив дескрипторов. В этом режиме выбирается дескриптор из памяти, в котором нет элементов NDPH или NDPL. Поскольку дескриптор не содержит запись следующего указателя дескриптора, подсистема DMA использует по умолчанию CURR_DESC_PTR для перешагивания по дескрипторам, что позволяет группе дескрипторов следовать в памяти одному за другим, наподобие массива.
0x6 - список дескрипторов (малая модель). В этом режиме выбирается дескриптор из памяти, в котором содержится поле NDPL, но не NDPH. Таким образом, старшие 16 следующего дескриптора берутся от старших бит в регистре NEXT_DESC_PTR, что ограничивает все дескрипторы областью страницы памяти 64 килобайта.
0x7 - список дескрипторов (большая модель). В этом режиме выбирается дескриптор из памяти, который включает NDPH и NDPL, что позволяет достичь максимальной гибкости для размещения дескрипторов в памяти.
NDSIZE[3:0] (Flex Descriptor Size). Определяет размер следующего дескриптора. Это поле задает количество регистров DMA MMR для загрузки из элементов дескриптора в памяти. Это поле должно быть равно 0, если нужна остановка или режим автобуфера. Если NDSIZE и FLOW указывают дескриптор, который расширяется за пределы YMOD, возникнет ошибка DMA.
0000 - требуется если Stop или режим автобуфера 0001 - 1001 - размер дескриптора 1010 - 1111 - зарезервировано
DI_EN (Data interrupt Enable). 0: не разрешать генерировать прерывание после завершения рабочего блока, 1: разрешить прерывание после завершения рабочего блока.
DI_SEL (Data interrupt Timing Select). Зарезервировано для ID-операции. 0: прерывание после завершения трансфера всего буфера (внешний цикл), 1: прерывание после завершения каждой строки (внутренний цикл) только для 2D. Этот бит указывает время прерывания данных: после завершения всего буфера или после каждой строки во внутреннем цикле. Этот бит используется только для функционирования 2D DMA.
RESTART (DMA Buffer Clear). Перезапуск, очистка буфера DMA. 0: сохранять данные DMA FIFO между рабочими блоками, 1: отбросить DMA FIFO перед началом рабочего блока. Этот бит указывает, должны ли принятые данные удерживаться в FIFO данных канала (RESTART=0), или же должны быть отброшены (RESTART=1) перед началом следующего рабочего блока. Принятые данные будут автоматически отброшены, когда DMA_EN изменяется от 0 к 1, обычно когда канал разрешается в первый раз. Принятые данные FIFO обычно должны сохраняться между рабочими блоками, если рабочие блоки составляют продолжающийся поток данных. Однако если новый рабочий блок запускает новый поток данных, бит RESTART должен быть установлен в 1, чтобы очистить ранее принятые данные.
DMA2D (DMA Mode). 0: линейный режим, 1: двухмерный (2D). Этот бит указывает, как должен работать режим DMA - вовлекать только X_COUNT и X_MODIFY (одномерный DMA) или также вовлекать Y_COUNT и Y_MODIFY (двухмерный DMA).
WDSIZE[1:0] (Transfer Word Size). Размер слова передачи:
00 - 8-битные передачи 01 - 16-битные передачи 10 - 32-битные передачи 11 - зарезервировано
Подсистема DMA поддерживает передачи 8-, 16- или 32-разрядных элементов. Каждый запрос/предоставление результата осуществляется за один доступ к памяти (несмотря на то, что требуется 2 цикла для передачи 32-битных данных через 16-битный порт памяти), или через 16-битную шину DAB. Размеры инкремента указателя адреса DMA (шаги) должны быть кратны размеру передаваемого элемента: 1 для 8 бит, 2 для 16 бит, 4 для 32 бит.
Дополнительную информацию про то, как настраивается каждый канал DMA для поддержки разных длин передачи, см. врезку "Регистры DMAx_PERIPHERAL_MAP, MDMAx_yy_PERIPHERAL_MAP".
WNR (DMA Direction). Направление DMA. 0: чтение памяти со стороны DMA (передача), 1: запись памяти со стороны DMA (прием).
DMA_EN (DMA Channel Enable). 0: запрет канала DMA, 1: разрешение канала DMA. Когда канал DMA периферийного устройства разрешен, прерывания от периферийного устройства означают запросы DMA. Когда канал запрещен, блок DMA игнорирует прерывание периферийного устройства и передает его напрямую в контроллер прерываний. Чтобы избежать непредсказуемого поведения, позаботьтесь о разрешении канала DMA перед разрешением периферийного устройства, и о запрете периферийного устройства перед запретом канала DMA.
Для двухмерных передач DMA (2D DMA) имеются регистры счетчика внутреннего цикла (Inner Loop Count, X_COUNT), показанные на рис. 9-4. Для одномерных передач DMA (1D DMA), они указывают количество элементов для чтения. Подробнее см. раздел "Двухмерные передачи DMA". Значение 0 для X_COUNT соответствует 65536 элементам.
Регистры инкремента адреса внутреннего цикла (inner loop address increment, X_MODIFY) содержат число со знаком в формате двоичного дополнения до 2 для инкремента байтового адреса. Для 1D DMA этот инкремент является шагом, который прикладывается после передачи каждого элемента.
Для 2D DMA этот инкремент накладывается после передачи каждого элемента во внутреннем цикле, до него, но не включая последний элемент в каждом внутреннем цикле (используется для развертки кадра). После последнего элемента в каждом внутреннем цикле вместо этого прикладывается Y_MODIFY, за исключением самого последней передачи в каждом рабочем блоке. X_MODIFY всегда прикладывается на последней передаче рабочего блока.
Поле X_MODIFY может быть установлено в 0. В этом случае DMA постоянно выполняется от одного и того же адреса. Это полезно, например, для передачи данных между регистром данных и внешним отображенным на память периферийным устройством.
Для режима 2D DMA регистры внешнего цикла (outer loop count, Y_COUNT) содержат счетчик внешнего цикла. Это не используется в режиме 1D DMA. В этом регистре содержится количество строк во внешнем цикле последовательности 2D DMA. Подробнее см. раздел "Двухмерные передачи DMA".
Регистры инкремента адреса внешнего цикла ( outer loop address increment, Y_MODIFY) содержат число со знаком в формате двоичного дополнения до 2 для инкремента байтового адреса. Это инкремент байтового адреса, который прикладывается после каждого декремента CURR_Y_COUNT, за исключением последнего элемента в 2D-массиве, когда также истекает CURR_Y_COUNT. Значение является смещением между последним словом в одной "строке" и первым словом в следующей "строке". Подробнее см. раздел "Двухмерные передачи DMA".
Регистры указателя текущего дескриптора (current descriptor pointer, CURR_DESC_PTR) содержат адрес памяти для следующего элемента дескриптора для загрузки. Для настроек режима FLOW, который вовлекает дескрипторы (FLOW=4, 6 или 7), этот регистр используется для чтения элементов дескриптора в подходящие MMR до начала рабочего блока DMA. Для режимов списка дескрипторов (FLOW=6 или 7), этот регистр инициализируется из NEXT_DESC_PTR перед загрузкой каждого дескриптора. Затем адрес в CURR_DESC_PTR инкрементируется с каждым прочитанным элементом дескриптора. Когда весь дескриптор прочитан, CURR_DESC_PTR содержит значение Descriptor Start Address + Descriptor Size (количество элементов).
Для режима массива дескрипторов (FLOW=4) этот регистр, но не регистр NEXT_DESC_PTR, должен быть запрограммирован доступом через MMR перед началом операции DMA.
Рис. 9-8. Current Descriptor Pointer Register (DMAx_CURR_DESC_PTR / MDMAx_yy_CURR_DESC_PTR).
Для этого регистра доступен доступ на чтение и запись до разрешения канала, и после разрешения канала доступен доступ только для чтения.
Регистры текущего адреса (current address, CURR_ADDR), показанные на рис. 9-9, содержат представленный адрес передачи DMA для имеющейся сессии DMA. В начале сессии DMA этот регистр загружается из регистра START_ADDR, и далее инкрементируется с каждой передачей. Регистр текущего адреса содержит 32 бита.
Рис. 9-9. Current Address Register (DMAx_CURR_ADDR / MDMAx_yy_CURR_ADDR).
Для этого регистра доступен доступ на чтение и запись до разрешения канала, и после разрешения канала доступен доступ только для чтения.
Регистр текущего внутреннего счетчика цикла (current inner loop count, CURR_X_COUNT) загружается значением X_COUNT в момент начала каждой сессии DMA session (для 1D DMA) и также после окончания каждой строки DMA (для 2D DMA). Иначе он будет декрементироваться каждый раз при передаче элемента. Когда регистр счетчика обнуляется, это означает завершение DMA. Для 2D DMA, CURR_X_COUNT равен 0 только когда передача завершится полностью. Между строками он равен X_COUNT.
Рис. 9-10. Current Inner Loop Count Register (DMAx_CURR_X_COUNT / MDMAx_yy_CURR_X_COUNT).
Для этого регистра доступен доступ на чтение и запись до разрешения канала, и после разрешения канала доступен доступ только для чтения.
Регистр текущего внешнего счетчика (current outer loop count, CURR_Y_COUNT) загружается значением Y_COUNT в момент начала каждой сессии 2D DMA. Он не используется для 1D DMA. Этот регистр декрементируется каждый раз, когда регистр CURR_X_COUNT истекает при операции 2D DMA (при его переходе от 1 к X_COUNT или от 1 к 0), что означает полную передачу строки. После завершения сессии 2D DMA значения регистров CURR_Y_COUNT=1 и CURR_X_COUNT=0.
Рис. 9-11. Current Outer Loop Count Register (DMAx_CURR_Y_COUNT / MDMAx_yy_CURR_Y_COUNT).
Для этого регистра доступен доступ на чтение и запись до разрешения канала, и после разрешения канала доступен доступ только для чтения.
Каждый регистр привязки периферии канала DMA PERIPHERAL_MAP содержит биты для:
• Привязки канала к специфическому периферийному устройству. • Идентификации, является ли канал каналом DMA периферийного устройства или каналом DMA памяти.
Есть 2 набора регистров PERIPHERAL_MAP. Один набор для каналов, связанных с DMA контроллером 0, и другой для каналов, связанных с DMA контроллером 1. Периферийные устройства назначаются на конкретный контроллер (0 или 1). Это назначение фиксировано, и не может быть выбрано пользователем (назначение для контроллера 0 приведено в таблице 9-5, для контроллера 1 в таблице 9-7).
Имейте в виду, что должно быть 1:1 соответствие в привязке каналов DMA и периферийных устройств. Пользователь отвечает за то, чтобы не было привязано несколько каналов DMA к одному и тому же периферийному устройству, и что несколько периферийных устройств не привязано к одному и тому же порту DMA. Если все-таки несколько каналов привязано на одно и то же периферийное устройство, то будет подключен только один канал (канал с самым низким приоритетом). Если к каналу привязано не существующее периферийное устройство (например, в поле PMAP записано значение 0xF), то канал будет запрещен - запросы DMA игнорируются, и не будут выдаваться чтения/записи DMA. Запросы DMA также не перенаправляются от периферийного устройства к контроллеру прерываний.
Ниже приведен пример шагов для переключения приоритетов канала DMA двух каналов. Убедитесь, что используются каналы 6 и 7.
1. Убедитесь, что DMA запрещен для каналов 6 и 7. 2. Запишите в DMA6_PERIPHERAL_MAP значение 0x7000, и в DMA7_PERIPHERAL_MAP значение 0x6000. 3. Разрешите канал DMA 6 и/или 7.
Регистр состояния прерывания (IRQ_STATUS), показанный на рис. 9-14, содержит биты информации канала DMA:
• Разрешен ли и работает ли канал, разрешен но остановлен, или запрещен. • Выбраны ли данные или дескриптор DMA. • Было ли детектировано глобальное прерывание DMA, или было выставлено прерывание канала. • Была ли зафиксирована ошибка DMA.
Обратите внимание, что прерывание DMA_DONE выставляется, когда был завершен последний доступ к памяти (чтение или запись). Для передач (чтение памяти) данные перемещаются в сторону периферийного устройства, здесь может быть до 4 слов данных в канале DMA, когда произошло прерывание. В этот момент будет нормальным немедленно запустить следующий рабочий блок. Однако если приложению нужно знать, когда в действительности последние данные были переданы в периферийное устройство, приложению нужно опрашивать бит DMA_RUN - этот флаг равен 1, пока есть не доставленные данные в FIFO.
Процессор поддерживает гибкую структуру прерываний с тремя источниками. Отдельные уровни прерываний IRQ выделены для данных, ошибок периферии и ошибок DMA:
• Прерывания, относящиеся к данным (см. таблицу 9-7). • Прерывания ошибки периферийного устройства. • Прерывания ошибки DMA (например, ошибка в дескрипторе или ошибка шины).
Все каналы DMA объединяются по ИЛИ на одно прерывание ошибки DMA системного уровня. Отдельные слова IRQ_STATUS каждого канала могут быть прочитаны для идентификации канала, на котором произошла ошибка DMA.
Рис. 9-14. Interrupt Status Register (DMAx_IRQ_STATUS / MDMAx_yy_IRQ_STATUS).
DMA_RUN (DMA Channel Running). Состояние канала DMA, бит только для чтения. Этот бит автоматически устанавливается в 1, когда записывается регистр DMA_CONFIG. 0: этот канал DMA запрещен, или он разрешен, но находится на паузе (FLOW mode 0), 1: этот канал DMA разрешен и работает, т. е. либо передает данные, либо делает выборку дескриптора DMA.
DFETCH (DMA Descriptor Fetch). Бит только для чтения, он автоматически устанавливается в 1, когда регистр DMA_CONFIG записывается с режимами FLOW 4–7. 0: этот канал DMA запрещен, или он разрешен, но остановлен (FLOW mode 0), 1: этот канал разрешен и в настоящий момент делает выборку дескриптора.
DMA_ERR (DMA Error interrupt register). Бит, который очищается операцией W1C (write-1-to-clear, записать 1 для очистки). 0: нет ошибки DMA, 1: произошла ошибка DMA, и выставлено глобальное прерывание DMA. После возникновения этой ошибки содержимое текущих регистров DMA не задано. Регистры параметров и управления остаются не измененными.
DMA_DONE (DMA Completion interrupt register). 0: для этого канала не было выставлено прерывание, 1: работа DMA завершена, и для этого канала DMA выставлено прерывание.
Таблица 9-9. Прерывания, относящиеся к данным.
Прерывание
Описание
-
Для этого рабочего блока прерывания могут быть запрещены.
Прерывание периферийного устройства
Прерывание от периферийного устройства, не относящееся к DMA.
Завершение строки
Прерывание DMA может произойти по завершении строки (когда истек CURR_X_COUNT).
Завершение буфера
Прерывание DMA может произойти по завершении передачи всего буфера (когда истекли CURR_X_COUNT и CURR_Y_COUNT).
Флаг DMA_DONE является флагом типа W1C (write-1-clear), т. е. для его сброса нужно в позицию флага по маске записать единицу. Пример ISR, где делается очистка прерывания завершения приема блока данных через SPORT3:
Когда происходит переключение от режима DMA к режиму без DMA, прерывания от периферийного устройства должны быть запрещены при переключении режима (через соответствующие регистры или маски SIC_IMASKx), чтобы нежелательное прерывание не было сгенерировано на общей линии запроса прерывания (поскольку прерывание DMA совмещено с прерыванием периферийного устройства).
[Гибкая структура дескриптора]
Гибкие дескрипторы DMA являются структурами с переменным размером данных, откуда содержимое загружается в регистры параметров DMA. Последовательность регистров в дескрипторе изначально фиксирована (в пределах 3 разных, но похожих вариантов), однако длина дескриптора полностью программируется. Регистры канала DMA упорядочены так, что чаще всего загружаемые регистры при обработке рабочего блока имеют самые младшие адреса MMR. При запуске подсистемы DMA пользователь может выбрать - использовать или не использовать дескрипторы. Если дескрипторы не используются, то пользователь может записать регистры DMA MMR напрямую, после чего запустить DMA, и использовать либо режим автобуфера (Autobuffer), если надо по циклу передавать один и тот же буфер, либо режим остановки (Stop) для одиночных передач буфера.
Для использования дескрипторов пользователь программирует поле NDSIZE в регистре DMAx_CONFIG количеством регистров DMA, которые должны быть загружены из дескриптора, начиная с самого младшего адреса MMR. Пользователь может выбрать размер дескриптора от одной записи (младшие 16 бит START_ADDR) до 9 записей (полностью все параметры DMA).
Имеется 3 варианта последовательности значений в дескрипторе - в зависимости от того, включен или не указатель на следующий дескриптор, и если включен, то какой у него вид.
1. Указатель на следующий дескриптор не включен (режим массива дескрипторов). 2. Включены младшие 16 бит следующего указателя дескриптора (список дескриптора, малая модель). 3. Включены полностью все 32 бита следующего указателя дескриптора (список дескриптора, большая модель).
Все другие регистры, которые не загружаются из дескриптора, сохраняют свои предыдущие значения (хотя регистры CURR_ADDR, CURR_X_COUNT, CURR_Y_COUNT перезагружаются между захватом дескриптора и запуском операции DMA).
Основные настройки DMA, которые не разрешено изменить из одного дескриптора к следующему в цепочке (малая или большая модели списков или режим массива дескрипторов): направление DMA, размер слова, область памяти (имеется в виду переключение между внутренней и внешней памятью).
Одна цепочка дескрипторов не может управлять последовательностью передачи буферов данных, которые размещены в разных видах памяти. Вместо этого создайте отдельные группы (цепочки) буферов данных для разных видов памяти, но не соединяйте цепочки разной памяти вместе. Сначала передайте первую цепочку, дождитесь последнего прерывания в этой первой цепочке и затем начните передавать следующую цепочку MMR-записью в DMA_CONFIG.
Обратите внимание, что хотя пользователь должен разместить каждый из буферов в цепочке в одном и том же пространстве памяти, структуры дескрипторов сами по себе могут быть размещены в любой области памяти, и могут создавать ссылку из дескриптора в одной области памяти на дескриптор в другой области памяти, без ограничений.
В таблице 9-10 показаны смещения для элементов дескриптора в трех выше описанных режимах. Обратите внимание, что имена в таблице перечисляют элементы дескриптора в памяти, но это не актуальные MMR, в которые они время от времени загружаются.
Таблица 9-10. Регистры параметров и смещения в дескрипторе.
Смещение дескриптора
Режим массива дескрипторов
Режим малой модели списка дескрипторов
Режим большой модели списка дескрипторов
0x00
SAL
NDPL
NDPL
0x02
SAH
SAL
NDPH
0x04
DMACFG
SAH
SAL
0x06
XCNT
DMACFG
SAH
0x08
XMOD
XCNT
DMACFG
0x0A
YCNT
XMOD
XCNT
0x0C
YMOD
YCNT
XMOD
0x0E
YMOD
YCNT
0x10
YMOD
[Двухмерные передачи DMA]
Двухмерные DMA поддерживают произвольные размеры строк и столбцов до 64K x 64K элементов, как и произвольные значения X_MODIFY и Y_MODIFY до ±32K байт. Более того, Y_MODIFY может быть отрицательным, что позволяет реализовать потоки данных с чередованием (interleaved data stream). X_COUNT и Y_COUNT задают размеры строк и столбцов, где X_COUNT должен быть 2 или больше.
Начальный адрес и значения для модификации указываются в байтах, и они должны быть выровнены на размер передаваемого слова DMA (WDSIZE[1:0] в регистре DMA_CONFIG). Ошибка выравнивания приведет к ошибке DMA.
Значение X_MODIFY является байтовым инкрементом адреса, который применяется после каждой передачи, когда декрементируется CURR_X_COUNT. Значение X_MODIFY не применяется, когда внутренний счетчик цикла оканчивает свое декрементирование CURR_X_COUNT с переходом от 1 к 0, за исключением случаев, когда это прикладывается на последней передаче, когда CURR_Y_COUNT равен 1 и CURR_X_COUNT декрементируется от 1 к 0.
Значение Y_MODIFY является байтовым инкрементом адреса, который применяется после каждого декремента CURR_Y_COUNT. Однако значение Y_MODIFY не прикладывается к последнему элементу в массиве, по которому считает счетчик внешнего цикла (CURR_Y_COUNT), когда он завершает декрементирование при переходе от 1 к 0.
После завершения последней передачи CURR_Y_COUNT=1, CURR_X_COUNT=0, и CURR_ADDR равен адресу последнего элемента плюс X_MODIFY. Обратите внимание, что если канал DMA запрограммирован для автообновления (режим автобуфера), то эти регистры загружаются из X_COUNT, Y_COUNT, и START_ADDR, как это было при первой передаче.
На рисунках 9-15 и 9-16 показан процесс DMA, состоящий из 2 частей.
Рис. 9-15. Работа DMA с точки зрения контроллера DMA (часть 1 из 2).
Рис. 9-16. Работа DMA с точки зрения контроллера DMA (часть 2 из 2).
[Предварительная настройка DMA]
В этом разделе рассматривается запуск DMA "с нуля". Ситуация будет похожа на запуск DMA, когда он встал на паузу в режиме FLOW = 0.
Перед инициацией DMA в первый раз на предоставленном канале убедитесь в инициализации всех регистров параметров. Особенно внимательно инициализируйте старшие 16 бит регистров NEXT_DESC_PTR и START_ADDR, потому что иначе к ним может не быть доступа, в зависимости от выбранного режима FLOW.
Для запуска операции DMA на предоставленном канале сначала должны быть напрямую записаны все или некоторые регистры параметров DMA. На этом шаге должны быть записаны как минимум регистр NEXT_DESC_PTR (или CURR_DESC_PTR в режиме FLOW = 4), однако пользователь может захотеть записать другие регистры DMA, которые конечно могут быть статическими при активности DMA (например, это X_MODIFY, Y_MODIFY). Содержимое NDSIZE и FLOW в DMA_CONFIG укажет, какие регистры, если таковые имеются, захватываются из элементов дескриптора в памяти. После выборки дескриптора, если он есть, настройка завершена, начнется операция DMA после записи DMA_CONFIG с битом DMA_EN = 1.
Когда DMA_CONFIG записан напрямую, контроллер DMA распознает этот факт как специальное условие запуска, которое происходит, когда запускается DMA в первый раз на этом канале или после того, как подсистема DMA была остановлена (при FLOW = 0). Когда выборка дескриптора завершилась и DMA_EN=1, то был прочитан элемент дескриптора DMACFG в регистр DMA_CONFIG, что подразумевается как управление (перед этим управление достигается прямой записью в DMA_CONFIG).
Как показано на рис. 9-15 и 9-16, при запуске биты FLOW и NDSIZE регистра DMA_CONFIG определяют процесс настройки DMA. Значение FLOW определяет, загрузить ли текущие регистры их элементов дескриптора в памяти, тогда как биты NDSIZE детализируют, как много элементов дескриптора будет выбрано перед запуском DMA. Регистры DMA, не включенные в дескриптор, не модифицируется, и в них остаются предыдущие значения. Более того, значения сброса DMA MMR никогда не восстанавливаются, за исключением ситуации системного сброса.
Если значение FLOW задает режимы моделей малого или большого списка дескрипторов, то NEXT_DESC_PTR копируется в CURR_DESC_PTR. Затем выполняется выборка новых элементов дескриптора из памяти, индексированных через CURR_DESC_PTR, который инкрементируется после каждой выборки. Если NDPL и/или NDPH являются частью дескриптора, то эти значения загружаются в NEXT_DESC_PTR, однако выборка текущего дескриптора продолжается с использованием CURR_DESC_PTR. После завершения выборки дескриптора CURR_DESC_PTR указывает на следующее 16-битное слово в памяти после конца дескриптора.
Если ни NDPH, ни NDPL не являются частью дескриптора (т. е. режим массива дескрипторов, FLOW = 4), то не происходит перемещение из NDPH/NDPL в CURR_DESC_PTR. Вместо этого индексированная выборка дескриптора начинается со значения в CURR_DESC_PTR.
Если DMACFG не является частью дескриптора, то управляют работой предыдущие настройки DMA_CONFIG (которые были записаны доступом к MMR при настройке). Если DMACFG входит в дескриптор, то значение DMA_CONFIG, запрограммированное доступом к MMR, управляет только загрузкой первого дескриптора из памяти. Последующее функционирование DMA управляется младшим байтом дескриптора DMACFG и регистрами параметров, загруженных из дескриптора. Биты DI_EN, DI_SEL, DMA2D, WDSIZE и WNR, запрограммированные ранее доступом через MMR, будут игнорированы.
Биты состояния DMA_RUN и DFETCH в регистре IRQ_STATUS показывают статус канала DMA. После записи DMA_CONFIG биты DMA_RUN и DFETCH могут быть автоматически установлены в 1. При первой загрузке дескриптора из памяти не произойдет прерываний данных.
После вышеописанных шагов текущие регистры загружаются автоматически из соответствующих элементов дескриптора, перезаписывая свое предыдущее содержимое:
• START_ADDR копируется в CURR_ADDR • X_COUNT копируется в CURR_X_COUNT • Y_COUNT копируется в CURR_Y_COUNT
Затем начинается операция передачи данных DMA, как показано на рис. 9-16.
[Обновление DMA]
По завершении рабочего блока контролер DMA завершает передачу всех данных между памятью и блоком DMA. Если это разрешено битом DI_EN, то контроллер сигнализирует прерыванием ядру наступление этого события, и устанавливает бит DMA_DONE в регистре IRQ_STATUS канала.
Когда биты FLOW очищены, (= 0), операция останавливается очисткой бита DMA_RUN в регистре IRQ_STATUS после любой передачи данных в канальном DMA FIFO, когда данные были переданы в периферийное устройство.
Во время выборки в режимах FLOW 4, 6 и 7, контроллер DMA устанавливает в 1 бит DFETCH регистра IRQ_STATUS. В этом месте функционирование DMA зависит от того, какое значение находится в FLOW, т. е. 4, 6 или 7:
FLOW = 4 (массив дескрипторов): загружается новый дескриптор из памяти в регистры DMA через содержимое CURR_DESC_PTR, когда инкрементируется CURR_DESC_PTR. Размер дескриптора берется из поля NDSIZE регистра DMA_CONFIG до начала выборки.
FLOW = 6 (модель малого списка дескрипторов): копируется 32-битный NEXT_DESC_PTR в CURR_DESC_PTR. Далее выбирается дескриптор из памяти в регистры DMA через новое содержимое CURR_DESC_PTR, когда инкрементируется CURR_DESC_PTR. Первый элемент дескриптора загружается в новое 16-битное значение для младших 16 бит регистра NEXT_DESC_PTR, за этим элементом дескриптора идут остальные элементы. Старшие 16 бит NEXT_DESC_PTR сохраняют свое прежнее значение. Это предоставляет более короткий и эффективный дескриптор по сравнению с моделью большого списка, что подходит для приложений, которые могут разместить дескрипторы канала в пределах блока памяти размером 64 килобайта.
FLOW = 7 (модель большого списка параметров): копируется 32-битный NEXT_DESC_PTR в CURR_DESC_PTR. Далее выбирается дескриптор из памяти в регистры DMA через новое содержимое CURR_DESC_PTR, когда инкрементируется CURR_DESC_PTR. Первые элементы дескриптора загружают новое 32-битное значение для полного NEXT_DESC_PTR, далее идут остальные элементы дескриптора. Старшие 16 бит NEXT_DESC_PTR могут отличаться от своего предыдущего значения. Это дает более гибкую поддержку списка дескрипторов, которые теперь могут находиться в любой области памяти - внутренней, внешней, или даже в ROM.
Обратите внимание, что если нужно связать цепочку дескрипторов, где одна часть цепочки находится в области 64 килобайта, а вторая часть находится вне этой области, то только в одном дескрипторе нужно использовать FLOW=7 – просто потому, что в нем будет содержаться ссылка для выхода за пределы 64 килобайтной области памяти. Все остальные дескрипторы, соединенные вместе, могут использовать все те же области памяти 64 килобайта с настройкой FLOW = 6.
FLOW = 1, 4, 6 или 7 (автобуфер, массив дескрипторов, малая модель списка дескрипторов или большая модель списка дескрипторов соответственно) загружают (или перезагружают) текущие регистры:
CURR_ADDR загружается из START_ADDR, CURR_X_COUNT загружается из X_COUNT, CURR_Y_COUNT загружается из Y_COUNT
Затем очищается бит DFETCH в регистре IRQ_STATUS, после чего снова начинается передача DMA, как это показано на рис. 9-16.
[Как остановить передачи DMA]
В режиме FLOW = 0 DMA автоматически остановится после завершения рабочего блока.
Если для управления DMA используется массив дескрипторов, и если каждый дескриптор содержит элемент DMACFG, то последний элемент DMACFG должен содержать настройку FLOW = 0, чтобы корректно остановить работу канала DMA.
В режиме автобуфера (FLOW = 1), или если используется список или массив дескрипторов без элементов DMACFG, то процесс передачи DMA должен быть прерван MMR-записью в регистр DMAx_CONFIG, где значение бита DMA_EN равно 0. Запись 0 в весь регистр всегда корректно останавливает DMA (без возникновения DMA abort).
Перед новым разрешением канала убедитесь, что любая медленная операция чтения памяти, которая была начата, завершилась (например, чтение из медленной внешней памяти). Не разрешайте канал, пока любые такие чтения не завершатся.
[Программная поддержка DMA]
Есть несколько методов синхронизации и управления для использования в задачах разработки программного обеспечения, которое должно поддерживать DMA и MDMA (см. также раздел "DMA для пересылок по памяти"). Такое программное обеспечение должно быть в состоянии принять запросы на новые передачи DMA от других программных задач, интегрировать эти передачи в существующие очереди передачи, и надежно оповещать другие задачи о завершении передач.
В процессоре можно поддерживать каждое периферийное устройство DMA и поток MDMA в отдельной задаче, или поддерживать их совместно с любым другим потоком. Каждый канал DMA независим, т. е. можно управлять регистрами, ресурсами и прерываниями канала так, что схема выбора схемы управления одного канала не влияет на выбор схемы управления других каналов. Например, одно периферийное устройство может использовать связанный список дескрипторов с прерываниями, а другое периферийное устройство может одновременно использовать передачи по запросу, настраивая буфер для каждой передачи, с синхронизацией по опросу регистра IRQ_STATUS register.
[Синхронизация программы и DMA]
Критическим элементом в программной поддержке DMA является синхронизация завершения обработки буфера DMA с ходом выполнения основного алгоритма программы. Это лучше всего выполнить с использованием прерываний, путем опроса IRQ_STATUS, или комбинацией обоих этих методов. Опрос адреса или счетчика может только предоставить синхронизацию с большим допуском, сопоставимым с длинами конвейера.
Методы синхронизации на основе прерываний должны избегать ситуаций с наложением прерывания (interrupt overrun), или ошибочного вовлечения обработчика прерывания канала DMA для каждого события прерывания, что дает слишком большую задержку в обработке прерываний. Обычно дизайн системы должен гарантировать, что планируется только одно прерывание на канал (например, по окончании списка дескрипторов), или что прерывания по времени отстоят друг от друга на достаточном расстоянии, чтобы ресурсы обработки системы могли гарантировать своевременную обработку каждого прерывания. Обратите внимание, что поскольку каждый канал имеет свое собственное, отдельное прерывание, управление взаимодействием между прерываниями разных периферийных устройств значительно упрощается.
Опрос регистров CURR_ADDR, CURR_DESC_PTR или CURR_X/Y_COUNT не рекомендуется как метод точной синхронизации DMA с обработкой данных, потому что стеки DMA FIFO и DMA/память конвейеризированы. Изменение регистров текущего адреса, указателя и счетчика произойдет за несколько циклов ранее до того момента, как их значение может быть доступно в момент чтения в программе. Например, в операциях приема DMA (когда память записывается данными, поступающими от периферийного устройства) во внешнюю память, предположим что запись DMA каналом A приведет к операции открытия страницы SRAM, которая займет несколько системных тактов. Затем подсистема DMA может перейти к другой операции DMA с каналом B, который сам по себе не вводит задержку, но будет приостановлен за медленной операцией канала A. Программное обеспечение, которое отслеживает канал B не сможет безопасно определить, была ли записана ячейка памяти, на которую указывает CURR_ADDR, если он будет основываться на опросе содержимого регистра CURR_ADDR.
Опрос регистров текущего адреса, указателя и счетчика может допустить свободную синхронизацию DMA с программным обеспечением, однако в том случае, когда не имеют значения допуски, связанные с длинами конвейера DMA/память. Длина DMA FIFO для канала DMA периферийного устройства занимает 4 ячейки (либо из 8-, либо из 16-битных элементов данных, либо из 2 элементов по 32 бита) и для MDMA FIFO 8 ячеек (или 4 элемента по 32-бита данных). DMA не изменяет текущие регистры адреса/указателя/счетчика, если эти стеки FIFO заполнены не завершенной работой (включая операции чтения, которые начались, но еще пока не завершились). Далее, длина комбинированных конвейеров DMA и L1 к внутренней памяти составляет примерно шесть 8- или 16-битных элемента данных, в то время как длина конвейеров DMA и EBIU составляет примерно три элемента данных, измеренные от точки, где обновление регистра DMA становится видимым для чтения MMR до точки, где доступ DMA и ядро к памяти строго упорядочен. Если сложить длины конвейера DMA FIFO и DMA/память, оценка может быть сделана из максимального количества незавершенных операций с памятью, которые выполняются в одно и то же время (обратите внимание, что этот максимум может включать трафик конвейера DMA/memory от других каналов DMA). Например предположим, что канал DMA периферийного устройства передает рабочий блок из 100 элементов данных во внутреннюю память, и его регистр CURR_X_COUNT читается как 60 оставшихся элементов, т. е. началась как минимум обработка из 40 первых элементов. Общая длина конвейера не больше чем сумма 4 (для PDMA FIFO) плюс 6 (для конвейера DMA/память), или 10 элементов данных, так что безопасно решить, что передача DMA завершила обработку первых 40-10 = 30 элементов данных.
Для точной синхронизации программное обеспечение должно либо ждать прерывания, либо консультироваться со значением канального регистра IRQ_STATUS для подтверждений завершения, но не опрашивать текущее значение регистров адреса/указателя/счетчика. Когда система DMA выдаст прерывание или изменит бит состояния в IRQ_STATUS, это гарантирует, что последняя операция с памятью рабочего блока была выполнена, и это будет определенно видно коду ядра. Для DMA чтения памяти последнее чтение данных из памяти будет безопасно принято в стеке DMA FIFO; для DMA записи памяти, блок DMA принял подтверждение от L1 или EBIU, что данные были записаны.
Следующие примеры показывают методы синхронизации программного обеспечения с несколькими различными стилями использования DMA.
В этом случае синхронизация проста, если активность DMA периферийного устройства состоит из изолированных передач одиночных буферов. Активность DMA инициируется программно MMR-записью в управляющие регистры канала. Пользователь может выбрать один дескриптор в памяти, в этом случае программное обеспечение нуждается только в записи регистров DMA_CONFIG и NEXT_DESC_PTR. Альтернативно пользователь может выбрать запись всех регистров MMR прямо из кода программного обеспечения, и в заключении запустить DMA записью регистра DMA_CONFIG.
Этот вариант выбирается битом DI_EN в регистре DMA_CONFIG и необходимой настройкой системных контроллеров прерывания. Если использование прерывания нежелательно, программа может опрашивать завершение чтениями регистра IRQ_STATUS и проверками в нем бита DMA_RUN. Если этот бит равен 0, то передача буфера завершилась.
Данные DMA от периферийного устройства состоят из постоянного, периодически возобновляемого потока данных сигнала, может быть эффективным выбор опции автобуфера DMA (FLOW=1). Здесь происходит DMA-обмен между буфером памяти с использованием схемы кольцевой адресации, и либо 1-, либо 2-мерным индексом, с нулевым участием со стороны процессора в процедуре обработки DMA. Есть следующие опции синхронизации:
1-D, с управлением по прерыванию. Программное обеспечение получает прерывание в конце каждой передачи буфера. Критические соображения для разработки состоят в том, что программа должна иметь дело с первыми элементами в буфере до следующей передачи DMA, которая могла бы перезаписать или перечитать начальную часть буфера до того, как она была обработана программой. Эта схема может быть работоспособна, если дизайн системы гарантирует, что период повторения данных больше, чем задержка обработки в прерывании - во всех возможных обстоятельствах.
2-D, с управлением по прерыванию (двойная буферизация). Буфер DMA делится на 2 или большее количество подбуферов, и выбирается прерывание (установкой DI_SEL = 1 в регистре DMA_CONFIG) для сигнализации о завершении каждого внутреннего цикла DMA. Например, два подбуфера из 512 слов внутри буфера из 1K слов может использоваться для приема 16-битных данных от периферийного устройства следующими настройками:
START_ADDR = базовый адрес буфера DMA_CONFIG = 0x10D7 (FLOW = 1, DI_EN = 1, DI_SEL = 1, DMA2D = 1, WDSIZ = 01, WNR = 1, DMA_EN = 1) X_COUNT = 512 X_MODIFY = 2 для 16-битных данных Y_COUNT = 2 для двух подбуферов Y_MODIFY = 2, как и у X_MODIFY для находящихся друг за другом подбуферов
Таким способом может быть реализована традиционная схема двойного буферизирования в стиле "пинг-понг".
2-D, с опросом. Если затраты на прерывания нежелательны, но допустимы потери точности синхронизации по опросу регистров адреса/счетчика, может использоваться схема синхронизации 2-D с несколькими буферами. Например, если принимаемые данные должны быть обработаны пакетами по шестнадцать 32-битных элементов. Следующими настройками может быть выделен 2-D DMA буфер, где каждый из 4 подбуферов может содержать один пакет:
START_ADDR = базовый адрес буфера DMA_CONFIG = 0x101B (FLOW = 1, DI_EN = 0, DMA2D = 1, WDSIZ = 10, WNR = 1, DMA_EN = 1) X_COUNT = 16 X_MODIFY = 4 для 32-битных данных Y_COUNT = 4 для 4 подбуферов Y_MODIFY = 4, как и у X_MODIFY для находящихся друг за другом подбуферов
Синхронизация ядра может прочитать Y_COUNT, чтобы определить, какой из подбуферов в настоящее время передается, и на основе этого узнать, какой подбуфер можно обрабатывать. Например, если чтение Y_COUNT показывает значение 3, то программное обеспечение должно предположить, что передается подбуфер 3, но некоторые порции подбуфера 2 может быть еще не приняли данные. Однако программное обеспечение может безопасно обрабатывать подбуферы 1 или 0.
1-D несинхронизированный FIFO. Если дизайн системы гарантирует, что обработка данных периферийного устройства и частота DMA данных остаются устойчиво коррелируемыми, однако могут быть допущены короткие изменения задержки, то может подойти построение простого FIFO. Здесь канал DMA может быть запрограммирован на использование режима адресации с автобуфером 1-D, без опросов или прерываний.
[Структуры дескрипторов]
Дескрипторы DMA могут использоваться для перемещения данных в память или из памяти, и это не будут простые массивы 1-D или 2-D. Например, если пакет данных для передачи состоит их нескольких кусков, находящихся в разных областях памяти (заголовок в одном месте, полезная нагрузка из списка нескольких блоков памяти управляется менеджером памяти, и маленький хвост содержит контрольную сумму), то может быть подготовлен отдельный дескриптор DMA для каждой области памяти, и дескрипторы могут быть сгруппированы либо в массив, либо в список путем выбора подходящего значения поля FLOW в регистре DMA_CONFIG.
Программное обеспечение может синхронизировать процесс передачи структуры выбором оповещения по прерыванию для одного или большего количества дескрипторов. Например, программа может выбрать оповещение по прерыванию для дескриптора заголовка и для дескриптора хвоста, но не для блоков полезной нагрузки.
Важно помнить значение различных полей в элементах дескриптора для DMA_CONFIG, когда строится список или массив дескрипторов DMA. В частности, младший байт DMA_CONFIG указывает выполняемую передачу DMA для текущего дескриптора (например, с разрешением прерывания, режим 2D); старший байт DMA_CONFIG задает формат следующего дескриптора в цепочке. Поля NDSIZ и FLOW в предоставленном дескрипторе не соответствуют формату самого дескриптора; они задают ссылку на следующий дескриптор, если он есть.
С другой стороны, когда перезапускается блок DMA, значение обоих байт DMA_CONFIG, записываемых в канальный регистр DMA_CONFIG, должны соответствовать текущему дескриптору. Как минимум поля FLOW, NDSIZ, WNR и DMA_EN должны быть согласованы с текущем дескриптором; поля WDSIZ, DI_EN, DI_SEL, RESTART и DMA2D будут получены из значения DMA_CONFIG в дескрипторе, прочитанном из памяти (и значения полей, записанные изначально, будут игнорированы).
[Управление очередью дескрипторов]
Разработчик системы мог бы пожелать написать менеджер DMA, который принимает запросы DMA от другого программного обеспечения. Программа менеджера DMA не знает заранее, когда будут получены новые запросы или что могли бы содержать эти запросы. Она могла бы управлять этими передачами с использованием кольцевого связанного списка дескрипторов DMA, где каждое поле NDPTR дескриптора указывает на следующий, и последний дескриптор указывает на первый.
Код, который использует записи в эти дескрипторы, мог бы использовать кольцевые режимы адресации процессора (регистры Ix, Lx, Mx и Bx), так чтобы не надо было бы использовать сравнение или условные инструкции для управления кольцевой структурой. В этом случае поля NDPTR каждого дескриптора могли бы быть записаны даже один раз при стартовой настройке, и пропущены каждый раз, когда дескрипторы записываются новым содержимым.
Рекомендуется использовать прерывание для синхронизации очереди дескрипторов. Очередь дескрипторов организована так, что как минимум последний допустимый дескриптор всегда программируется для генерации прерывания.
Вот два основных метода для управления очередью с использованием прерываний:
1. Прерывание на каждом дескрипторе. 2. Использование прерываний по минимуму - только на последнем дескрипторе.
В этой системе программа менеджера DMA синхронизируется с блоком DMA, разрешая прерывание в каждом дескрипторе. Этот метод должен использоваться только если система может гарантировать, что каждое прерывание будет обработано отдельно (не произойдет перекрытия прерываний, interrupt overrun).
Чтобы поддержать синхронизацию очереди дескрипторов, программное обеспечение вне прерывания отслеживает счетчик дескрипторов, добавленных в очередь, тогда как обработчик прерывания отслеживает счетчик завершенных дескрипторов, удаленных из очереди. Счетчики равны только кода канал DMA встал на паузу после обработки всех дескрипторов.
При каждом новом принятом рабочем запросе программа менеджера DMA инициализирует новый дескриптор, заботясь о записи значения DMA_CONFIG, где поле FLOW равно 0. Затем программа сравнивает счетчики дескрипторов, чтобы определить, работает канал DMA или нет. Если канал DMA стоит на паузе (счетчики равны), то программное обеспечение инкрементирует свой счетчик и затем запускает блок DMA записью нового значения DMA_CONFIG дескриптора в канальный регистр DMA_CONFIG.
Если счетчики не равны, то вместо этого программа модифицирует значение DMA_CONFIG в предпоследнем дескрипторе так, что его верхняя половина (FLOW и NDSIZ) теперь описывает новый поставленный в очередь дескриптор. Эта операция не повредит канал DMA, если остальная часть структуры дескриптора была инициализирована заранее. Однако нужно синхронизировать программу с DMA, чтобы корректно определить, старое или новое значение DMA_CONFIG было прочитано каналом DMA.
Эта операция синхронизации должна быть выполнена в ISR. Сначала, когда возникло прерывание, обработчик должен прочитать регистр IRQ_STATUS канала. Если бит DMA_RUN установлен, то канал перешел к обработке другого дескриптора, и обработчик может увеличить свой счетчик и выйти. Если бит DMA_RUN не установлен, то этот канал стоит на паузе - либо потому, что нет больше дескрипторов для обработки, либо потому что последний дескриптор был поставлен в очередь слишком поздно (т. е. модификация элемента DMA_CONFIG предпоследнего дескриптора была после того, как элемент был прочитан блоком DMA). В этом случае обработчик должен записать значение DMA_CONFIG, соответствующее последнему дескриптору для канального регистра DMA_CONFIG, инкрементировать счетчик завершенных дескрипторов и выйти.
И снова, система может сбойнуть, если задержки в обработке системного прерывания достаточно большие, чтобы привести к тому, что любое из прерываний канала DMA было отброшено. ISR, способный к безопасной синхронизации нескольких прерываний дескриптора должен быть сложным, и должен делать несколько MMR-обращений, чтобы гарантировать устойчивую работу. В такой системе предпочтительнее использовать метод с одним прерыванием (см. далее).
В этой системе может быть только одно событие прерывания DMA на целую очередь. ISR для DMA в этой системе может быть также очень коротким. Очередь дескрипторов организована в "активной" и "ожидающей" порциях, где прерывания разрешены только в последнем дескрипторе каждой порции.
Когда обрабатывается каждый новый запрос DMA, код программы вне прерывания заполняет содержимое нового дескриптора и добавляет его к ожидающей порции очереди. Слово DMA_CONFIG дескриптора должно иметь значение FLOW равное 0. Если будет принято больше одного запроса до срабатывания прерывания завершения очереди DMA, код вне прерывания должен ставить в очередь более поздние дескрипторы, формируя этим ожидающую часть очереди, которая разъединена с активной частью очереди, которую обрабатывает блок DMA. Другими словами, все активные дескрипторы, кроме последнего, содержат значения FLOW >= 4 с отключенным прерыванием, в то время как последний активный дескриптор содержит FLOW = 0, и в нем разрешено прерывание установкой бита DI_EN в 1. Также все ожидающие дескрипторы, кроме последнего, содержат значения FLOW >=4 с отключенными прерываниями, в то время как последний ожидающий дескриптор содержит FLOW = 0 и бит разрешения прерывания, установленный в 1. Это гарантирует, что блок DMA может автоматически обработать всю активную очередь, и выдать одно прерывание. Также такое выравнивание упрощает запуск ожидающей очереди в обработчике прерывания путем одиночной записи регистра DMA_CONFIG.
После постановки в очередь нового ожидающего дескриптора код вне прерывания должен оставить сообщение для своего ISR в почтовом ящике, где содержится желаемое значение DMA_CONFIG, которое должно быть использовано для запуска первого из очереди ожидающих дескрипторов (или 0, чтобы показать, что нет ожидающих дескрипторов).
Критичным является то, что программа напрямую не модифицирует содержимое очереди активных дескрипторов, как только блоком DMA запущена их обработка, если не приняты тщательные меры по синхронизации. В самой прямой реализации очереди дескрипторов программа менеджера DMA никогда не будет модифицировать дескрипторы в активной очереди; вместо этого менеджер ждет, пока не сработает прерывание, сигнализирующее о завершении обработки активной очереди DMA.
Когда получено прерывание завершения очереди DMA, ISR прочитает почтовый ящик, в котором программа вне прерывания записала значение. Далее ISR запишет это прочитанное значение в регистр DMA_CONFIG канала DMA. Эта одиночная запись в регистр перезапустит очередь, эффективно преобразуя этим ожидающую очередь в активную очередь. Обработчик прерывания затем должен передать сообщение обратно коду вне прерывания, показывая этим, что размещение последнего дескриптора принято в активной очереди. С другой стороны, если ISR прочитает почтовый ящик и найдет в нем значение DMA_CONFIG равное нулю, что показывает, что больше не нужно выполнять работу, то ISR должен передать соответствующее сообщение (например, ноль) обратно в код вне прерывания, что показывает, что очередь остановлена. Этот простой ISR может быть закодирован очень малым количеством инструкций.
Программа вне прерывания, которая принимает новые рабочие запросы DMA, нуждается в синхронизации активации новой работы с ISR. Если очередь остановлена, т. е. если почтовый ящик из ISR равен 0, то код вне прерывания отвечает за запуск очереди (записью значения первого дескриптора DMA_CONFIG в регистр DMA_CONFIG канала). Однако если очередь не остановлена, то код вне прерывания не должен записывать регистр DMA_CONFIG (что вызвало бы ошибку DMA), и вместо этого он должен ставить дескриптор в ожидающую очередь, и обновлять свой почтовый ящик, который предназначен для чтения из ISR.
Примеры использования DMA, поддерживаемые гибкими дескрипторами, могут быть устроены следующим образом:
• Одиночный линейный буфер, который останавливается при завершении (FLOW = stop mode). • Линейный буфер с шагом больше единицы (X_MODIFY > 1). • Кольцевой, автообновляемый буфер с прерыванием при каждом заполнении буфера. • Подобный буфер, когда прерывание срабатывает на части буфера (например 1/2, 1/4, т. е. 2D DMA). • 1D DMA, с использованием набора идентичных буферов по принципу ping-pong, определенных как связанное кольцо из дескрипторов в 3 слова, каждый содержит { указатель связи, 32-битный адрес }. • 1D DMA, с использованием связанного списка дескрипторов из 5 слов { указатель связи, 32-битный адрес, длина, конфигурация } (стиль ADSP-2191). • 2D DMA, с использованием массива дескрипторов из 1 слова, где указан только базовый адрес в пределах общей страницы данных. • 2D DMA, с использованием связанного списка дескрипторов из 9 слов, где указана самая полная информация для запуска передачи DMA.
[DMA для пересылок по памяти]
В этом разделе описаны контроллеры памяти DMA (MDMA), которые предоставляют функцию передач DMA память-память между различными областями памяти (включая L1 и внешние синхронные / асинхронные устройства памяти).
Каждый контроллер MDMA содержит DMA FIFO, этот FIFO состоит из 8 слов по 16 бит каждое. Блок FIFO используется для передачи данных между L1 либо шиной EAB. Обычно используется передача между внешней памятью и внутренней памятью. Также поддерживается DMA из Boot ROM на шину EAB. FIFO может использоваться для хранения данных, переданных между двумя областями L1, или между двумя областями внешней памяти.
Каждый контроллер DMA предоставляет 4 канала MDMA:
• 2 канала источника (для чтения из памяти) • 2 канала назначения (для записи в память)
Есть также 2 контроллера DMA, каждый содержит 2 потока. Между контроллерами DMA есть свой арбитраж, с которым у контроллера 0 есть преимущество перед контроллером 1. В каждом из контроллеров DMA два потока имеют приоритеты, как это показано в таблице 9-11.
Таблица 9-11. Приоритеты потоков контроллера DMA.
Самый высокий приоритет
MDMA stream D0 (поток 0 памяти DMA, для места назначения)
MDMA stream S0 (поток 0 памяти DMA, для источника)
MDMA stream D1 (поток 1 памяти DMA, для места назначения)
Самый низкий приоритет
MDMA stream D1 (поток 1 памяти DMA, для источника)
Поскольку меньшие числовые значения приоритета приоритетнее (прошу прощения за тавтологию), чем большие, поток 0 памяти DMA имеет приоритет перед потоком 1 памяти DMA, за исключением использования планирования типа round-robin. Обратите внимание, что недопустимо программировать поток источника для записи памяти и также недопустимо программировать поток назначения для чтения памяти.
Каналы поддерживают 8-, 16- и 32-разрядные передачи памяти DMA, однако оба окончания передачи MDMA должны быть запрограммированы на одинаковый размер слова. Другими словами, передача MDMA не выполняет упаковку или распаковку данных; каждое чтение соответствует одной записи. Обоим окончаниям MDMA FIFO для имеющегося потока приоритет предоставляется одновременно. Каждая пара совместно использует 16-битный FIFO глубиной в 8 слов. Подсистема DMA источника заполняет FIFO, в то время как подсистема DMA назначения его опустошает. Глубина стека FIFO позволяет пересекающиеся быстрые пакетные передачи шин EAB и DAB, значительно увеличивая полосу передач блока между внутренней и внешней памятью. Нужны два отдельных блока дескрипторов для предоставления рабочих параметров для каждой пары MDMA, один для канала источника, и один для канала назначения.
Из-за того, что подсистемы источника и назначения DMA используют один общий буфер FIFO, блок дескрипторов должен быть сконфигурирован так, чтобы был одинаковый размер данных. Можно иметь разную смесь дескрипторов на обоих концах, пока общее количество на обоих концах остается одинаковым.
Для запуска операции передачи MDMA записываются регистры MMR для потоков источника и назначения, каждый примерно так же, как и DMA периферийных устройств. Ограничение только в том, что регистр DMA_CONFIG для потока источника должен быть записан перед регистром DMA_CONFIG потока назначения. Когда записан регистр DMA_CONFIG потока назначения, запускается операция MDMA после задержки в 3 такта SCLK.
Сначала, если был выбран любой поток MDMA для использования дескрипторов, дескрипторы выбираются из памяти. При этом первыми выбираются дескрипторы потока назначения. Затем, после задержки в 4 такта SCLK после того, как последнее слово дескриптора было выбрано из памяти (или обычно 8 тактов SCLK после выборки последнего слова дескриптора из-за конвейерной обработки памяти), поток источника MDMA начинает выбирать данные из буфера источника. Эти данные размещаются в 8-ячеечном стеке FIFO потока MDMA, и затем после задержки в 2 такта SCLK поток назначения MDMA начинает записывать данные в буфер памяти назначения.
[Полоса пропускания MDMA]
Если у областей памяти источника и назначения разные области памяти (одна внутренняя, другая внешняя), то передачи внутренней и внешней памяти обычно происходят одновременно и непрерывно, занимая 100% полосы пропускания шины внутреннего и внешнего интерфейсов. На эту производительность влияет соотношение тактовых частот ядра и системы. При соотношении около 2.5:1 синхронизация и задержки конвейера дадут результат по меньшей загрузке шины в домене системной тактовой частоты. При соотношении тактовых частот 2:1 обычно DMA работает на 2/3 от тактовой частоты системы. На более высоких тактовых частотах сохраняется полная полоса пропускания.
Если источник и назначение находятся в одной и той же области памяти (оба во внутренней, или оба во внешней, то поток MDMA) обычно выбирает с упреждением данные источника в FIFO, и затем автоматически передает все доступные данные из FIFO в буфер назначения. Длина пакета зависит от трафика, и равна 3 плюс задержку памяти для DMA в тактах SCLK (обычно 7 для внутренних передач и 6 для внешних передач).
[Приоритет MDMA и планирование (шедулинг)]
Все операции MDMA имеют приоритет ниже, чем любая операция DMA с периферийным устройством. Таким образом, MDMA эффективно используют всю оставшуюся полосу памяти, которая не задействована трафиком DMA периферийных устройств.
Если используются 2 потока MDMA (S0-D0 и S1-D1), пользователь может выбрать выделение полосы либо по фиксированному приоритету потока, либо по схеме round-robin. Это выбирается программированием поля MDMA_ROUND_ROBIN_PERIOD в регистре DMAx_TCPER (см. "Приоритезация и управление трафиком").
Если это поле установлено в 0, то MDMA планируется по фиксированному приоритету. Поток MDMA 0 имеет приоритет перед потоком MDMA 1 всякий раз, когда поток 0 готов выполнить передачи. Поскольку поток MDMA обычно может передавать данные в каждом доступном цикле, то это приведет к приостановке трафика канала 1 MDMA до момента, когда канал 0 MDMA завершит свои операции. Эта схема могла бы подойти системам, где короткие по времени, но чувствительные к задержкам буферы данных должны быть переданы немедленно, прерывания длинные, низкоприоритетные фоновые передачи.
Если поле MDMA_ROUND_ROBIN_PERIOD установлено в ненулевое значение в диапазоне 1 < = P < = 31, то тогда используется метод планирования round robin. Два потока MDMA получают доступ к шине поочередно, передавая пакеты до P данных. Это могло бы использоваться в системах, где 2 процесса передачи должны существовать вместе, каждый с гарантированной частью полосы пропускания. Например, один поток может быть запрограммирован для передач из внутренней во внешнюю память, в то время как другой запрограммирован для передач и внешней памяти во внутреннюю, и каждый должен занимать примерно одинаковую полосу данных.
При функционировании по принципу round robin, выбор потока MDMA в любой момент времени может быть в состоянии free (свободно) или locked (заблокировано). Изначально выбирается free. На любом доступном free-цикле для MDMA (когда нет доступа со стороны PDMA, который имеет приоритет), если оба потока MDMA запрашивают доступ, то поток с более высоким приоритетом получает доступ (в случае конфликта это будет поток 0), и этот выбор потока переходит в состояние locked. Поле счетчика MDMA_ROUND_ROBIN_COUNT в регистре DMAx_TCCNT загружается периодом P из MDMA_ROUND_ROBIN_PERIOD, и начинается передача MDMA. Счетчик декрементируется с каждой передачей данных (с каждым словом данных, записанным в память). После передачи, соответствующей счетчику 1 выбор потока MDMA автоматически переходит к другому потоку с нулевыми затратами, и счетчик MDMA_ROUND_ROBIN_COUNT перезагружается значением периода P из MDMA_ROUND_ROBIN_PERIOD. В этом цикле если другой поток MDMA готов передавать, выбор потока становится в состояние locked для нового потока MDMA. Если другой поток не готов выполнять передачу, то не будет выполнена передача, и в следующем цикле выбор потока разблокируется, и он снова переходит в состояние free.
Если шедулинг round robin используется только на одном активном потоке MDMA, то будет вставлен 1 цикл ожидания для каждых P циклов данных MDMA, что незначительно снижает полосу на коэффициент деления 1/(P+1). Однако если используются оба потока MDMA, то DMA памяти может непрерывно работать с нулевыми дополнительными затратами полосы при чередовании потоков (кроме циклов, обычно связанных с реверсированием направления чтения/записи памяти). Путем выбора разных значений периода P, который определяет, как часто потоки MDMA должны чередоваться, может поддерживаться максимальная эффективность передач для каждого потока.
[Ошибки контроллера DMA (Abort)]
Каждый из двух контроллеров DMA может генерировать ошибку контроллера DMA.
Ошибки DMA контроллера (abort) детектируются модулем канала DMA в случаях, описанных ниже. Когда происходит ошибка DMA, канал немедленно останавливается (DMA_RUN переходит в 0) и любые предварительно выбранные данные отбрасываются. Дополнительно выставляется прерывание DMA_ERROR.
Есть только одно прерывание DMA_ERROR для всего контроллера DMA, которое выставляется всякий раз, когда любой из каналов детектировал событие ошибки.
ISR для DMA_ERROR должен для каждого канала выполнять следующие действия:
• Прочитать регистр IRQSTAT каждого канала, чтобы найти канал, у которого установлен бит DMA_ERR (бит 1). • Очистить проблему с этим каналом, например, исправить значения регистров. • Очистить бит IRQ (записать IRQSTAT значением, где бит 1 = 1).
Аппаратурой DMA детектируются следующие события ошибки.
• Произошла недопустимая запись регистра, когда канал был запущен и работает. Можно записывать только регистры DMA_CONFIG и IRQ_STATUS, когда DMA_RUN = 1. • При доступе к памяти произошла ошибка выравнивания адреса. Например, в регистре DMA_CONFIG поле WDSIZE = 1 (16 бит), но в адресе самый младший бит не равен 0, или WDSIZE = 2 (32 бита), но два самых младших бита адреса не равны 00. • На передаче произошел переход от одной области памяти к другой (от внутренней к внешней или наоборот). • Произошла ошибка доступа к памяти. Либо была сделана попытка доступа к внутреннему адресу, который не соответствует ячейке памяти, или эта ячейка занята под кэш, или доступ к внешней памяти привел к ошибке (об этом сигнализирует внешний интерфейс с памятью).
В результате произойдет прерывание DMA abort, и регистр конфигурации содержит следующие недопустимые значения.
• Некорректное значение WDSIZE (==11) • Бит 15 не установлен в 0 • Некорректное значение FLOW (FLOW=2, 3 или 5) • Значение NDSIZE не соответствует FLOW. См. таблицу 9-12.
Таблица 9-12. Допустимые значения для NDSIZE.
FLOW
NDSIZE
Примечание
0
0
1
0
4
0 < NDSIZE < = 7
Массив дескрипторов, без выборки указателя дескриптора
6
0 < NDSIZE < = 8
Список дескрипторов, выбран малый указатель дескриптора
7
0 < NDSIZE < = 9
Список дескрипторов, выбран большой указатель дескриптора
Некоторые запрещенные ситуации не детектируются аппаратурой DMA. Не произойдет прерывание DMA abort в следующих ситуациях.
• Бит направления в регистре DMA_CONFIG (WNR) не соответствует с направлением привязанного периферийного устройства. • Бит направления в регистре DMA_CONFIG не соответствует направлению канала MDMA. • Размер слова в регистре DMA_CONFIG (WDSIZE) не поддерживается привязанным периферийным устройством. • Не равны размеры слова в DMA_CONFIG в источнике и назначении потоков MDMA. • В цепочке буферов есть буферы данных, которые находятся не в одной и той же области памяти. • Для 2D DMA в ситуации X_COUNT = 1.
[Быстродействие DMA: приоритезация и оптимизация]
Система DMA разработана для предоставления максимума пропускной способности на канал, и максимальной утилизации внутренних шин, в приспособлении к собственным задержкам доступа к памяти.
Ключевая особенность архитектуры DMA состоит в разделении активности шины периферийных устройств DMA (шина DAB) от активности шин между DMA и памятью (шины DCB и DEB). Каждый канал периферийного устройства имеет свой собственный стек FIFO данных, лежащий между шиной DAB и шинами памяти. Эти стеки FIFO автоматически с упреждением захватывают данные из памяти для передачи и буферизируют данные для последующих записей в память. Это позволяет периферийному устройству выполнить передачу DMA с очень малой задержкой в сравнении с общей задержкой конвейеризированного доступа к памяти, позволяя получить максимально возможную скорость повторений (полосу пропускания) каждого канала DMA.
В результате каналы DMA периферийных устройств передают с максимальной скоростью одно 16-битное слово на 2 такта системной шины на канал в обоих направлениях. Каналы MDMA передают с максимальной скоростью одно 16-битное слово на 1 системный такт, на каждый канал.
Весь трафик канала DMA агрегируется:
• Передачи между периферийными устройствами и блоком DMA осуществляются с максимальной скоростью в одну 16-битную передачу на такт системы. • Передачи между блоком DMA и внутренней памятью (L1) осуществляются с максимальной скоростью одна 16-битная передача на такт системной частоты. • Передачи между блоком DMA и внешней памятью осуществляются с максимальной скоростью одна 16-битная передача на такт системной частоты.
Вот то, что ограничивает реальную производительность:
• Доступы к внутренней или внешней памяти с конфликтом с доступом со стороны ядра к той же самой памяти. Это может привести к задержкам, например, для доступа к тому же самому банку L1 для открытия/закрытия страниц SDRAM, или для заполнения строк кэша. • Каждое изменение направления от RX к TX на шине DAB приводит к задержке на 1 такт. • Изменения направления на шине DCB (например запись, за которой следует чтение) для того же банка внутренней памяти могут вставлять задержки. • Изменения направления (например запись, за которой следует чтение) на шине DEB к внешней памяти может дать задержку на несколько циклов. • Доступы к MMR регистрам, кроме DMAx_CONFIG, DMAx_IRQ_STATUSF или DMAx_PERIPHERAL_MAP будут приостанавливать всю активность DMA на 1 такт на переданное 16-битное слово. Напротив, доступ к регистрам управления/состояния не приводят к приостановкам или циклам ожидания. • Чтения из регистров, кроме регистров управления/состояния будут использовать один цикл ожидания шины PAB, задерживая ядро на несколько тактов ядра. • Выборка дескриптора потребляет один цикл памяти DMA на чтение 16-битного слова из памяти, но это не задерживает передачи по шине DAB. • Инициализация канала DMA приостанавливает активность DMA на один такт. Это происходит, когда DMA_EN меняет состояние с 0 на 1, или когда бит RESTART в регистре DMAx_CONFIG установлен в 1.
Некоторые из этих факторов могут быть минимизированы правильным дизайном приложения. Часто можно структурировать программу так, чтобы избежать конфликтов между внутренней и внешней памятью путем тщательного выделения буферов данных в пределах банков и страниц, и планированием низкой активности кэша на критических операциях DMA. Больше того, нежелательные доступы к MMR могут быть минимизированы, особенно с использованием дескрипторов или автобуферирования.
Потеря эффективности, вызванная чрезмерными изменениями направления (перегрузкой), может быть минимизирована функциями управления трафиком процессора, что описано в следующем разделе.
[Приоритезация и управление трафиком]
Каналам DMA обычно предоставляют обслуживание строго в соответствии с их приоритетом. Приоритет канал просто соответствует его номеру канала, где меньшим числам предоставляется больше приоритета. Таким образом, периферийное устройство с более интенсивным трафиком или с минимальной требуемой задержкой должно быть назначено на канал с меньшим номером (у кого больше приоритет) с использованием регистров DMAx_PERIPHERAL_MAP. Потоки DMA памяти (MDMA) всегда получают приоритет меньше, чем периферийные устройства, однако так как они постоянно запрашивают обслуживание, то гарантируется, что слоты времени, неиспользуемые DMA периферийных устройств, будут задействованы для передач MDMA. По умолчанию, когда больше чем один поток MDMA разрешен и готов, дается доступ только потоку MDMA с более высоким приоритетом. Однако если желательно, чтобы потоки MDMA делили между собой доступную полосу, то может быть запрограммирован MDMA_ROUND_ROBIN_PERIOD, чтобы потоки выбирались по очереди на фиксированное количество передач.
В DMA процессора есть 2 полностью раздельных, но одновременно работающих процесса приоритезации: приоритезация шины DAB и приоритезация шины памяти (DCB и DEB). Периферийные устройства запрашивают DMA через шину DAB, и конкурируют друг с другом за циклы шины DAB те устройства, чьи данные стеков FIFO готовы к передаче. Подобным образом, но по отдельности, конкурируют друг с другом за шины памяти те каналы, чьи стеки FIFO требуют обслуживания памяти (предвыборка или запросы на запись). Потоки MDMA конкурируют за доступ к памяти как узел, и доступ может быть предоставлен и источнику, и назначению в том случае, если их перемещения в памяти не конфликтуют. Таким способом передачи из внутренней памяти во внешнюю или из внешней памяти во внутреннюю могут проходить на полной системной тактовой частоте (SCLK). Примеры конфликта памяти включают одновременный доступ к той же самой области памяти и попытки одновременной выборки дескрипторов. Может произойти специальная обработка, если периферийное устройство запрашивает DMA, но его FIFO не готово (например, пустой передающий FIFO или заполненный приемный FIFO). Дополнительную информацию см. в разделе "Срочные (Urgent) передачи DMA".
Управление трафиком - важный аспект для оптимизации использования ресурсов DMA. Управление трафиком это способ влиять на то, как часто может меняться направление передачи на шинах данных, с автоматическим группированием друг с другом передач с одним направлением. Блок DMA предоставляет механизм управления трафиком через регистры DMACx_TC_PER и DMACx_TC_CNT. Этот механизм выполняет оптимизацию без вмешательства процессора в реальном времени, и без необходимости программировать пакеты передачи в рабочие потоки узла DMA. Трафик может независимо управляться для каждой из 3 шин (DAB, DCB и DEB) простыми счетчиками. Дополнительно может управляться чередование передач между потоками MDMA через поля MDMA_ROUND_ROBIN_COUNT регистра DMACx_TC_CNT.
С использованием возможности управления трафиком система DMA дает предпочтительные передачи данных по DAB или шинам памяти в том же направлении чтение/запись, что и предыдущая передача, пока либо не истечет таймаут счетчика, либо пока трафик не остановится, либо пока не поменяется само направление.
Когда счетчик трафика достигает нуля, то выбор меняется на противоположное направление потока. Эти предпочтения работают как если бы приоритет противоположного направления был уменьшен на 16.
Например, если каналы 3 и 5 запрашивали доступ к DAB, но канал с меньшим приоритетом 5 проходит с трафиком "в том же направлении", и канал с более высоким приоритетом проходит с "противоположным" трафиком, то эффективный приоритет канала 3 станет 19, и тогда канал 5 получит преимущественный доступ вместо канала 3. Если на следующем цикле передачи DAB запрашивают только те каналы, у которых весь трафик "обратный" (предположим, каналы 3 and 6), то их эффективные приоритеты станут 19 и 22. Будет дан доступ одному из каналов (каналу 3), даже при том, что его направление противоположно текущему потоку. С таким принципом не тратятся впустую циклы шины, только на необходимые задержки, связанные с необходимым переключением направления шины.
Такой тип управления трафиком работает за счет компромисса в задержке, чтобы улучшить утилизацию (эффективность). Более высокие таймауты трафика могут увеличить время, когда каждый запрос ожидает разрешения на обработку, однако часто значительно повышает пропускную возможность высоконагруженных систем, часто выше 90%.
Чтобы запретить приоритезацию DMA по предпочтениям, запрограммируйте регистр DMACx_TC_PER в значение 0x0000.
Поле MDMA_ROUND_ROBIN_COUNT показывает текущий счетчик передач, оставшийся в периоде round robin передачи MDMA. Оно инициируется значением MDMA_ROUND_ROBIN_PERIOD всякий раз, когда записывается DMACx_TC_PER, всякий раз, когда дается доступ другому потоку MDMA, или всякий раз, когда каждый поток MDMA приостанавливается, затем считает вниз до 0 с каждой передачей MDMA transfer. Когда этот счетчик переходит от 1 к 0, выбирается следующий допустимый поток MDMA.
Поле DAB_TRAFFIC_COUNT показывает текущий счетчик циклов, оставшийся в периоде трафика DAB. Оно инициируется значением DAB_TRAFFIC_PERIOD всякий раз, когда записывается DMACx_TC_PER, или всякий раз, когда шина DAB меняет направление или приостанавливается, затем считает вниз от DAB_TRAFFIC_PERIOD до 0 с каждым тактом системы (исключая приостановки DMA). Пока этот счетчик не обнулился, предпочтительнее считается то же самое направление DAB. Когда этот счетчик переходит от 1 к 0, то предпочтительным становится противоположное направление, в результате чего направление передачи данных может поменяться. Когда этот счетчик равен 0, и происходит доступ к шине DAB, счетчик перезагружается из DAB_TRAFFIC_PERIOD для начала нового пакета.
Поле DEB_TRAFFIC_COUNT показывает текущий счетчик циклов, сколько осталось периода трафика DEB. Он инициируется значением DEB_TRAFFIC_PERIOD всякий раз, когда записывается DMACx_TC_PER, или всякий раз, когда меняется направление шины DEB или она приостанавливает работу, и затем считает вниз от DEB_TRAFFIC_PERIOD до 0 с каждым тактом системы (за исключением приостановок DMA). Пока этот счетчик не обнулился, считается предпочтительным то же самое направление по шине DEB. Когда этот счетчик переходит от 1 к 0, то считается предпочтительным противоположное направление, что в результате может привести к смене направления передачи. Когда этот счетчик равен 0, и происходит доступ к шине DEB, счетчик перезагружается из DEB_TRAFFIC_PERIOD для начала нового пакета.
Поле DCB_TRAFFIC_COUNT показывает текущий счетчик циклов, оставшийся в периоде трафика DCB. Он инициируется значением DCB_TRAFFIC_PERIOD всякий раз, когда записывается DMACx_TC_PER, или всякий раз, когда меняется направление шины DCB или она приостанавливает работу, и затем считает от DCB_TRAFFIC_PERIOD до 0 с каждым тактом системы (за исключением приостановок DMA). Пока этот счетчик не обнулился, считается предпочтительным то же самое направление по шине DCB. Когда этот счетчик переходит от 1 к 0, то считается предпочтительным противоположное направление, что в результате может привести к смене направления передачи. Когда этот счетчик равен 0, и происходит доступ к шине DCB, счетчик перезагружается из DCB_TRAFFIC_PERIOD для начала нового пакета.
Рис. 9-17. DMA Traffic Control Counter Period Register (DMACx_TC_PER).
MDMA_ROUND_ROBIN_PERIOD[4:0]. Максимальная длина пакетов MDMA round-robin. Если не 0, то любой поток MDMA, который получил доступ, может передать до этого количества передач, после чего передает доступ другим потокам MDMA.
DAB_TRAFFIC_PERIOD[2:0]. 000 - нет группирования передач шины DAB. Другое значение - задается предпочтительная длина однонаправленных передач по шине DAB между DMA и периферийным устройством.
DEB_TRAFFIC_PERIOD[3:0]. 000 - нет группирования передач шины DEB. Другое значение - задается предпочтительная длина однонаправленных передач по шине DEB между DMA и внешней памятью.
DCB_TRAFFIC_PERIOD[3:0]. 000 - нет группирования передач шины DCB. Другое значение - задается предпочтительная длина однонаправленных передач по шине DCB между DMA и внутренней памятью L1.
Рис. 9-18. DMA Traffic Control Counter Register (DMACx_TC_CNT).
MDMA_ROUND_ROBIN_COUNT[4:0]. Текущее значение счетчика оставшихся передач в периоде MDMA round robin.
DAB_TRAFFIC_COUNT[2:0]. Текущий счетчик оставшихся циклов до завершения периода трафика DAB.
DEB_TRAFFIC_COUNT[3:0]. Текущий счетчик оставшихся циклов до завершения периода трафика DEB.
DCB_TRAFFIC_COUNT[3:0]. Текущий счетчик оставшихся циклов до завершения периода трафика DCB.
[Срочные (Urgent) передачи DMA]
Обычно передачи DMA для имеющейся периферии происходят с регулярными интервалами. Чаще всего чем короче интервал, тем должен быть назначен выше приоритет этому периферийному устройству. Если средняя полоса всех периферийных устройств не слишком велика как часть от общей доступной полосы, то тогда должны быть обработаны все запросы от периферийных устройств, как это требуется.
Иногда мгновенный трафик DMA может превысить доступную полосу, что приводит к перегрузке. Это может произойти, если L1 или внешняя память временно приостановлена, возможно для переключения страницы SDRAM или заполнения строки кэша. Перегрузка может также произойти, если один или большее количество каналов DMA инициируют поток запросов, возможно для выборок дескрипторов или для заполнения FIFO в DMA или периферийном устройстве.
Если перегрузка сохраняется, то менее приоритетные DMA периферийных устройств могут "голодать" в ожидании передачи данных. Даже при низком приоритет периферийного устройства, если необходимая передача не произойдет до окончания определенного интервала времени, может произойти отказ системы. Чтобы минимизировать такую возможность, блок DMA детектирует периферийные устройства, для которых потребность в данных стала срочной (urgent), и предпочтительно дает им обслуживание с самым высоким приоритетом. Запрос канала DMA к службе памяти определяется как urgent, если оба стека FIFO канала не готовы к передаче по шине DAB (т. е. передающий стек FIFO пуст, или принимающий стек FIFO заполнен), и периферийное устройство выставляет свою линию запроса DMA.
Выборка дескриптора может быть urgent, если она необходима для инициирования или продолжения работы цепочки блока DMA для периферийного устройства, обработка которого чрезмерно задерживается. Запросы DMA от канала MDMA никогда не становятся urgent.
Когда один или большее количество каналов DMA показывают срочный запрос к памяти, происходят 2 события:
1. У всех не-urgent запросов к памяти понижается приоритет на 32, что гарантирует, что только urgent-запросам будет дан доступ. Urgent-запросы конкурируют друг с другом, и если запросов больше одного, то выбирается предпочтение запросу по тому же самому направлению.
2. Полученная передача в памяти помечается для ускоренной обработки в целевой системе памяти (L1 или внешняя), так что все предыдущие незавершенные передачи уступают доступ к этой системе памяти. Это может привести к нескольким доступам к внешней памяти со стороны ядра, чтобы мог быть размещен urgent-запрос периферийного устройства.
Преференциальная обработка urgent-передач DMA осуществляются полностью автоматически. От пользователя не требуется никакого управления для работы этой функции.