STM Урок 156. LL. DMA. MEM2MEM. Часть 1



На прошлом занятии мы с вами начали плотно изучать DMA в контроллере STM32F1 и на практике, применяя возможности библиотеки HAL, нам удалось скопировать некоторое количество информации из одной области памяти в другую (MEM2MEM).

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

Скорее всего, полностью аппаратную реализацию периферии DMA мы в данном уроке также не изучим, потому что акцент будет сделан именно на режим передачи информации из одну область памяти в другую — (MEM2MEM).

В документации Reference Manual на контроллеры серии F1 нет подробного описания данного режима, но зато он вполне неплохо описан в аналогичной документации на контроллеры серии STM32F4, с которыми мы также с вами уже много работали, причём различия в режиме MEM2MEM между ними принципиального нет, так как он тоже здесь доступен в любом канале любого из двух контроллера DMA. Вот диаграмма, показывающая процесс передачи данных в режиме MEM2MEM

 

 

Различие с нашим контроллером STM32F1 будет только в наименовании регистров, так как у нас нет потоков, есть только каналы. Но принцип тот же.

Передача идёт через буфер, причём адрес источника заносится в регистр адреса периферии, в нашем случае будет DMA_CPARx, где x — номер используемого канала. Он используется здесь, видимо, потому, что нет двух раздельных регистров для адресов памяти. А вот для хранения адреса приёмника используется регистр адресации памяти, в нашем случае — DMA_CMARx, где x — также номер используемого канала.

Теперь, когда принцип передачи информации через DMA в режиме MEM2MEM немного понятен, можно приступить к изучению регистров и назначения их битов.

Начнём с регистра конфигурирования

 

 

Данный регистр существует в каждом канале двух контроллеров DMA.

В регистре все используемые биты работают как на чтение, так и на запись.

 

 

Назначение их следующее:

MEM2MEM (Memory to memory mode): регистр включения режима memory to memory

0 — режим MEM2MEM отключен

1 — режим MEM2MEM включен

Если режим отключен, то режим будет устанавливаться с помощью настройки направления передачи.

PL[1:0] (Channel priority level): битовое поле настройки приоритета канала

00 — Low (низкий)

01 — Medium (средний)

10 — High (высокий)

11 — Very high (очень высокий).

MSIZE[1:0] (Memory size): битовое поле настройки размерности данных в памяти (в случае использования режима MEM2MEM в приёмнике данных)

00 — 8 бит

01 — 16 бит

10 — 32 бита

11 — зарезервировано.

PSIZE[1:0] (Peripheral size): битовое поле настройки размерности данных в периферии (в случае использования режима MEM2MEM в источнике данных)

00 — 8 бит

01 — 16 бит

10 — 32 бита

11 — зарезервировано.

MINC (Memory increment mode): бит включения автоинкрементирования адреса памяти (в случае использования режима MEM2MEM адреса приёмника)

0 — автоинкрементирование отключено

1 — автоинкрементирование включено.

PINC (Peripheral increment mode): бит включения автоинкрементирования адреса периферии (в случае использования режима MEM2MEM адреса источника)

0 — автоинкрементирование отключено

1 — автоинкрементирование включено.

CIRC (Circular mode): бит включения циклического режима

0 — циклический режим отключен

1 — циклический режим включен.

DIR (Data transfer direction): бит настройки направления передачи данных

0 — передача данных из периферии в память (данное направление также включаем при использовании режима MEM2MEM)

1 — передача данных из памяти в периферию.

TEIE (Transfer error interrupt enable): бит включения прерываний в случае возникновения ошибки передачи данных

0 — прерывания отключены

1 — прерывания включены.

HTIE (Half transfer interrupt enable): бит включения прерываний по окончанию передачи половины передаваемых данных

0 — прерывания отключены

1 — прерывания включены.

TCIE (Transfer complete interrupt enable): бит включения прерываний по окончанию передачи всех данных

0 — прерывания отключены

1 — прерывания включены.

EN (Channel enable): бит включения канала

0 — канал отключен

1 — канал включен.

Следующий регистр — регистр состояния флагов прерываний

 

 

Биты данного регистра распределены по 4 на каждый канал, а так как каналов у нас максимум 7, то хватило одного регистра на все каналы.

В регистре все биты работают только на чтение. Флаги всех прерываний устанавливаются аппаратно, а сбрасываются программно в регистре DMA_IFCR.

