48250
[i] Начальные сведения о DMA
Дата последнего изменения: 27.02.2024 16:37:48
Материал из настоящей статьи, относящийся к микросхемам К1986ВЕ92QI и К1986ВЕ1QI, распространяется в том числе на микроконтроллеры К1986ВЕ92FI, К1986ВЕ92F1I, К1986ВЕ94GI и К1986ВЕ1FI, К1986ВЕ1GI
DMA (Direct Memory Access) - специализированный контроллер, предназначенный для пересылки данных без использования ядра микроконтроллера. Использование DMA позволяет не тратить процессорное время на отслеживание готовности данных в периферийных блоках и последующую их пересылку. Ядро инициализирует DMA и переходит к выполнению других задач, пока не возникнет прерывание от DMA, сигнализирующее о том, что заданное количество данных было передано.
Как и в любой функции копирования данных для запуска обмена с использованием DMA необходимы следующие параметры:
- адреса источника и приёмника;
- количество передаваемых данных (цикл DMA);
- размерность передаваемых данных;
- инкремент адресов источника и приёмника после передачи каждого значения.
Пересылаемые данные могут быть:
- 8-разрядные (байт);
- 16-разрядные (полуслово);
- 32-разрядные (слово).
1. Каналы DMA
Для выполнения нескольких «параллельных» задач по пересылке данных в контроллере DMA реализовано 32 независимых канала. Одновременно активен только один канал. Каждый канал настраивается отдельно на выполнение конкретной задачи. Таким образом, возможно одновременно запустить и копирование массивов, и считывание данных из АЦП, и запись данных в ЦАП и многое другое. Все это будет работать как бы "параллельно".Для реализации совместной работы нескольких каналов в контроллере DMA предусмотрен механизм смены текущего канала при исполнении цикла обмена - арбитраж. Активный канал при арбитраже меняется не тогда, когда текущий канал полностью закончил свой цикл обмена, т.е. выполнит все заданные передачи, а внутри цикла. Для этого в настройках канала используется параметр R_power - количество передач до процедуры арбитража. Значение этого параметра является степенью 2, т.е. возможны 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 и 1024 непрерывные передачи, которые не могут прерваться процедурой арбитража.
Например, необходимо передать 100 значений из массива в массив. Если выставить параметр R_power = 6 (26 = 64), то канал передаст 64-е значения и разрешит провести арбитраж. Далее:
- если нет запросов от более приоритетных каналов, то текущий канал закончит передачу оставшихся 36-х значений. После этого канал разрешит арбитраж и вызовет аппаратное прерывание от DMA - завершение цикла DMA;
- если есть запросы от более приоритетных каналов, то DMA обработает эти приоритетные каналы. Канал, настроенный на передачу 100 значений, выставит запрос на обработку и будет ожидать арбитраж, в ходе которого DMA вернется к исполнению канала и будут переданы оставшиеся 36 значений.
1.1 Источники и приемники данных
В отличие от простого цикла копирования, DMA может не просто выполнять пересылку данных, а делать это по определённому событию.Например, можно настроить, чтобы одно слово данных копировалось из адреса источника по событию готовности АЦП. Тогда, если адресом источника выбрать регистр "ADC_RESULT", то DMA может без участия ядра считывать готовые значения из АЦП и складывать их, например, в массив. Затем, когда DMA закончит передавать заданное количество данных (цикл DMA), будет сгенерировано прерывание от DMA, и ядро может обработать весь массив полученных данных от АЦП. Отличие от обычного копирования здесь в том, что измерение АЦП занимает некоторое количество времени, поэтому считывать результат с АЦП нужно только по событию готовности.
Аналогично, для контроллера ЦАП, адресом назначения DMA выбирается регистр "DAC_DATA", а событием, по которому происходит передача слова, выбирается событие таймера CNT == ARR (запрос к DMA по событию совпадения счётчика CNT и основания счёта ARR). Тогда с помощью DMA получится равномерный (по таймеру) вывод сигнала в ЦАП. Форма сигнала для вывода в ЦАП в данном случае обычно прописывается массивом, который выбирается в качестве источника данных для DMA. Размер массива указывается в параметре - "количество передаваемых данных". По окончанию передачи массива возникает прерывание от DMA - окончание цикла DMA.
1.2 Запросы к DMA от периферийных устройств
Передача одного значения называется одиночной передачей, а передача 2R_power данных - блочной передачей.Периферийные блоки могут запрашивать блочные и одиночные передачи, используя внутренние сигналы dma_req[С] и dma_sreq[С]. С - номер канала, т то есть каждый канал имеет отдельные сигналы от периферии.
dma_req[C] - запрос на блочную передачу DMA. Когда от периферии приходит запрос dma_req[С], контроллер DMA выполняет 2R_power передач, далее контроллер DMA ожидает новый запрос dma_req[С] или dma_sreq[С] от периферии. Если в цикле DMA осталось выполнить меньше количество передач, чем 2R_power, то выполняется оставшееся количество передач, чтобы закончить цикл DMA.
dma_sreq[C] - запрос на одиночную передачу DMA. Когда от периферии приходит запрос dma_sreq, контроллер DMA выполняет 1 передачу, далее контроллер DMA ожидает новый запрос dma_sreq[С] от периферии.
Обработку одиночных запросов от dma_sreq[C] можно отключить/включить - для этого используются регистры CHNL_USEBURST_SET / CHNL_USEBURST_CLR. При выключенной обработке одиночных запросов от dma_sreq[C] будут обрабатываться только запросы от dma_req[C].
В МК К1986ВЕ92QI, К1986ВЕ1QI, К1986ВК234, К1986ВК025 и MDR1206FI сигналы dma_req[С] и dma_sreq[С] от определенных периферийных контроллеров жестко привязаны к каналам DMA. Например, подключение сигналов запросов dma_req[С] и dma_sreq[С] от периферии к каналам DMA для микроконтроллера К1986ВЕ92QI приведено в таблице 1.
Таблица 1 – Распределение запросов от периферийных контроллеров по каналам DMA
Номер канала | Источник dma_sreq | Источник dma_req |
0 | UART1_TX | UART1_TX |
1 | UART1_RX | UART1_RX |
2 | UART2_TX | UART2_TX |
3 | UART2_RX | UART2_RX |
4 | SSP1_TX | SSP1_TX |
5 | SSP1_RX | SSP1_RX |
6 | SSP2_RX | SSP2_TX |
7 | SSP2_RX | SSP2_RX |
8 | ADC1_EC | - |
9 | ADC2_EC | - |
10 | TIMER1 | - |
11 | TIMER2 | - |
12 | TIMER3 | - |
13 | - | - |
… | - | - |
31 | - | - |
Каналы 13 - 31 являются программными, поэтому для установления запроса на выполнение передачи должен быть установлен соответствующий каналу бит в регистре CHNL_SW_REQUEST. Необходимо отметить, что запрос на передачу аппаратного канала также можно выставить программный путём с помощью регистра CHNL_SW_REQUEST.
У каждого канала есть свой приоритет, и он определяется индексом канала. 0-ой канал имеет самый высокий приоритет, далее приоритет следует в порядке убывания. Если посмотреть распределение каналов DMA для К1986ВЕ92QI, то самый приоритетный - это UART1_TX. Приоритет по умолчанию можно увеличить, задав каналу высокий приоритет. Для задания высокого приоритета используется регистр CHNL_PRIORITY_SET, в который необходимо записать "1" в бит по индексу канала. Для возвращения приоритета в обычное состояние (низкий приоритет), используется регистр CHNL_PRIORITY_CLR - запись "1" в бит по индексу канала. Чтение регистра CHNL_PRIORITY_SET возвращает текущее состояние приоритета канала: 0 - приоритет по умолчанию (низкий приоритет), 1 – высокий приоритет.
В МК К1986ВК01GI сигналы запросов dma_sreq[C] и dma_req[C] от периферийных устройств могут мультиплексироваться между каналами, что позволяет гибко настроить приоритет работы DMA с периферийными контроллерами.
1.3 Арбитраж каналов DMA
На рисунке 1 показана структурная схема работы каналов DMA с осуществлением арбитража.Рисунок 1 – Структурная схема работы каналов DMA с осуществлением арбитража
Пояснения к рисунку 1:
- всего есть 32 канала DMA;
- приоритет каналов убывает от 0-го канала к 31-му;
- каналы передают данные блоками по 2R_power, между которыми осуществляется арбитраж - смена канала;
- DMA передача - это передача одного слова данных заданной размерности;
- цикл DMA - это общее количество данных, которое необходимо передать. Задается параметром N_minus_1;
- для передачи следующей порции данных необходим запрос на обслуживание канала DMA - DMA Request. По этой причине более приоритетный канал С-1 отдает управление каналу С – так как запрос к С-1 еще не установлен к моменту арбитража. Поэтому исполнение переходит к каналу С, и только на следующем арбитраже канал С-1 передаст оставшееся слово;
- под DMA Request подразумевается запрос по сигналам sreq[C], req[C] или программный запрос;
- каждый канал управляется своей структурой, состоящей из 4-х 32-битных слов;
- последнее слово резервное и не используется;
- два слова в структуре задают адрес источника и приемника данных;
- все настройки обмена задаются в слове Control:
- общее количество передач задается полем N_minus_1 при запуске. Далее это значение используется для вычисления текущего адреса передаваемых данных и уменьшается контроллером DMA при передаче каждого слова;
- младшие 3 бита Control задают режим работы канала. По окончанию цикла DMA это поле сбрасывается контроллером DMA в 0, что означает режим STOP - канал работу закончил.
1.4 Управляющие данные канала DMA
Каждый канал управляется своей структурой, которая состоит из 4-х 32-разрядных слов:- Source End Pointer - конечный адрес источника данных;
- Destination End Pointer - конечный адрес приемника данных;
- Control - параметры обмена;
- Reserved - не используется.
Таблица 2 – Описание полей слова Control
Биты | Поле | Значения | Описание |
31..30 | dst_inc |
b00 - байт b01 - полуслово b10 - слово b11 - ноль/нет инкремента |
Инкремент адреса приемника |
29..28 | dst_size | Размерность данных приемника, всегда равна src_size! | |
27..26 | src_inc | Инкремент адреса источника | |
25..24 | src_size | Размерность данных источника | |
23..21 | dst_prot_ctrl |
b001 - Привилегированый доступ b010 - Буферизируется b100 - Кэшируется |
Флаги привилегий приемника |
20..18 | src_prot_ctrl | Флаги привилегий источника | |
17..14 | R_power | b000 - 1 передача | Передач до арбитража |
b001 - 2 передачи | |||
b010 - 4 передачи | |||
… | |||
b1010 - 1024 передачи | |||
13..4 | N_minus_1 | 0 - 1024 | Передач в цикле DMA |
3 | next_useburst | b0 - sreq и req |
Переопределение CHNL_USEBURST_SET[C] в режиме с изменением конфигурации |
b1 - req | |||
2..0 | cycle_ctrl | b000 - STOP | Режим работы |
b001 - Основной | |||
b010 - Авто-запрос | |||
b011 - Пинг-понг | |||
b100/b101 - Реконфигурация с памятью | |||
b110/b111 - Реконфигурация с периферией |
Контроллер DMA вычисляет адрес текущей передачи из конечного адреса по следующей формуле:
Addr = data_end_ptr - (n_minus_1 << src_inc), где src_inc - инкремент данных источника
Размерность данных приемника всегда должна быть равна размерности данных источника: src_size == dst_size
Управляющие структуры каналов должны быть расположены в памяти друг за другом и представлять собой массив структур. Когда DMA будет обрабатывать канал, например, 5-й, то он будет считывать и изменять 5-ю структуру в массиве. Указатель на начало массива структур должен быть прописан в регистре CTRL_BASE_PTR.При использовании SPL этот массив структур уже определен в файле «MDR32F9Qx_dma.c» как массив структур DMA_ControlTable[64]. Массив DMA_ControlTable[64] имеет вдвое большую длину - 64 структуры, а каналов всего 32. Вторая половина (с 32-го индекса) является альтернативным массивом структур, и адрес этого массива можно считать в регистре ALT_CTRL_BASE_PTR. Регистр ALT_CTRL_BASE_PTR доступен только на чтение и устанавливается автоматически при задании регистра CTRL_BASE_PTR.
Альтернативная структура может использоваться, например, в режиме работы ping-pong. В этом режиме по окончании цикла основной структуры DMA переключится на исполнение альтернативной структуры, затем, по окончании цикла альтернативной структуры DMA снова перейдёт к выполнению основной структуры и так далее. Получается, что один и тот же канал работает то с одной управляющей структурой, то с другой. По окончании цикла каждой структуры будет вызвано прерывание, и пока DMA выполняет обмен по текущей структуре, необходимо заново проинициализировать следующую структуру. Такой подход позволяет организовать непрерывную пересылку данных с помощью DMA с минимальными затратами процессорного времени.
Режим ping-pong может пригодиться, например, для вывода сигнала в ЦАП. Пока DMA выводит сигнал по основной структуре, ядро высчитывает и заполняет данные сигнала для альтернативной структуры. По завершении цикла DMA переключится на альтернативную структуру, и ядро может заполнять сигнал для основной структуры и так далее.
2. Регистры блока DMA
Полное описание регистров представлено в спецификации. В данной статье будут рассмотрены только основные моменты работы с регистрами DMA. Особое внимание следует уделить параметрам ReadOnly (RO) и WriteOnly (WO). Далее по тексту ниже, где атрибуты не указаны, доступ разрешен и на запись, и на чтение - Read-Write (RW).Доступ к большинству регистров блока DMA реализованы с помощью дополнительных регистров с приставками SET и CLR, которые позволяют осуществлять установку и сброс отдельных бит в основном регистре. Запись нулей в регистры SET и CLR не влияют на состояние регистра.
- Регистр SET: - RW, при записи 1-ниц устанавливаются биты в основном регистре;
- Регистр CLR: - RO, при записи 1-ниц сбрасываются биты в основном регистре.
Таблица 3 - Перечень регистров контроллера DMA
Название регистра | Описание |
STATUS | Отражает состояние контроллера, RO |
CFG | Бит Master_enable - включает работу блока DMA. Но весь регистр WO, при чтении возвращается 0. |
CTRL_BASE_PTR | Задает указатель на массив первичных и вторичных управляющих структур каналов. |
ALT_CTRL_BASE_PTR | Возвращает указатель на массив альтернативных управляющих структур каналов, RO. Значение высчитывается из CTRL_BASE_PTR и количества каналов в блоке DMA. |
WAITONREG_STATUS | Состояние сигналов запроса на обработку к каналам DMA, RO |
CHNL_SW_REQUEST | Запись 1 в бит канала вызывает программный запрос на обработку канала, WO. |
CHNL_USEBURST (S/C) | Бит канала: 0 - обработка запросов sreq и req, 1 - только req. |
CHNL_REQ_MASK (S/C) | Бит канала: 0 - работа канала разрешена, 1 - работа канала запрещена. |
CHNL_ENABLE (S/C) | Запись 1 в бит канала запускает работу канала. После окончания цикла, бит аппаратно сбрасывается в 0. |
CHNL_PRI_ALT (S/C) | Бит канала: 0 - канал использует первичную структуру, 1 - альтернативную. Можно указать вручную. В режимах работы, использующих обе структуры, бит переключается аппаратно. |
CHNL_PRIORITY (S/C) | Бит канала: 0 - обычный приоритет, 1 - повышенный. |
ERR_CLR | Бит 0: Возвращает наличие ошибки при работе DMA. Запись 1 сбрасывает ошибку. |
3. Пример программного копирования данных в FIFO контроллера Ethernet
В данном пункте приводится пример работы с DMA из библиотечного файла «MDR32FxQI_eth.c». В данном примере пакет данных с помощью DMA записывается в FIFO контроллера Ethernet.3.1 Инициализация DMA
Перед использованием DMA необходимо его предварительно настроить. Функция предварительной инициализации DMA приведена в фрагменте кода 1. В данной функции задаются только основные параметры DMA. Далее, при вызове функции обмена параметры управляющей структуры перенастраиваются. Для пересылки данных используется 15 канал DMA - DMA_Channel_SW2, запросы выставляются программным путём с помощью регистра CHNL_SW_REQUEST.Фрагмент кода 1 – Функция предварительной инициализации контроллера DMA
#define DMA_Channel_SW2 ((uint8_t)(15))
void ETH_DMAPrepare(void)
{
// Локальная управляющая структура канала DMA
DMA_CtrlDataInitTypeDef DMA_PriCtrlStr;
// Структура инициализации DMA
DMA_ChannelInitTypeDef DMA_InitStr;
// Подача тактирования на DMA
RST_CLK_PCLKcmd(RST_CLK_PCLK_DMA, ENABLE);
// Сброс настроек DMA
DMA_DeInit();
// Инициализация управляющей структуры по умолчанию
DMA_StructInit(&DMA_InitStr);
// Настройка DMA - выбор основной управляющей структуры
DMA_InitStr.DMA_PriCtrlData = &DMA_PriCtrlStr;
DMA_InitStr.DMA_Priority = DMA_Priority_High;
DMA_InitStr.DMA_UseBurst = DMA_BurstClear;
DMA_InitStr.DMA_SelectDataStructure = DMA_CTRL_DATA_PRIMARY;
// Инициализация DMA
DMA_Init(DMA_Channel_SW2, &DMA_InitStr);
}
3.2 Функция записи в FIFO через DMA
Адрес FIFO (адрес назначения), как и адрес массива данных (источника), задается вызывающим кодом вместе с количеством передаваемых данных. Функция записи в FIFO контроллера Ethernet приведена во фрагменте кода 2, далее приведена дополнительная информация к коду:- запись в FIFO осуществляется всегда по одному адресу, поэтому для приемника не задается смещение адреса;
- для обмена выбран канал 15;
- для того чтобы передать весь пакет максимально быстро повышается приоритет данного канала и значение R_power выбирается максимальное - арбитраж через 1024 передачи. Размер же пакета может быть меньше данного значения, но не больше (контролируется вызывающим кодом);
- выставляется режим Авто-запроса для автоматического формирования запросов передачи данных к DMA;
- прерывание от DMA не используется, поскольку так организован вызывающий код.
#define DMA_Channel_SW2 ((uint8_t)(15))
// Доступ к глобальному массиву управляющих данных каналов
extern DMA_CtrlDataTypeDef DMA_ControlTable[DMA_Channels_Number * (1 + DMA_AlternateData)];
void ETH_DMAFrameTx(uint32_t * DstBuf, uint32_t BufferSize, uint32_t * SrcBuf)
{
__IO uint32_t * ptrControltable;
uint32_t tmpval;
// Высший приоритет
MDR_DMA->CHNL_PRIORITY_SET |= 1 << DMA_Channel_SW2;
// Настройка управляющей структуры
DMA_ControlTable[DMA_Channel_SW2].DMA_SourceEndAddr = (uint32_t)SrcBuf + 4*(BufferSize-1);
DMA_ControlTable[DMA_Channel_SW2].DMA_DestEndAddr = (uint32_t)DstBuf;
DMA_ControlTable[DMA_Channel_SW2].DMA_Control = DMA_DestIncNo | DMA_SourceIncWord |
DMA_MemoryDataSize_Word |
DMA_Mode_AutoRequest |
DMA_Transfers_1024 |
((BufferSize - 1) << 4);
// Разрешение работы канала - DMA ожидает запрос для запуска
DMA_Cmd(DMA_Channel_SW2, ENABLE); // MDR_DMA->CHNL_ENABLE_SET = (1 << DMA_Channel);
// Подача DMA Request - старт цикла DMA
DMA_Request(DMA_Channel_SW2); // MDR_DMA->CHNL_SW_REQUEST = (1 << DMA_Channel);
// Получение указателя на поле Control канала
ptrControltable = (uint32_t *) &DMA_ControlTable[DMA_Channel_SW2].DMA_Control;
// Ожидание окончания цикла
while( 1 )
{
tmpval = (*ptrControltable) & 0x7;
if(tmpval == 0) // режим STOP?
break;
}
// Выключение канала DMA
DMA_Cmd(DMA_Channel_SW2, DISABLE); // MDR_DMA->CHNL_ENABLE_CLR = (1 << DMA_Channel);
}
4. Работа с DMA в К1986ВЕ1QI
Следует обратить внимание, что в микроконтроллере К1986ВЕ1QI не вся память ОЗУ доступна для контроллера DMA, а только AHB-Lite SRAM 16KB, начинающаяся с адреса 0x2010_0000 (спецификация, раздел «Организация памяти»). Это необходимо учитывать при выборе источника и приёмника, а также при размещении массива управляющих структур.В SPL массив управляющих структур DMA_ControlTable[] объявлен с атрибутом __attribute__((section("EXECUTABLE_MEMORY_SECTION"))), позволяющим разместить данный массив в определённую область памяти МК. Данный атрибут необходимо указать в конфигурационном файле компоновщика для соответствующего региона памяти.
Например, в среде Keil конфигурационный файл компоновщика (scatter file) автоматически создается при сборке проекта, если в опциях проекта установлена галочка «Linker -> Use Memory Layout from Target Dialog». Конфигурационный файл создается в поддиректории «Objects» и называется именем проекта с расширением *.sct. Для работы с DMA необходимо убрать галочку с опции «Use Memory Layout from Target Dialog», чтобы данный файл не обновлялся при каждой сборке (рисунок 2), а также в сам файл дописать строку с указанием атрибута массива управляющих структур для региона памяти ОЗУ AHB-Lite SRAM 16KB, как показано в фрагменте кода 3.
Фрагмент кода 3 – Размещение структуры с атрибутом "EXECUTABLE_MEMORY_SECTION" в регион памяти IRAM2
RW_IRAM2 0x20100000 0x00004000 {
*.o (EXECUTABLE_MEMORY_SECTION)
.ANY (+RW +ZI)
}
Рисунок 2 - Настройка конфигурационного файла компоновщика в опциях проектаПодробная информация про конфигурационный файл компоновщика приведена на официальном сайте Keil, а также в статье «[i] Расположение функций в ОЗУ, программирование EEPROM».
5. Первоначальная инициализация DMA для работы с прерываниями
После включения МК некоторые периферийные блоки могут выставить запросы к DMA. При этом, если канал DMA, к которому установлен запрос, будет выключен, то контроллер DMA оповестит об этом ядро путём выставления запроса прерывания (спецификация, правила осуществления DMA передач при «запрещенных» каналах, правило №19). Таким образом DMA показывает запросы от периферии, которые поступают на выключенные каналы. Если данный механизм оповещения не требуется в проекте, то его можно отключить. Для этого необходимо:- запретить обработку запросов по dma_req[C] и dma_sreq[C] во всех каналах DMA, кроме требуемых, установив соответствующие биты в регистре «CHNL_REQ_MASK_SET»;
- разрешить работу всех каналов DMA, установив все биты в регистре «CHNL_ENABLE_SET»;
- разрешить работу контроллера DMA путём установки бита «master_enable» в регистре «DMA_CFG»;
- сбросить отложенное прерывание от DMA с помощью вызова функции NVIC_ClearPendingIRQ(DMA_IRQn).
Теги
Работа с DMA