Микроконтроллеры Atxmega [1], в отличие от своих предшественников ATmega, имеют гораздо более высокую производительность, что обеспечивается не только повышенной тактовой частотой, но и более развитой внутренней архитектурой, в которой присутствует ряд новых узлов. Один из них - контроллер прямого доступа к памяти (ПДП), с помощью которого организуется прямая пересылка информации между ячейками памяти данных микроконтроллера, минуя процессор. Роль последнего сводится лишь к настройке контроллера ПДП и управлению его работой.
Рациональное использование прямого доступа к памяти (ПДП) позволяет существенно ускорить работу программ, в ходе выполнения которых необходимы регулярные пересылки массивов данных между модулями микроконтроллера. Ускорение происходит как за счёт большой скорости пересылки, так и за счёт освобождения от участия в ней процессора, который в это время может выполнять другие фрагменты программы.
Прежде чем рассматривать сам контроллер ПДП, необходимо остановиться на некоторых особенностях архитектуры микроконтроллера, которые необходимо знать для эффективного использования ПДП. Элементы любой вычислительной системы можно разделить на активные и пассивные. К активным относят те элементы, которые могут генерировать обращения к другим элементам системы. Типичный пример - процессор. В микроконтроллерах семейства ATmega это единственный активный элемент. В семействе ATxmega в их число вошёл и контроллер ПДП.
Одновременное функционирование в системе нескольких активных элементов может приводить к конфликтам между ними при одновременном обращении к одному и тому же пассивному элементу. Доступные для обращений со стороны нескольких активных элементов пассивные элементы принято именовать общими ресурсами вычислительной системы. Типичный пример - память, к которой активные элементы регулярно обращаются и при этом нередко конфликтуют между собой. Если не предпринять никаких мер, то результат конфликта один - остановка работы обоих конфликтующих элементов и обычно вычислительного процесса в целом.
Меры, принимаемые, чтобы избежать подобных последствий, могут быть аппаратными и программными. Аппаратные меры сводятся к оптимизации архитектуры вычислительной системы. Например, запоминающие устройства, при обращении к которым наиболее часто возникают конфликты, делают многоканальными, разделяя общий массив памяти на отдельные банки и обеспечивая независимый доступ к каждому из них. Предоставление каждому активному элементу своего банка памяти позволяет резко уменьшить возможное число конфликтов, однако полностью не избавляет от них.
Чтобы последствия конфликтов не стали фатальными для вычислительного процесса, шину доступа к общему ресурсу оборудуют арбитром шины, в который заложена шкала приоритетов всех возможных обращений к этому ресурсу. При одновременном обращении нескольких активных элементов арбитр первым допустит к ресурсу элемент с самым высоким приоритетом, затем с меньшим и так далее. Иначе говоря, выстроит очередь обращений.
Программные меры предотвращения конфликтов сводятся к такой организации вычислительного процесса, при которой продолжительность занятия общего ресурса каждым активным элементом минимальна, в результате чего вероятность конфликта предельно снижена. Эффективность программных мер полностью зависит от мастерства программиста, от его знания не только средств программирования, но и особенностей архитектуры той системы, для которой он разрабатывает программу. Применительно к рассматриваемым микроконтроллерам это, в первую очередь, знание структур адресного пространства и шины памяти данных.
Следует напомнить, что в микроконтроллерах имеется память двух видов: память программ (часто называемая FLASH-памятью) и память данных. Память программ не относится к общим ресурсам, так как доступна только процессору. Поэтому в дальнейшем будем рассматривать только память данных, доступную как процессору, так и контроллеру ПДП.
Память данных микроконтроллера состоит из однобайтовых ячеек. Все 16 Мбайт адресного пространства этой памяти разбиты на четыре области:
0000Н-0FFFH - память ввода-вывода, в которой находятся программнодоступные регистры всех модулей микроконтроллера, в том числе процессора;
1000Н-1FFFH - энергонезависимая память (EEPROM). У разных микроконтроллеров её объём неодинаков, поэтому реальное значение верхней границы этой области следует брать из описания конкретного микроконтроллера;
2000H и выше - внутренняя и внешняя память данных с произвольным доступом. Верхняя граница внутренней памяти этого типа (ОЗУ) зависит от её объёма в конкретном микроконтроллере. Например, микроконтроллер ATxmega64 имеет ОЗУ объёмом 4 Кбайт, следовательно, его верхняя граница - 2FFFH. Через порты к микроконтроллеру может быть подключена внешняя память данных, начальный адрес которой на единицу больше максимального адреса внутреннего ОЗУ, а конечный может достигать 0FFFFFFH.
Для полного использования адресного пространства памяти данных работающее с ней активное устройство (например, контроллер ПДП) должно формировать 24-разрядные коды адреса. В качестве внешней памяти могут выступать не только микросхемы памяти, но и различные периферийные устройства с параллельным интерфейсом, допускающие обращение к ним как к ячейкам памяти (например, индикаторы).
Шина памяти данных микроконтроллера устроена так, что позволяет организовать одновременное обращение активных устройств к разным областям памяти данных. Это даёт возможность организовать параллельную бесконфликтную работу с ними процессора и контроллера ПДП. На рис. 1 показан пример такой работы. Здесь процессор читает содержимое EEPROM, аконтроллер ПДП в то же самое время пересылает информацию из внешней памяти во внутреннее ОЗУ Если процессор и контроллер ПДП одновременно обратятся к одной области памяти, то возникнет конфликт, который должен разрешить арбитр шины по приоритетному принципу. Естественно, в такой ситуации программа исполняется медленнее, чем при бесконфликтной работе.
Рис. 1. Блок-схема алгоритма работы программы микроконтроллера
Применение контроллера ПДП тесно связано и с системой прерываний микроконтроллера, работой которой управляет контроллер прерываний. В рассматриваемых микроконтроллерах эта система не претерпела революционных изменений по отношению к микроконтроллерам предыдущих поколений. Помимо существенного увеличения числа возможных источников запросов прерывания, принципиально новым стало только то, что контроллер прерываний стал многоуровневым. Он позволяет разделить запросы прерываний от различных модулей микроконтроллера на группы по уровню важности (высокому, среднему и низкому) и раздельно управлять обработкой этих групп.
Контроллер ПДП имеет четыре автономных канала пересылки информации. Для каждого канала должны быть установлены индивидуальные значения параметров, определяющих схему пересылки: источник запуска, систему адресации, уровень приоритета. Это позволяет пересылать до четырёх информационных потоков параллельно.
Пересылка массива информации по каналу ПДП называется транзакцией. Максимальный размер транзакции - 16 Мбайт. Она выполняется блоками объёмом до 64 Кбайт, а передача блока, в свою очередь, может происходить пакетами из одного, двух, четырёх или восьми байтов. При блочной схеме пересылки контроллер ПДП захватывает шину на всё время передачи блока, при пакетной - только на время передачи пакета. Столь сложная структура транзакции позволяет с минимальными простоями обслуживать обращения процессора и контроллера ПДП к одной и той же области памяти.
Поясним это на примере. Пусть в ходе выполнения некоторой программы контроллер ПДП должен переслать последовательность результатов работы АЦП в ОЗУ. Причём АЦП выдаёт новый однобайтовый результат каждую микросекунду, а всего нужно переслать 2000 результатов (байтов). Если эту транзакцию осуществить одним блоком такого объёма, то контроллер ПДП, получив доступ к ОЗУ, не освободит его до завершения передачи всего блока. Поэтому в течение 2000 мкс ОЗУ будет недоступно процессору.
Это неразумно, поскольку между пересылками по каналу ПДП двух смежных байтов проходит 1 мкс, а операция записи байта в ОЗУ выполняется за один машинный такт (около 0,03 мкс при тактовой частоте 32 МГц). Другими словами, лишь 3 % времени транзакции ОЗУ будет занято операциями записи, а в течение оставшихся 97 % будет бесполезно простаивать, оставаясь недоступным для процессора. Ему придётся ждать завершения транзакции. Понятно, что это сильно замедлит работу программы.
В рассматриваемом случае целесообразно настроить контроллер ПДП на пакетную передачу, задав размер пакета 1 байт. Контроллер ПДП станет захватывать шину каждую микросекунду всего на один машинный такт. В оставшуюся часть микросекунды ОЗУ будет свободно для обращений к нему процессора.
Настраивают контроллер ПДП записью необходимых кодов в его управляющие регистры. Рассмотрим основные из них. При описании регистров и их разрядов использованы их оригинальные мнемонические имена на английском языке. Многие системы программирования (например, BASCOM AVR) позволяют указывать эти имена вместо истинных адресов, что облегчает программирование. В скобках после имён описываемых разрядов указаны их порядковые номера в соответствующем регистре от 7 (старший) до 0 (младший).
Те разряды, которые на момент написания статьи зарезервированы для использования в дальнейших модификациях микроконтроллера, обычно доступны только для чтения, которое, как правило, даёт нулевой результат. Если запись в них разрешена, то записывать рекомендуется только нулевые значения. Более подробно о контроллере ПДП рассматриваемых микроконтроллеров и его регистрах можно узнать в [2].
Общие регистры контроллера ПДП
Регистр CTRL - управление контроллером ПДП.
ENABLE (7) - разрешение (единица) или запрет (ноль) работы контроллера ПДП.
RESET (6) - запись единицы в этот разряд приводит к установке контроллера ПДП в исходное состояние. По её завершении разряд обнуляется автоматически. Действует только при ENABLE=0.
DBUFMODE[1:0] (3, 2) - режим двойной буферизации: 00 - выключен; 01 - включён в каналах 0, 1; 10 - включён в каналах 2, 3; 11 - включён во всех каналах. Двойная буферизация гарантирует непрерывность передачи информации при последовательном использовании двух каналов ПДП. Как только передача в первом канале завершается, разрешается работа второго канала, и наоборот.
pRiMODE[1:0] - установка приоритетов каналов ПДП: 00 - обработка запросов всех каналов карусельным методом; 01 - высший приоритет у канала 0, запросы остальных каналов обрабатываются по карусельному методу; 10 - высший приоритет у канала 0, следующий - у канала 1, запросы остальных каналов обрабатываются по карусельному методу; 11 - высший приоритет у канала 0, затем в порядке уменьшения приоритетов следуют каналы 1-3.
Разряды 4, 5 зарезервированы для будущих модификаций.
Регистр INTFLAGS - флаги состояния прерываний от контроллера ПДП.
CH3ERRIF-CH0ERRIF (7-4) - флаги прерываний по ошибкам в каналах ПДП. Исходное значение - 0000. Ошибка в любом из каналов ПДП приводит к установке единицы в соответствующем разряде. Запись единицы в один из этих разрядов приводит к его обнулению.
CH3TRNFIF-CH0TRNFIF (3-0) - флаги прерываний по завершению транзакций в каналах ПДП. Исходное значение - 0000. Флаг устанавливается (разряд переходит в единичное состояние), когда транзакция в соответствующем канале завершена. Если задано неограниченное число повторений, флаг устанавливается по окончании передачи каждого блока. Запись единицы в разряд снимает флаг.
Регистр STATUS - состояние контроллера Пдп.
CH3BUSY-CH0BUSY (7-4) - флаги занятости каналов. Флаг устанавливается (переходит в единичное состояние) при начале транзакции. Он снимается (переходит в нулевое состояние) при отключении канала, при установке флага прерывания по завершении транзакции или при ошибке в канале.
CH3PEND-CH0PEND (3-0) - флаги ожидания пересылки блока. Устанавливаются, когда заданная пересылка блока фактически не происходит. Автоматически снимаются с началом пересылки или при отмене транзакции.
Регистры канала ПДП
Регистр CTRLA - управление каналом.
ENABLE (7) - запись единицы в этот разряд разрешает работу канала. Разряд автоматически обнуляется по завершении транзакции. Если в него записать ноль во время пересылки информации, то пересылка будет остановлена лишь после опустошения внутреннего буфера передачи.
RESET (6) - запись единицы в этот разряд приводит к установке канала в исходное состояние. Разряд автоматически обнуляется по завершении этой операции. Действует только при ENABLE=0.
REPEAT (5) - запись единицы в этот разряд активирует режим повторения пересылки блоков. Предварительно следует указать число повторений в регистре REPCNT Разряд автоматически обнуляется при запуске последнего из заданных повторений пересылки.
TRFREQ (4) - запись единицы в этот разряд приводит к генерации запроса на пересылку информации по каналу DMA. Разряд автоматически обнуляется с началом пересылки.
SINGLE (2) - запись единицы в этот разряд разрешает однократную передачу пакета информации, длина которого указана в поле BURSTLEN этого же регистра. Передачу инициирует источник информации. Значение в этом разряде нельзя изменить, если канал занят.
BURSTLEN[1:0] (1, 0) - задаёт число байтов в пакете: 00 - 1; 01 - 2; 10 - 4; 11-8. Его нельзя изменить, если канал занят.
Разряд 3 этого регистра зарезервирован для будущих модификаций.
Регистр CtrLb - управление каналом.
CHBUSY(7) - флаг занятости канала. Устанавливается, когда канал начинает транзакцию. Автоматически снимается при отключении канала, при установке флага прерывания по завершению транзакции или при установке флага прерывания по ошибке в канале.
CHPEND (6) - флаг ожидания пересылки блока по каналу. Он автоматически снимается с началом пересылки или при её отмене.
ERRIF (5) - флаг прерывания по ошибке в канале.
TRNIF (4) - флаг прерывания по завершении транзакции. Вместе с его установкой может генерироваться запрос прерывания. Если режим повторения не включён, установка флага и завершение транзакции происходят по окончании пересылки блока. В режиме бесконечного повторения флаг устанавливается после каждой передачи блока. Этот флаг не снимается автоматически с началом обработки прерывания. Его нужно снимать принудительно записью единицы в этот разряд.
ERRINTLVL[1:0] (3, 2) - приоритет прерывания по ошибке в канале: 00 - прерывание запрещено; 01 - низкий приоритет; 10 - средний приоритет; 11 - высокий приоритет.
TRNINTLVL[1:0] (1,0) - приоритет прерывания по завершению транзакции. Устанавливается также, как в разрядах ERRINTLVL[1:0].
Регистр ADDRCTRL - управление адресом.
SRCRELOAD[1:0] (7, 6) - устанавливают момент перезагрузки регистра адреса источника информации начальным значением: 00 - нет перезагрузки; 01 - перезагрузка в конце передачи блока; 10 - перезагрузка в конце передачи пакета; 11 - перезагрузка по окончании транзакции. Значение в этих разрядах не может быть изменено, если канал занят.
SRCDIR[1:0] (5, 4) - задают режим изменения адреса источника информации: 00 - адрес не изменяется; 01 - адрес увеличивается на единицу после пересылки каждого байта; 10 - адрес уменьшается на единицу после пересылки каждого байта; 11 - зарезервировано. Значение в этих разрядах не может быть изменено, если канал занят.
DESTRELOAD[1:0] (3, 2) - аналогичны SRCRELOAD[1:0], но для приёмника информации:
DESTDIR[1:0] (1, 0) - аналогичны SRCDIR[1:0], но для источника информации.
Регистр TRIGSRC - выбор источника запуска канала.
TRIGSRC[7:0] (7-0) - задают модуль или устройство ввода-вывода микроконтроллера, который будет формировать сигнал запуска передачи информации по каналу. Значение, которое необходимо загрузить в этот регистр, вычисляется как сумма базового значения, полученного из табл. 1, и смещения, полученного из табл. 2 - табл. 5.
Таблица 1
Источник запуска | База |
Разряд TRFREQ регистра CTRLA | 000H |
Система событий | 001H |
АЦП А | 010H |
ЦАП А | 015Н |
АЦП В | 020H |
ЦАП В | 025Н |
Таймер-счетчик СО | 040Н |
Таймер-счетчик С1 | 046Н |
SPI порта С | 04AH |
USART С0 | 04ВН |
USART С1 | 04ЕН |
Таймер-счетчик D0 | 060Н |
Таймер-счетчик D1 | 066Н |
SPI порта D | 06АН |
USART D0 | 06ВH |
USART Dl | 06ЕН |
Таймер-счетчик Е0 | 080Н |
Таймер-счетчик Е1 | 086 Н |
SPI порта Е | 08АН |
USART Е0 | 08ВН |
USART Е1 | 08ЕН |
Таймер-счетчик F0 | 0A0H |
Таймер-счетчик F1 | 0А6Н |
SPI порта F | 0AAH |
USART F0 | 0АВН |
USART F1 | 0AЕН |
Таблица 2
Канал | Смещение | |
АЦП | ЦАП | |
0 | 0 | +0 |
1 | 1 | +1 |
2 | Нет | +2 |
3 | Нет | +3 |
0-3 | Нет | +4 |
Таблица 3
Состояние таймера- счётчика | Смещение |
Переполнение или вычитание из нуля | +0 |
Ошибка | +1 |
Захват или сравнение в канале А | +2 |
Захват или сравнение в канале В | +3 |
Захват или сравнение в канале С* | +4 |
Захват или сравнение в канале D* | н-5 |
* - Только в таймере-счётчике 0
Таблица 4
Состояние USART | Смещение |
Прием завершен | +0 |
Регистр данных пуст | +1 |
Таблица 5
Событие | Смещение |
0 | +0 |
1 | +1 |
2 | +2 |
Пример. Необходимо запустить ПДП от канала 2 АЦП В. Из табл. 1 находим базовое значение кода запуска от АЦП В, равное 020Н, а из табл. 2 - смещение для канала 2 АЦП, равное +2. Итак, TRIGSRC=20H+2=22H.
Регистр REPCNT - счётчик повторений передачи блока.
REPcNt[7:0] (7-0) - оставшееся число повторений передачи блока, его начальное значение необходимо записать в этот регистр до разрешения повторений разрядом REPEAT регистра CTRLA. По завершении каждой передачи блока содержимое счётчика уменьшается на единицу. По достижении нулевого значения транзакция считается законченной. Разрешение повторений при нулевом значении в регистре REPCNT приводит к бесконечному повторению передачи.
Регистры SRCADDRO, SRCADDR1, SRCADDR2 - адрес источника информации (соответственно его младший, средний и старший байты). Перед началом передачи в них заносится 24-разрядный адрес первой ячейки области памяти, из которой будет передаваться информация. В процессе передачи блока содержимое этих регистров изменяется, как задано разрядами SRCRE-LOAD и SDRCDIR регистра ADDRCTRL.
Регистры DESTADDRO, DESTADDR1, DESTADDR2 - адрес приёмника информации. Устроены и функционируют аналогично регистрам SRCADDR0- SCRADDR2, но характер изменения их содержимого устанавливают разряды DESTRELOAD и DERTDIR регистра ADDRCTRL.
Практическое использование ПДП
Рассмотрим практическое использование ПДП на примере программы микроконтроллера цифрового осциллографа. В ходе приёма информации от АЦП и её отображения на ЖКИ циклически выполняются следующие действия:
- приём от внутреннего АЦП с периодом 0,5 мкс оцифрованных отсчётов исследуемого сигнала и запись их в буферную область ОЗУ объёмом 7200 байт;
- вывод на ЖКИ изображения масштабной сетки объёмом 3048 байт;
- отображение на ЖКИ осциллограммы (выборки объёмом 240 байт из буферной области ОЗУ).
Естественно, перед началом цикла настраиваются (конфигурируются) все модули микроконтроллера, участвующие в выполнении программы.
Алгоритм работы программы без ПДП мог бы иметь вид, показанный на рис. 2. Рассматривая происходящие в ней процессы пересылки информации между различными областями памяти, нужно учитывать следующее:
- регистры АЦП отображаются в область памяти ввода-вывода;
- электронная масштабная сетка представляет собой массив байтов, подготовленный заранее и хранящийся в программной (FLASH) памяти микроконтроллера. В ходе вывода на индикатор он затирает осциллограмму, выведенную на него в предыдущем цикле;
- индикатор подключён к микроконтроллеру через интерфейс внешней памяти данных, его регистры находятся в адресном пространстве этой области.
Применительно к структуре памяти микроконтроллера в каждом цикле работы программы необходимо, во-первых, 7200 байт пересылать из памяти ввода-вывода в ОЗУ, во-вторых, 3048 байт - из программной памяти во внешнюю память данных, в-третьих, 240 байт - из ОЗУ во внешнюю память данных.
Рис. 2. Блок-схема алгоритма работы программы микроконтроллера без ПДП
Вторую из этих пересылок выполнить с помощью ПДП невозможно, так как контроллер ПДП не имеет доступа к программной памяти. На третьем этапе использовать ПДП технически возможно, но очень сложно, так как подлежащие пересылке байты не расположены в ОЗУ последовательно и предварительно подвергаются ряду преобразований, которые может выполнить только процессор.
А вот на первом этапе никаких препятствий использованию ПДП нет. Процессор, соответствующим образом настроив контроллер ПДП перед началом цикла, должен в теле цикла лишь давать этому контроллеру разрешение начать транзакцию. Пока она происходит, контроллер может выполнять другую работу, например, выводить на индикатор масштабную сетку. Эти операции будут выполняться одновременно и совершенно бесконфликтно. В результате может быть достигнута существенная экономия времени.
К выполнению третьего этапа - отображению на индикаторе информации из буфера в ОЗУ - можно приступать только после заполнения буфера. Если ПДП не используется, это условие легко соблюдается автоматически, так как процессор обычно выполняет участки программы в строгой последовательности. ПДП, работая параллельно с процессором, изменяет ситуацию. При этом очевидно, что процессор перешлёт 3048 байт масштабной сетки быстрее, чем канал ПДП заполнит буфер ОЗУ объёмом 7200 байт, да ещё с задержками на 0,5 мкс между байтами. Поэтому, прежде чем начинать построение осциллограммы на ЖКИ, процессор должен убедиться в окончании транзакции ПДП.
Сделать это можно, проанализировав значения разрядов одного из регистров CTRLA или CTRLB либо регистра iNtFLAGS. В разряд ENABLE регистра CTRLA программно записывают единицу, разрешая начать транзакцию. По её завершении в этом разряде автоматически появляется нулевое значение. В разряде TRNIF регистра CTRLB флаг окончания транзакции автоматически устанавливается по её завершении. В регистре INTFLAGS имеются флаги CH3TRNFIF-CH0TRNFIF, обозначающие окончание транзакций соответственно в каналах ПДП с третьего по нулевой.
Состояние какого регистра анализировать для фиксации момента окончания транзакции - дело вкуса программиста. Следует, однако, иметь в виду, что автоматически установленный в регистре CTRLB флаг после его анали-занеобходимо снимать принудительно. То же самое относится к флагам в регистре INTFLAGS. Во фрагментах программы на языке BASCOM AVR, рассмотренных в статье далее, анализируется состояние флага в регистре INTFLAGS.
Блок-схема алгоритма работы программы микроконтроллера, использующей ПДП, показана на рис. 3. Оцифровку исследуемого сигнала выполняет нулевой канал АЦП А, работающий в восьмиразрядном непрерывном режиме. Буферная область ОЗУ начинается с адреса 3000Н и имеет объём 7200 байт. Для пересылки в неё результатов работы АЦП используется нулевой канал ПДП.
Рис. 3. Блок-схема алгоритма работы программы микроконтроллера, использующей ПДП
Перед основным циклом программа настраивает модули микроконтроллера, участвующих в выполнении программы - систему синхронизации, АЦП А, контроллер ПДП и др. При настройке АЦП А ему назначается генерация запроса прерывания по готовности результата преобразования.
Далее остановимся на действиях, связанных с организацией ПДП. Настройку контроллера ПДП выполняют две директивы. Первая из них настраивает общеканальную часть контроллера:
Config Dma=Enabled,Doublebuf=◊
Disabled, Cpm=Ch0rr123
Здесь и далее знак ◊ в конце строки означает, что она продолжается в следующей. В компьютер их следует вводить одной строкой без этого знака. Директива разрешает работу контроллера ПДП, запрещает двойную буферизацию (в ней нет необходимости, так как предполагается использовать только один канал ПДП) и задаёт наивысший приоритет каналу 0.
Следующая директива настраивает используемый канал 0 ПДП. В соответствии с поставленной задачей ему задаются пакетный режим передачи с длиной пакета 1 байт и без повторения блоков, постоянный адрес источника - регистра младшего байта результата АЦП А, начальный адрес приёмника информации &H3000 - адрес начальной ячейки буфера в ОЗУ - с инкрементированием после передачи каждого байта и перезагрузкой начального значения по окончании транзакции. Последнее подготавливает канал к следующей транзакции. Объём транзакции - 7200 байт, источник запуска - нулевой канал АЦП А.
Рассматриваемая директива имеет вид Config Dmach0=.... Далее следует длинный список параметров, которые задают значения, загружаемые в регистры канала 0, рассмотренные выше. Получить подробную информацию об этой директиве можно в раздел "Help" среды BASCOM AVR. Кратко отметим лишь, что начальные адреса источника и приёмника информации нельзя указывать константами. Они должны загружаться из переменных. Если один из этих адресов лежит в области памяти ввода-вывода, т. е. представляет собой адрес программно доступного регистра, то его можно задать с помощью встроенной в BASCOM AVR функции Varptr(Имя_Регистра). Она возвращает адрес регистра, носящего указанное в качестве параметра имя. Это весьма удобно, так как помнить имена регистров значительно легче, чем их адреса. При этом использовать промежуточную переменную для хранения полученного адреса нет необходимости.
Учитывая изложенное, вторая директива конфигурирования канала 0 ПДП имеет вид
Adr=&H300
Config Dmach0=Disabled,Burstlen=1,◊
Chanrpt=Disabled, Tci=L0, Eil=Lo,◊
Singleshot=Enabled, Sar=None,◊
Sam=Fixed,Dar=Transaction,Dam=Inc,◊
Trigger=&H10,Btc=7200,Repeat=1,◊
Sad=varptr(adca_ch0_resl),Dadr=Adг
Перед ней в переменную Adr занесено значение начального адреса приёмника информации (буфера в ОЗУ), из которой оно перегружается в тело директивы. Начальный адрес источника информации (регистра младшего байта результата работы нулевого канала АЦП А adca_ch0_resl) указан с помощью функции Varptr.
В приведённом виде директива не разрешает работу канала. Если сразу разрешить его работу (Config Dmach0= Enabled....), то транзакция может начаться немедленно после исполнения этой директивы и получения от АЦП А первого сигнала готовности результата. Это может случиться до входа в основной цикл программы, когда ещё не завершена вся необходимая настройка. Поэтому разрешать работу канала ПДП следует позже, в начале основного цикла программы.
В качестве альтернативного способа конфигурирования контроллера ПДП (как и любого другого модуля микроконтроллера) можно пользоваться записью необходимых кодов непосредственно в его регистры. Этот приём удобен при частичном реконфигурировании модуля. Например, чтобы изменить только источник запуска канала ПДП, проще загрузить новое значение в регистр TRIGSRC, чем переписывать всю директиву конфигурирования.
Согласно блок-схеме алгоритма (рис. 3), первым действием в цикле должно быть разрешение работы канала ПДП. Это выполняется записью единицы в разряд ENABLE регистра CTRLA канала командой
Set Dma_ch0_ctrla.7
После неё канал ПДП начинает заполнять буфер в ОЗУ На фоне этой транзакции процессор выводит на экран масштабную сетку, побайтно считывая её из командной памяти
Restore setka
For I = 1 To 3048
Read Dispdata
Gosub Eram_Data_w
Next
Здесь Setka - метка начала массива байтов изображения координатной сетки во FLASH-памяти; Eram_Data_w - имя подпрограммы, выводящей байты на индикатор.
После вывода масштабной сетки на индикатор процессор проверяет, завершена ли транзакция каналом ПДП (то есть заполнен ли буфер). Если нет, он ждёт её завершения. Признаком завершения транзакции служит флаг CH0TRNFIF в регистре INTFLAGS:
Bitwait Dma_intflags.0,Set
По завершении транзакции этот флаг следует снять:
Set Dma_intflags.0
Теперь можно приступать к отображению осциллограммы. Для упрощения условимся, что будем отображать первые 240 байт буфера ОЗУ:
Addr=&H3000
Step=5
For I=0 to 239
Dispdata=inp(Addr)
Gosub Eram_osc
Addr=Addr+Step
Next
Здесь Eram_osc - имя подпрограммы, осуществляющей необходимые преобразования считанных из буфера данных и их отображение.
Микроконтроллеры ATxmega и система программирования BASCOM AVR
Разработчики системы программирования BASCOM AVR заявляют, что полноценную работу с микроконтроллерами ATxmega эта система обеспечивает, начиная с версии 2.0.7.5. Более ранние версии, начиная с 2.0.5.0, предоставляют лишь ограниченные возможности такой работы. Данных о возможности разработки программ для ATxmega с помощью ещё более ранних версий BASCOM AVR у автора нет.
Как определить, пригодна ли имеющаяся версия для ATxmega? Лучше всего, конечно, поискать нужную информацию на http://mcselec.com/ - сайте разработчика BASCOM AVR. Если нужной информации там не нашлось, запустите BASCOM AVR. В его главном окне откройте пункт меню "Options- Compiler-Chip". В поле "Chip" открывшегося окна разверните выпадающий список файлов с необходимой компилятору информацией о микроконтроллерах и поищите в нём файлы, имена которых начинаются с "xm" (например, файл xm128a3def.dat описывает микроконтроллер ATxmega128A3). Если файл, относящийся к нужному микроконтроллеру, имеется - всё в порядке. В противном случае версию системы BAS-COM AVR следует обновить.
И последнее. В версиях BASCOM AVR ниже 2.0.7.5 в начальной части исходного текста программы после директив, описывающих тип микроконтроллера, задающих его тактовую частоту и размер стека, обязательно должны находиться следующие директивы:
$lib "xmega.lib"
$external _xmegafix_clear
$external _xmegafix_rol_r1014
Именно они обеспечивают корректную работу системы программирования с микроконтроллерами семейства ATxmega.
Литература
1. 8/16-bit Atmel XMEGA A3U Microcontroller. - URL: http://www.atmel.com/images/ atmel-8386-8-and-16-bit-avr-microcontroller-atxmega64a3u-128a3u-192a3u-256a3u_ datasheet.pdf (13.08.14).
2. 8-bit Atmel XMEGA A Microcontroller. XMEGA A MANUAL. - URL: http://www.atme!. com/Images/doc8077.pdf (13.08.14).
Автор: А. Савченко, пос. Зеленоградский Московской обл.