Их назначение:

TEIFx (Channel x transfer error flag (x = 1 ..7)): флаг прерывания в случае возникновения ошибки передачи данных в канале

0 — ошибки передачи данных не происходило

1 — произошла ошибка передачи данных.

HTIFx (Channel x half transfer flag (x = 1 ..7)): флаг прерывания по окончанию передачи половины передаваемых данных

0 — окончания передачи половины передаваемых данных не происходило

1 — произошла передача половины передаваемых данных.

TCIFx (Channel x transfer complete flag (x = 1 ..7)): флаг прерывания по окончанию передачи всех данных

0 — окончания передачи данных не происходило

1 — произошло окончание передачи данных.

GIFx (Channel x global interrupt flag (x = 1 ..7)): флаг глобального прерывания

0 — событий TE, HT или TC не происходило

1 — произошло событие TE, HT или TC.

 

 

Следующий регистр — регистр сброса флагов прерываний

 

 

Подобно предыдущему регистру, биты данного регистра также распределены по 4 на каждый канал.

Все биты регистра доступны только на запись.

Их назначение:

CTEIFx (Channel x transfer error clear (x = 1 ..7)): сброс флага прерывания TEIF в регистре DMA_ISR

0 — не используется

1 — сброс флага.

CHTIFx (Channel x half transfer clear (x = 1 ..7)): сброс флага прерывания HTIF в регистре DMA_ISR

0 — не используется

1 — сброс флага.

CTCIFx (Channel x transfer complete clear (x = 1 ..7)): сброс флага прерывания TCIF в регистре DMA_ISR

0 — не используется

1 — сброс флага.

CGIFx (Channel x global interrupt clear (x = 1 ..7)): сброс флагов прерывания GIF, TEIF, HTIF и TCIF в регистре DMA_ISR

0 — не используется

1 — сброс флагов.

Следующий регистр — регистр количества передаваемых единиц информации (размерность единицы настраивается битовыми полями MSIZE и PSIZE регистра DMA_CCR)

 

 

Такой регистр существует для каждого канала. Все 16 используемых бит в нём содержат число, содержащее количество передаваемых единиц информации.

Следующий регистр — регистр адреса периферии для передачи данных (в случае использования режима MEM2MEM адреса источника)

 

 

Если битовое поле PSIZE регистра CCR соответствующего канала настроено на передачу 16-битных данных (полуслов), то бит 0 данного регистра DMA_CPARx игнорируется и значение адреса выравнивается до полуслова, а если PSIZE настроено на передачу 32-битных данных (слов), то игнорируются биты 0 и 1 и значение адреса уже выравнивается до слова.

Следующий регистр — регистр адреса памяти для передачи данных (в случае использования режима MEM2MEM адреса приёмника)

 

 

Если битовое поле MSIZE регистра CCR соответствующего канала настроено на передачу 16-битных данных (полуслов), то бит 0 данного регистра DMA_CMARx игнорируется и значение адреса выравнивается до полуслова, а если PSIZE настроено на передачу 32-битных данных (слов), то игнорируются биты 0 и 1 и значение адреса уже выравнивается до слова.

Вот, в принципе, и всё по регистрам DMA. Можно смело приступать к проекту.

Проект создадим из проекта урока 154, предназначенного для ведущего устройства с именем LL_SPI_MASTER и назовём его LL_DMA_MEM_TO_MEM.

Откроем проект в Cube MX и отключим сначала SPI1

 

 

Затем отключим ножку PA4

 

Включим в канале DMA1 канал 1 в режиме MEM2MEM и настроим размерность 16 бит, а также оставим инкрементирование адресов и приёмника и источника

 

 

Включим глобальные прерывания на канал DMA в NVIC

 

 

Включим использование библиотеки LL на DMA

 

 

Сгенерируем проект, откроем его в Keil, настроим программатор на автоперезагрузку, отключим оптимизацию и подключим к дереву проекту файл MAX7219 для индикатора.

В следующей части нашего урока мы мы напишем код, в котором скопируем данные из одного участка памяти в другой при помощи DMA.

 

 

Предыдущий урок Программирование МК STM32 Следующая часть

 

 

Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6

Программатор недорогой можно купить здесь ST-Link V2

Индикатор светодиодный семиразрядный с драйвером MAX7219

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM LL. DMA. MEM2MEM

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*