Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить

Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC33)

Пн янв 07, 2019 08:17:17

Обычно те, кто пишет на Си, достаточно полигамны в смысле выбора платформ МК. Поэтому сия тема не для них. Ну, во всяком случае, не специально для них.
Речь будет идти для тех, кто желает разобраться в архитектуре 16-разрядной платформы и начать писать простые программы на АСМе этой платформы.
Итак.
Пару слов о программной модели.
Вообще, очень хорошо все расписано в первой части специального мануала Микрочипа по программированию 16-разрядных МК этой фирмы:
http://ww1.microchip.com/downloads/en/D ... 00157g.pdf
Рискну изложить коротко и на русском языке.

1. Платформа делится на PIC24 и dsPIC. Они отличаются наличием/отсутствием DSP-ядра и ряда команд связанных с этим ядром, а так же еще некоторых фич, которые будут упомянуты в дальнейшем. В остальном система команд и программная модель полностью идентичны.
2. Длина команды - 24 бита, в которых 8 бит занимает код операции, а остальное связано с адресацией операндов.
3. Счетчик команд - 23 бита. Это значит, что возможна адресация программной памяти размером 4М*24 (4М инструкций). Естественно, что физически реализована лишь малая часть этого адресного пространства. Счетчик команд всегда четный (0, 2, 4 ...). Нечетные адреса занимают старшие байты команд. Нечетная адресация возможна лишь при байтном чтении программной памяти. Попытка чтения 16 битного слова из нечетного адреса программного флеша вызывает ошибку с переходом по вектору обработки этой ошибки. Очень полезно при отладке. Подробнее - позже.
Код исполняется только из программной памяти. Это чисто гарвардская архитектура. В новейших двухядерных МК этой платформы второе ядро исполняет код из PRAM - программной ОЗУ. Но эта ОЗУ не имеет отношения к ОЗУ данных.
Все команды обработки данных исполняются в один цикл, кроме деления. Деление исполняется в 18 циклов. Команды переходов и ветвления (связанные с конвейером) исполняются более, чем 1 цикл. Команды чтения из флеша могут исполнятся более, чем за 1 цикл. Это связано с организацией шин в конкретном семействе платформы.
4. Длина данных - 16 бит. Адресное данных пространство ОДНОБАЙТНОЕ. Четные адреса - младшие байты 16-разрядных слов, нечетные адреса - старшие байты. Часть команд могут быть байтными.
5. Адресное пространство данных позволяет адресовать 64К байт (32К слов), но есть страничная адресация, позволяющая расширить это пространство (EDS). А так же есть PSV - видимость младших двух байт программной памяти в адресном поле данных. Это дает возможность формирования таблиц во флеше с обращением к ним как к ОЗУ.
6. Ядро содержит 16 регистров общего назначения (РОНов), два из которых загружена функциями ядра (W14 и W15). РОНы попарно образуют 32-разрядные слова в части арифметических операций (умножение и деление). РОНы так же используются для косвенной адресации.
7. Адресация операндов указывается в команде (инструкции). Адресация команд бывает:
- безадресная (типа nop)
- непосредственная (операнд в команде - константа) add #20, W0 (W0=W0+20)
- прямая (адрес операнда в команде) inc temp (temp=temp+1)
- косвенная (адрес операнда в РОНе) mov [W0], W1 (содержимое в ОЗУ с адресом в W0 копируется в W1)
Косвенная адресация бывает:
- без модификации указателя (содержимого РОНа) [W0]
- пост автоинкрементная [W1++]
- пост автодекрементная [W1--]
- пре автоинкрементная [++W1]
- пре автодекрементная [--W1]
- со смещением на константу [W2+26]
- индексная (со смещением на переменную) [W0+W7]
DSP команды в dsPIC имеют ограниченное число видов адресаций. Но устраивающих задачи специфические для этих команд.
Так же есть AGU (модуль генерации адресов) реализующий:
- модульная адресация (организована через специальные регистры указатели окна), когда косвенная адресация оказывается кольцевой в этом окне адресов.
- битреверсная адресация (специфическая адресация для FFT (быстрого преобразования Фурье)
8. Стек реализован с помощью указателя стека (вершины стека) расположенного в W15 и регистра SPLIM - контролирующего выход стека за обозначенный в нем предел адреса - вызывает обработчик ошибки стека. Удобно при отладке.
Эти регистры обязаны быть инициализированы в начале программы, если предполагается использовать стек, естественно.
9. Локальный стек (фрейм) позволяет при входе в вызов (call или прерывание) открывать указатели на локальные переменные. Эти указатели размещены сразу за вершиной стека. Указатель локального стека размещен в W14. При входе в вызов локальный стек объявляется командой lnk #N . При выходе из вызова локальный стек закрывается командой ulnk . Это Си ориентированный механизм определения локальных переменных.
10. Регистры ядра:
Все РОНы W0...W15, из них W0...W3 имеют шадоу-стек загружаемый/выгружаемый в один цикл безоперандными командами push.s/pop.s. Этими же командами в тот же шадоу-стек сохраняется весь контекст из STATUS регистра. Понятно, что с этих команд начинается и заканчивается любой обработчик прерываний.
SPLIM - ограничитель стека
STATUS - регистр состояний ядра
PC - программный счетчик
RCOUNT - счетчик команды repeat - однокомандный цикл
DCOUNT - счетчик команды do - многокомандный цикл (только в dsPIC)
DOSTART - стартовый адрес команды do (только в dsPIC)
DOEND - конечный адрес команды do (только в dsPIC)
CORCON - регистр управления ядром
TBLPAG - страница табличного доступа
PSVPAG - страница доступа к флешу
DSWPAG - страница расширенного адреса при записи
DSRPAG - страница расширенного адреса при чтении

Пока все. Продолжение следует.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пн янв 07, 2019 16:36:04

Продолжим наши совместные изыскания на тему.
Топология программного флеша.
Особенность рассматриваемой архитектуры состоит в расположении таблицы векторов прерываний в самом начале программного флеша.
По адресу 0х0000 флеша всегда размещен вектор сброса. По этому адресу линкер должен вставить стандартную команду перехода на стартовый адрес исполняемого кода.
Чтобы линкер это сделал, в тексте программы на Ассемблере обязан быть объявлен этот вектор:
Код:
.global   __reset

В результате линкер вставит по нулевому адресу команду goto <стартовый адрес исполняемого кода>
Эта команда займет два командных слова.
Далее будут следовать не инструкции, а АДРЕСА ВЕКТОРОВ ПРЕРЫВАНИЙ. Позиции векторов фиксированы. Каждый источник прерываний имеет свою позицию. Но в этой позиции появится физический адрес исполняемого кода при выполнении ДВУХ условий. Этот вектор должен быть объявлен:
Код:
.global   __T1Interrupt      ; прерывание по переполнению таймера TMR1

Должен быть в наличии сам обработчик этого прерывания:
Код:
__T1Interrupt:
       push.s
.........
.........
       pop.s
       retfie

Синтаксис объявлений ИМЕН векторов нормирован в скрипте линкера, который следует присоединить к проекту. Ошибка в написании имени самого исполняемого вызова (оно включает двойное подчеркивание) приведет к тому, что вызов станет обычной подпрограммой без особенностей обработчика прерываний (адрес этой подпрограммы не попадет в таблицу векторов). Все дженерик-скрипты линкера типа gld, как и хедер-файлы типа inc находятся в файлах папки соответствующего семейства раздела Support компилятора XC16. Следует заметить, что нынче ASM16 является частью компилятора XC16. Достаточно free версии.
Но вернемся к IVT - interrupt vector table - таблице прерываний.
В разных подсемействах таблица может иметь особенности, но она всегда размещена между вектором сброса и адресом 0х200 программного флеша.
Некоторые подсемейства имеют альтернативную таблицу векторов (AIVT), которая размещена вслед за основной таблицей. Код может НА ЛЕТУ переключить таблицу в соответствующем регистре контроллера прерываний.
Завершается таблица прерываний ловушкой переадресующий исполнение на адрес ресет вектора. Эту ловушку формирует линкер. Поэтому начало реального кода смещено на несколько адресов ниже 0х200.
В даташитах на конкретный МК указан размер доступного флеша и расположение разного рода конфигурационных регистров в адресном поле программной памяти. Иногда в поле адресов самого флеша (физически реализованного), иногда гораздо ниже, как отдельный фрагмент адресного пространства. Там же размещен EEPROM (если он есть) в адресном поле флеша (помимо регистрового доступа).
Память данных.
ОЗУ рассматриваемой платформы делится на сегменты. Ближний (near) сегмент (8К байт) доступен для команд с прямой адресацией. То есть если мы собираемся использовать переменную в командах типа add temp , переменная temp должна быть расположена в ближнем сегменте. Начиная с нулевого адреса ОЗУ располагается поле регистров специального назначения (SFR). Собственно ОЗУ общего назначения начинается с адреса 0х0800 или даже 0х1000 в зависимости от подсемейства.
Аппаратный дебаггер на время отладки сдвигает адреса объявленных переменных сегмента near на 0х50 адресов.
Остальная память в контроллерах PIC24 не имеет особенностей.
Кроме того, в контроллерах dsPIC адресное пространство ОЗУ разбито на два типа: X и Y. Это связано с адресацией в DSP командах, где выборка данных может быть фиксирована для разных типов. Но об этом позже.

Типы инструкций (команд).
Тут все структурировано:
1. Move Instructions
2. Math Instructions
3. Logic Instructions
4. Rotate/Shift Instructions
5. Bit Instructions
6. Compare/Skip and Compare/Branch Instructions
7. Program Flow Instructions
8. Shadow/Stack Instructions
9. Control Instructions
10. DSP Instructions (только для dsPIC)

Собственно разбор каждой из команд будет выборочным и эпизодическим по ходу изложения. Ранее приведенная ссылка:
http://ww1.microchip.com/downloads/en/D ... 00157g.pdf
содержит во второй своей части исчерпывающее описание каждой из команд с примерами кода и результатом действия.
По требованию читателей моей графоманской писанины можно будет разобрать интересующую команду подробно и на русском языке.
Синтаксис большинства самых используемых команд идентичен синтаксису 8-разрядных семейств, что делает очень простым переход на обсуждаемую платформу адептов 8-разрядных ПИКов.
Для того, чтобы читатель не потерял интерес к моим виршам окончательно, перейдем сразу к созданию проекта с разбором стартап-кода. И там будем применять ранее упомянутые команды.

Прежде чем начнем писать код, создадим проект в среде РАЗРАБОТКИ MPLABX IDE (предлагаю сразу скачать и установить последнюю текущую версию 5.10).
https://www.microchip.com/mplab/mplab-x-ide
Вместе со средой можно установить интегрированную в дистрибутив среду ПРОГРАММИРОВАНИЯ MPLABX IPE, которая поддерживает все виды программаторов, начиная с 3-го поколения (PICkit3/ICD3 и старше).
Кроме этого нужно скачать и инсталлировать ПОСЛЕ установки среды текущую версию компилятора XC16 (1.36). При инсталляции заявляем о желании free версии, если только не желаем 90 дней пользоваться триал-версией полного функционала Си (но нам Си пока не требуется, поэтому ставим free).
https://www.microchip.com/mplab/compilers
После установки и первого запуска мы увидим стартовую страницу, которая нам не нужна. ОДНАКО!!!! Настоятельно рекомендую не ставить галку о ее уничтожении впредь, поскольку в таком случает автоматически открываемый (ранее открытый) исходный файл на АСМе будет содержать ошибочную расцветку метакоманд кода типа equ, space, end, global и т.п. и придется сначала закрыть исходный файл, а потом его снова открыть. Гораздо проще закрыть только стартовую страницу. Подождем пока Микрочип подрихтует сей непринципиальный баг.
Картинки далее кликаем для увеличения.
Открываем в верхней строке меню:
Изображение
Tools-Options-Embedded
Изображение
И правим в нижней строке таблицы Default Charset кодировку на Windows-1251, чтобы русские комментарии стали отображаться корректно в любом создаваемом проекте по умолчанию.
Кроме того, выбираем во второй снизу строке таблицы Debug startup любой вариант кроме Run, иначе при отладке после компиляции проект запустит Run (исполнение) автоматически.
Я выбираю то, что изображено, чтобы и при ресете и после компиляции в отладчике, МК всегда находился на ресет-векторе. Если будет выбран Main, МК встанет на адрес начала исполняемого кода.
Жмякаем по оранжевой папке с зеленым крестом для открывания визарда создания нового проекта:
Изображение
Открывается окно визарда, где с первым меню мы просто соглашаемся:
Изображение
Далее выбираем контроллер:
Изображение
Далее выбираем отладчик (для начала стоит выбрать симулятор):
Изображение
Выбираем установленный ранее компилятор XC16:
Изображение
Выбираем (или вновь создаем) папку проекта:
Изображение
Далее пропускаем включение в проект файлов и проект открывается слева в консоли Projects как активный (проектов может быть несколько, но активный (выделен болдом) только один).
Изображение
Далее жмякаем по крайней серой папке с зеленым крестом:
Изображение
Выбираем Assembler - AssemblyFile.s
Изображение
Определяем его имя:
Изображение
И он открывается в окне с пустыми 4 строками:
Изображение
Затем открываем отдельно папку проекта и проверяем, что исходный файл попал туда.
Это папка проекта:
Изображение
Это ее содержимое:
Изображение
Открываем support в папке xc16 и выбираем семейство МК (путь к папке будет идентичен показанному на скрине):
Изображение
Копируем в папку проекта gld и inc файлы из соответствующих папок:
Изображение
Включаем в проект все три файла, жмякая правой кнопкой мыши по соответствующей папке дерева проекта и указывая пункт меню Add Existing Item...:
Изображение
В принципе, место расположения этих трех файлов по папкам значения не имеет, но желательно для порядка их растащить по своим.
Все. Проект готов.
Можно начинать писать код в окне исходника (s-файла).

Еще немного настроим редактор, убрав автоотступ при переводе строки. Снова Tool-Options, но уже раздел Editor-Formatting:
Изображение
А теперь можно писать код.
Для начала предлагаю создать "рыбу". Темплейт со стандартным стартапом.
Его можно будет копировать практически во все проекты без изменений (только корректируя include по примененному МК).
Код:
;==========
.include "p33ep128mc202.inc"
;==========
.global __reset
.global __AddressError
.global __StackError
.global __MathError
;==========
    .text
__reset:
   mov      #__SP_init, W15
   mov      #__SPLIM_init, W0
   mov      W0, SPLIM
   bra      Main
;----------
__AddressError:
   nop
   nop
   nop
   retfie
__StackError:
   nop
   nop
   nop
   retfie
__MathError:
   nop
   nop
   nop
   retfie
;----------
Main:
   nop
   nop
Superloop:
   nop
   bra      Superloop
;----------
.end

mov #__SP_init, W15 - линкер сам определит константу __SP_init по самому протяженному отрезку адресов свободного ОЗУ. # - означает константу. Команда загрузит константу в РОН W15, который является указателем вершины стека.
mov #__SPLIM_init, W0 - линкер сам определит конец свободных адресов и последний адрес как константу __SPLIM_init
mov W0, SPLIM - прямой загрузки константы в ОЗУ нет. поэтому сначала константа попадает в РОН, а из РОНа в регистр.
Аналог в 8 разрядных МК:
movlw <константа>
movwf <регистр>

bra Main - ничем от 18-х не отличается. Короткий безусловный переход-ветвление.
В код вставлены обработчики ошибок адреса, стека и математики (деление на 0, например). Можно будет держать там дежурные брекпойнты при отладке в симуляторе. они перехватят ошибку и по шагам мы выйдем в точку следующую прямо за ошибкой.
Иногда в симуляторе этот механизм не работает (программа зависает в ловушке).

Продолжение следует.

ЗЫ.
Еще немного настроек, теперь линкера.
Правой кнопкой мыши кликаем по корневому имени проекта в дереве проектов слева в окне. Последний пункт выпадающего меню - Properties.
Открывается окно Project properties. Слева в окне дерево Categories. Выбираем ветку xc16-ld. Справа меню настроек линкера. Убираем галку с опции инициализации секции данных и фиксируем Apply-OK:
Изображение

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Вт янв 08, 2019 20:13:49

Выяснил почему зависает в обработчиках ошибок.
В железе при отладке флаг ошибки в регистре прерываний INTCON1 падает сам. В симуляторе его нужно зачистить руками.
Итого, исходный текст стал:
Код:
;==========
.include "p33ep128mc202.inc"
;==========
.global __reset
.global __AddressError
.global __StackError
.global __MathError
;==========
    .text
__reset:
   mov      #__SP_init, W15
   mov      #__SPLIM_init, W0
   mov      W0, SPLIM
   bra      Main
;----------
__AddressError:
   bclr      INTCON1, #ADDRERR
   nop
   retfie
__StackError:
   bclr      INTCON1, #STKERR
   nop
   retfie
__MathError:
   bclr      INTCON1, #MATHERR
   nop
   retfie
;----------
Main:
   nop
   nop
Superloop:
   nop
   nop
   bra      Superloop
;----------
.end


Теперь нужно запустить симуляцию. Для этого компилируем имеющийся исходник с загрузкой отладчика, для чего жмем:
Изображение
И после небольшого процесса входим в отладку:
Изображение
Нажимаем один раз на шаговое исполнение (стрелка вниз) и зеленый курсор текущего значения счетчика команд появляется на первой команде. Программа с ресет-вектора встала на первую команду исполняемого кода.
Изображение
Теперь можно открыть панель Watches (Window-Debugging-Watches) и в ней открыть любой регистр для наблюдения.
Пока у нас нет переменных, наблюдаем за РОНами:
Изображение

Поскольку пока речь идет о симуляторе, конфиг мы никак не обозначили.

Объявим переменные.
Для этого нужно создать секцию переменных:
Код:
;==========
.include "p33ep128mc202.inc"
;==========
    .section buf1, near, bss
ptrArrVar:   .space 2
arrVar:      .space 64
;==========
.global __reset
.global __AddressError
.global __StackError
.global __MathError
;==========
    .text
__reset:
   mov      #__SP_init, W15
   mov      #__SPLIM_init, W0
   mov      W0, SPLIM
   bra      Main
...........................
...........................


.section buf1, near, bss - заголовок секции, где buf1 - ее имя, near - место размещения (первые 8К байт), bss - неинициализированные данные.
ptrArrVar: .space 2 - переменная длиной 2 байта (1 слово)
arrVar: .space 64 - массив длиной 64 байта (32 слова)

Снова компилируем.

Открываем панель ОЗУ: Window-TargetMemoryWiews-FileRegisters. Перетаскиваем ее "за ухо" под панель Watches. И снизу этой панели меняем формат с HEX на Simbol. Стрелка вниз в этом окне (Go To) - переходим на адрес 0х1000 :
Изображение
Видим наши переменные. Конец массива никак не обозначен. Только стартовый адрес.
Теперь мы можем написать небольшой код заполнения массива, пользуясь инструкцией repeat:
Код:
;----------
Main:
   mov      #arrVar, W1
   mov      #0xAA, W0
   repeat      #31
      mov      W0, [W1++]
Superloop:
   nop
   nop
   bra      Superloop
;----------


mov #arrVar, W1 - имя массива является константой его стартового адреса, его мы грузим в W1 (он будет указателем массива
mov #0xAA, W0 - константу 0xAA (шахматный код) мы грузим в W0
repeat #31 - команда цикла на одну инструкцию следующую за ней, количество повторов равно аргументу команды+1 (то есть 31+1=32). В качестве аргумента может быть переменная в любом РОНе, тогда вид будет repeat W12
mov W0, [W1++] - содержимое W0 будет 32 раза грузиться по указателю в W1, при этом будет происходить постинкремент указателя.

Смещение табуляцией повторяемой команды сделано для лучшей читабельности.

Компилируем и проходим шагами, наблюдая в окне ОЗУ как заполняется массив, при этом в окне Watches можно наблюдать за инкрементом указателя в W1:

Изображение

Теперь открываем мануал по программированию 16-разрядной платформы (ссылка ранее была) и бегло знакомимся со списком команд.
Интересующие команды вставляем в нашу программу и смотрим как они работают.

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

Но это вечером.

Добавлено after 6 hours 32 minutes 27 seconds:

Продолжаем.

При написании программ на АСМе есть прямой смысл придерживаться соглашений подобных языкам высокого уровня. И вообще, строить программу подобно тому, как ее пишут на Си, например.

Большинство серьезных программ имеют несколько режимов. И эти режимы переключаются с помощью некоего интерактивного меню.
Каждому режиму соответствует своя инициализация, свой режим обработки данных и свой участок графики (индикации) и управления.
Традиционно такие программы строят с помощью машины состояний. Причем оная машина состояний может быть одно или многомерная.
Точно как структура меню управления устройством.
Удобнее всего для построения алгоритма такого устройства использовать указатели на функцию.
Тем более, что в системе команд 16-разрядных PIC-ов есть инструкция call Wn.
Пусть некое устройство имеет четыре режима, каждому из которых соответствуют свои: Инициализация, Расчет, Графика-индикация, Управление.
То есть ЧЕТЫРЕ ФУНКЦИИ.
Вот и напишем эти четыре функции в главном цикле просто подряд:
Код:
;----------
Main:
   nop
   nop
Superloop:
   call      MainInit
   call      MainCalc
   call      MainDraw
   call      MainControl
   bra      Superloop
;----------
;--- функции главного цикла ---
;----------
CommonMainFunc:
   mov      W0, DSRPAG
   mov      statMode, W0
   sl      W0, W0
   mov      [W1+W0], W1
   mov      #0x01, W0
   mov      W0, DSRPAG
   call      W1
   return
MainInit:
   btss      statFlags, #req_init
   return
   bclr      statFlags, #req_init
   mov      #psvpage(TabFuncInit), W0
   mov      #psvoffset(TabFuncInit), W1
   bra      CommonMainFunc
MainCalc:
   btss      statFlags, #data_ready
   return
   bclr      statFlags, #data_ready
   mov      #psvpage(TabFuncCalc), W0
   mov      #psvoffset(TabFuncCalc), W1
   bra      CommonMainFunc
MainDraw:
   mov      #psvpage(TabFuncDraw), W0
   mov      #psvoffset(TabFuncDraw), W1
   bra      CommonMainFunc
MainControl:
   mov      #psvpage(TabFuncControl), W0
   mov      #psvoffset(TabFuncControl), W1
   bra      CommonMainFunc
;----------
FuncInit0:
<тело функции инициализации режима 0>
   return
;----------
FuncInit1:
<тело функции инициализации режима 1>
   return
;----------
...........................
<остальные функции>
;----------
FuncControl3:
<тело функции управления режима 3>
   return
;----------

;----------
;--- таблицы указателей на функции
;----------
TabFuncInit:
.pword  handle (FuncInit0)
.pword  handle (FuncInit1)
.pword  handle (FuncInit2)
.pword  handle (FuncInit3)
TabFuncCalc:
.pword  handle (FuncCalc0)
.pword  handle (FuncCalc1)
.pword  handle (FuncCalc2)
.pword  handle (FuncCalc3)
TabFuncDraw:
.pword  handle (FuncDraw0)
.pword  handle (FuncDraw1)
.pword  handle (FuncDraw2)
.pword  handle (FuncDraw3)
TabFuncControl:
.pword  handle (FuncControl0)
.pword  handle (FuncControl1)
.pword  handle (FuncControl2)
.pword  handle (FuncControl3)
;----------


Этот пример использует табличное чтение указателей с помощью оператора handle(), возвращающего 16-разрядное значение адреса метки в скобках.
Таким образом единое тело универсальной функции использовано для всех четырех режимов главного цикла.
Но входы этой функции для всех режимов разные, что дает возможность создать специфические условия исполнения этих функций (например вход по флагу), а так же подготовить константы таблиц указателей, переключая универсальное тело на разные группы таблиц.
Переменная statMode и есть машина состояний.

На сегодня все. Продолжение следует.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Вт янв 08, 2019 21:00:39

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

Спасибо за пинок, скомпилилось и в симуляторе МпЛаб забегало:

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пт янв 11, 2019 18:50:54

KPAM писал(а):Синтаксис большинства самых используемых команд идентичен синтаксису 8-разрядных семейств, что делает очень простым переход на обсуждаемую платформу адептов 8-разрядных ПИКов.

Синтаксис тут не при чем. Малое количество дип - корпусов у этой серии мк отпугивает + более высокая цена.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пт янв 11, 2019 19:56:29

KPAM писал(а):Синтаксис большинства самых используемых команд идентичен синтаксису 8-разрядных семейств, что делает очень простым переход на обсуждаемую платформу адептов 8-разрядных ПИКов.

Синтаксис тут не при чем. Малое количество дип - корпусов у этой серии мк отпугивает + более высокая цена.

Асм тоже для лично меня важен.
Кроме инициализации - беглое чтение списка команд - показало что там только на 1 взгляд их 84 штуки. А с учётом исключений/адресаций и тд - их пара/тройка сотен.
На зубрёжку/привыкание времени однозначно больше уйдёт чем на Пик-18.
Так что - будем не спеша, но потихоньку.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пт янв 11, 2019 21:45:53

Синтаксис тут не при чем. Малое количество дип - корпусов у этой серии мк отпугивает + более высокая цена.


Да кому нынче этот дип нужен, разве что в макетку втыкать.

P.S.
Автору темы низкий поклон. Качественная подача информации.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пт янв 11, 2019 23:53:42

Поигрался и бросил PIC24. Есть новое 8 - ми разрядное семейство K42, там и IVT, и раздельное тактирование периферии, и CLC, и PPS, DMA, аппаратный CVD, АЦП с аппаратной обработкой выходного результата, таймеры и прочая дребедень в DIP40. Можно паять на коленке и разводить соплями дорожки для быстрой проверки задуманного.
p.s.
В 16-ти разрядниках интересное - двуядерные MK и секвенсор периферии.

Добавлено after 1 hour 33 minutes 39 seconds:
KPAM писал(а):Синтаксис большинства самых используемых команд идентичен синтаксису 8-разрядных семейств, что делает очень простым переход на обсуждаемую платформу адептов 8-разрядных ПИКов.

Синтаксис тут не при чем. Малое количество дип - корпусов у этой серии мк отпугивает + более высокая цена.

Асм тоже для лично меня важен.
Кроме инициализации - беглое чтение списка команд - показало что там только на 1 взгляд их 84 штуки. А с учётом исключений/адресаций и тд - их пара/тройка сотен.
На зубрёжку/привыкание времени однозначно больше уйдёт чем на Пик-18.
Так что - будем не спеша, но потихоньку.

После ASM30, MPASM вам покажется очень кривым и неудобным. Проблема только в том, что PIC24/30, подавляющему большинству писателей этого форума, нужен как собаке пятая нога.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Сб янв 12, 2019 07:10:52

После ASM30, MPASM вам покажется очень кривым и неудобным.

Не понял нащщет "после"... :))) :))) :)))
После кого? После Вас? Могу поспорить, что ПОСЛЕ МЕНЯ... :wink: :tea:
Не будем пока про PTG, я отдельно чуть позже вернусь к нему. Однако если формат обрабатываемых данных превышает 8 разрядов, а при разрядности АЦП даже 10 - это всегда, то байтный формат АЛУ понизит скорость обработки примерно раз в 5...10. А с учетом примитивной системы команд и до 20. Кстати, плотность кода - это не только скорость. Это еще и ПОТРЕБЛЕНИЕ. Каждая инструкция съедает энергию источника питания. Меньше инструкций - экономичнее устройство...
Кроме того, на PIC24FJ256GA70x цена даже ниже, чем на 42-ые 18-е ПИКи.
Если человек пишет на АСМе, то зачем плодить геморрой?
И причем тут ДИП, если элементарно можно запаять TQFP на переходную плату с PLS-ами в ряд или квадратом.

Но к теме. Нынче выходной, поэтому продолжу свой флуд для интересующихся.
Для утренней разминки приведу программу извлечения квадратного корня из 32 разрядного числа. Это базовая функция при вычислении мгновенного амплитудного значения синусоидального сигнала.
Код:
;--- SQRT (W1:W0 -> W0)
SQRT:
   mov      # 0x8000, W5
   clr      W6
LpSq:
   ior      W6, W5, W6
   mul.uu      W6, W6, W2
   sub      W0, W2, W4
   subb      W1, W3, W4
   btss      SR, # C
   sub      W6, W5, W6
   lsr      W5, W5
   bra      NC, LpSq
   mov      W6, W0
   return
;----------

Алгоритм последовательных приближений.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Сб янв 12, 2019 12:25:11

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

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Сб янв 12, 2019 14:01:41

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

Добавлено after 1 hour 24 minutes 28 seconds:
Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC33)
Про АЦП в скоростных семействах 16-битной платформы.
В значительной части этих МК имеет место быть один или два АЦП с ЧЕТЫРЬМЯ УВХ.
Для тех задач, где очень важен одновременный захват аналогового сигнала, требуется МК с несколькими отдельными АЦП. Альтернативой может быть многоканальный УВХ, когда захват происходит во всех УВХ одновременно, а преобразование последовательно (канал за каналом подряд).
Например мы решили сделать приемник с магнитной антенной (RFID, например), где собственно антенна представляет из себя две катушки, которые накачивают либо синфазно, либо противофазно, реализуя тем самым две диаграммы - "ноль" и "восьмерка", каждая из которых обеспечивает накачку меток в разных проекциях этих меток на антенну. Принимаемый в каждой катушке сигнал требует МАТРИЦИРОВАНИЯ, то есть сложения и вычитания, чтобы обеспечить прием этими же самыми "нулем" и "восьмеркой".
Можно конечно сделать аналоговое матрицирование, но это не по-пацански. Схемотехнически проще сложить и вычесть МАССИВЫ двух каналов АЦП, к которым подключены наши два приемных канала.
Однако, для того, чтобы иметь право так поступать с массивами, семплирование сигналов в каждом канале должно быть строго синхронным с другим.
Вот тут и пригодится многоканальный УВХ.
Стоит сказать, что включение такого УВХ ограничивает разрядность АЦП (только 10 разрядов), а так же кратно уменьшает рейт АЦП (максимальная скорость для 10 разрядов - 1,1 мспс, для двух УВХ в одновременном режиме - 550 кспс, а для всех 4-х УВХ - 275 кспс, соответственно). 12-битный режим имеет рейт 550 кспс.
Так же есть возможность сразу разбрасывать каналы УВХ по своим массивам, но не более 127 отсчетов в один массив (при использовании ДМА).
100 мипсовое семейство уже содержит отдельные АЦП (до 3х) с одноканальными УВХ, зато рейт возрос до более чем 3 мспс с возможностью интерлива (конвейерного преобразования с кратным увеличением рейта сразу 2 или 3 АЦП).

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Сб янв 12, 2019 22:16:18

не. не. тема полезная. а КРАМ-у спасибо что делаете такое для людей. :shock:
ПИК24 действительно не нужен под мои задачи. даже одна задача.
но нет гарантии что в будущем это задача не появиться.

к примеру недавно думали над одним проектом где требовалось делать вычисления в реальном времени, по формуле таблицы пифагора. там уже ясен пень пик18 курить будет.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Вс янв 13, 2019 07:03:09

Как там у Евстигнеева в "Берегись автомобиля":
Не пора ли, друзья мои, нам замахнуться на Вильяма, понимаете, нашего Шекспира!

:)))
Модуль PTG (PERIPHERAL TRIGGER GENERATOR)
Прямо скажу, мой нынешний выбор этой платформы процентов на 50, если не больше, мотивирован этим модулем.
Этот секвенсер по сути является периферийным ко-процессором микроконтроллера.
Я достаточно долго вертел этот модуль в голове, прежде чем нашел весьма удобную форму взаимодействия с ним в коде.
Итак.
Этот модуль представляет из себя 16 или 32 (зависит от "жирности" конкретного МК) ячейки для инструкций модуля.
Эти инструкции исполняются последовательно, точно так же, как исполняется код из программного флеша МК.
Инструкции могут управлять периферией, могут управляться ОТ периферии, могут управлять самим модулем PTG, включая ветвление исполняемой модулем программы.
Тактирование модуля в целом осуществляется от разных источников на выбор:
- от системных клоков контроллера (тактовая частота периферии, равная половине частоты осциллятора)
- от самого осциллятора (т.е. в 2 раза быстрее, чем работает остальная периферия)
- от клоков таймеров (обычно 1, 2 и 3-его), т.е. после их селекторов выбора тактирования и их предделителей.
- от тактовой частоты АЦП (Tad)
Любое выбранное тактирование проходит через предделитель с коэффициентом деления от 1 до 32 с шагом в 1.
Все формируемые модулем сигналы управления периферией могут иметь длительность от 1 до 16 клоков самого модуля (общая для всех сигналов установка).
Модуль имеет собственные:
- 2 таймера задержки
- 2 счетчика циклов исполнения
- 1 регистр задержки темпа исполнения
- 1 вачдог
- 1 регистр константы установки счетчиков/таймеров модуля
- 1 регистр константы шага настройки счетчиков/таймеров модуля
- 1 регистр константы-литерала для записи в регистр другой периферии
На базе таймеров делаются задержки. На базе счетчиков делаются циклы исполнения. На базе регистра задержки выполняется изменение темпа исполнения. Вачдог нужен для решения вопросов с зависаниями при ожидании событий ОТ периферии. Константы позволяют увеличивать установку таймеров и счетчиков на величину этой константы, а так же просто устанавливать значение в них. Ну и регистр литерала для установки мультиплексора АЦП (только первого, если модулей АЦП больше одного). Так же регистр литерала я использую для чтения его из кода МК, чтобы передать какой либо параметр в ОЗУ.
Команды (инструкции) модуля:
PTGCTRL
опции команды:
- включить/выключить задержку темпа исполнения инструкций (из регистра задержки)
- старт таймера 0 или таймера 1 модуля и ожидание его переполнения (задержка без изменения темпа исполнения инструкций модуля)
- ожидание софт-старта (модуль остановится в ожидании установки бита в своем регистре управления)
- копирование текущего содержимого одного из счетчиков модуля в регистр мультиплексора АЦП
- копирование константы-литерала в регистр мультиплексора АЦП
- генерация широковещательного (Broadcast Trigger) события для выбранного списка периферии (синхронный запуск)
PTGADD
опции команды:
- суммирование константы настройки с одним из регистров модуля: таймеры, счетчики, константа-литерал, регистр задержки
PTGCOPY
опции команды:
- запись константы установки в один из регистров модуля: таймеры, счетчики, константа-литерал, регистр задержки
PTGWHI/PTGWLO
опции команды:
- ожидание восходящего/нисходящего фронтов от периферийных модулей (на выбор из списка указывается код периферийного модуля). Это модули fast-PWM, OutputCompare, InputCapture, компараторы, событие завершения преобразования АЦП, внешнее прерывание.
PTGIRQ
опции команды:
- генерация собственных прерываний (по одному из четырех векторов на выбор - указывается в опции команды)
PTGTRIG
опции команды:
- генерация событий синхронизации/триггеров (это разные опции) внешней периферии из списка (указывается в опции команды). Это индивидуальный запуск/тактирование периферии.
В список входят модули OutputCompare, fast-PWM, АЦП, маски мультиплексоров компараторов/операционных усилителей.
PTGSTRB - копирование кода самой опции команды в мультиплексор УВХ АЦП
PTGJMP - безусловный переход на одну из инструкций модуля по номеру инструкции в опции команды
PTGJMPC0 - условный переход по номеру инструкции (указан в опции команды) или продолжение исполнения с одновременным инкрементом счетчика 0 (создание циклов исполнения)
PTGJMPC1 - тоже самое, но для счетчика 1

Я написал специальный блок дефайнов для системы команд и опций модуля, который позволил изобразить программу модуля в виде обычной таблицы. Этих таблиц может быть несколько. А в исполняемом коде написал функцию инициализации модуля, которая разворачивает одну из выбранных таблиц (входной указатель для функции) в регистры модуля PTG.
В результате все программирование модуля сводится к простому написанию отлично читаемых инструкций. Точно как написание кода на АСМе для самого МК.
Однако, прежде чем писать этот код для модуля, я рисую в Splan-е блок-схему программы модуля со всеми ветвлениями и циклами. Это позволяет хорошо ориентироваться даже в очень сложных временных диаграммах формируемых модулем при взаимодействии с периферией.

Блок дефайнов я позволю себе привести, но он, естественно, не является догмой. Кто-то может его модифицировать/уточнить под себя.
Код:
.equ   PTGCTRL,   0b00000000
;---опции PTGCTRL
.equ   DisStepDel,   0b0010
.equ   EnStepDel,   0b0110
.equ   StartTmr0,   0b1000
.equ   StartTmr1,   0b1001
.equ   WaitSWTedge,   0b1011
.equ   WaitSWTlevel,   0b1010
.equ   CopyCnt0,   0b1100
.equ   CopyCnt1,   0b1101
.equ   CopyLit0,   0b1110
.equ   GenBTE,      0b1111
;----------
.equ   PTGADD,      0b00010000
.equ   PTGCOPY,   0b00011000
;---опции PTGADD/PTGCOPY
.equ   Counter0,   0b0000
.equ   Counter1,   0b0001
.equ   Timer0,      0b0010
.equ   Timer1,      0b0011
.equ   StepDelay,   0b0100
.equ   Literal0,   0b0101
;----------
.equ   PTGSTRB,   0b00100000
.equ   PTGWHI,      0b01000000
.equ   PTGWLO,      0b01010000
.equ   PTGIRQ,      0b01110000
.equ   PTGTRIG,   0b10000000
;---опции PTGTRIG
.equ   PWMSE,      0b0000
.equ   PWMMT,      0b0001
.equ   PWM1Int,   0b0010
.equ   PWM2Int,   0b0011
.equ   PWM3Int,   0b0100
.equ   PWM4Int,   0b0101
.equ   PWM5Int,   0b0110
.equ   OC1Tr,      0b0111
.equ   OC2Tr,      0b1000
.equ   IC1Tr,      0b1001
.equ   CMP1Tr,      0b1010
.equ   CMP2Tr,      0b1011
.equ   CMP3Tr,      0b1100
.equ   CMP4Tr,      0b1101
.equ   ADCdone,   0b1110
.equ   INT2ext,   0b1111
;----------
.equ   PTGJMP,      0b10100000
.equ   PTGJMPC0,   0b11000000
.equ   PTGJMPC1,   0b11100000


Пример самой таблицы-программы модуля:

Код:
TabPTGmode3:
;-----
.pword  (PTGWHI|IC1Tr)      ; step0    IC1->wait start PTG
.pword  (PTGTRIG|0)      ; step1    PTG->OC1
.pword  (PTGCTRL|GenBTE)   ; step2    PTG->OC3&OC4
.pword  (PTGCTRL|StartTmr0)   ; step3    period pump
.pword  (PTGJMPC0|2)      ; step4    counter of pump
.pword  (PTGIRQ|3)      ; step5    PTGIRQ3->start comp Tx->TMR7->IRQ TMR7->stop comp Tx
.pword  (PTGCTRL|StartTmr1)   ; step6    start delay to DMA-ADC
.pword  (PTGIRQ|0)      ; step7    PTGIRQ0->start DMA-ADC/stop comp Rx
.pword  (PTGADD|Literal0)   ; step8    Literal0+Adj->frame increment
.pword  (PTGJMPC1|29)      ; step9    counter of frame (if continuous goto 29 step)
.pword  (PTGWLO|OC1Tr)      ; step10   wait OC1
.pword  (PTGIRQ|1)      ; step11   PTGIRQ1->set next frame
.pword  0         ; step12
.pword  0         ; step13
.pword  (PTGCTRL|GenBTE)   ; step14  PTG->OC3&OC4(third frame of a period 50 Hz)
.pword  (PTGCTRL|StartTmr0)   ; step15  period pump
.pword  (PTGJMPC0|14)      ; step16  counter of pump
.pword  (PTGIRQ|3)      ; step17  PTGIRQ3->start comp Tx->TMR7->IRQ TMR7->stop comp Tx
.pword  (PTGCTRL|StartTmr1)   ; step18  start delay to DMA-ADC
.pword  (PTGIRQ|0)      ; step19  PTGIRQ0->start DMA-ADC/stop comp Rx
.pword  (PTGCTRL|EnStepDel)   ; step20
.pword  0         ; step21
.pword  0         ; step22
.pword  (PTGCTRL|DisStepDel)   ; step23
.pword  0         ; step24
.pword  0         ; step25
.pword  (PTGCOPY|Literal0)   ; step26  restore frame
.pword  (PTGIRQ|2)      ; step27  PTGIRQ2->set next 3 frames
.pword  (PTGJMP|0)      ; step28  go to start period
.pword  (PTGWLO|OC1Tr)      ; step29  wait OC1
.pword  (PTGIRQ|1)      ; step30  PTGIRQ1->set next frame
.pword  (PTGJMP|1)      ; step31  go to start second frame
;-----
.pword  0b1100         ; BTE-> OC3&OC4->pump
.pword  997         ; LIMT0=period pump=1000
.pword  45000         ; LIMT1=delay to ADC=770us
.pword  58000         ; LIMSD=1ms (for delay to end of 3-d frame)
.pword  tauPump      ; LIMC0=count of pump
.pword  1         ; LIMC1=count of frame
.pword  0         ; HOLD=LIMT0
.pword  1         ; ADJ=1
.pword  0         ; LITERAL0
;----------


Ну и код инициализации с указателем на таблицу в W0:

Код:
; W0=указатель на таблицу исполнения модуля PTG
PTGinit:
   clr      PTGCST
   clr      PTGCON
   clr      PTGQPTR
   mov      W0, W2
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE0
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE1
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE2
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE3
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE4
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE5
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE6
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE7
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, # 8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE8
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE9
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, # 8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE10
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE11
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE12
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE13
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE14
   mov      [W2++], W0
   mov      [W2++], W1
   sl      W1, #8, W1
   ior      W0, W1, W0
   mov      W0, PTGQUE15
   mov      [W2++], W0
   mov      W0, PTGBTE
   mov      [W2++], W0
   mov      W0, PTGT0LIM
   mov      [W2++], W1
   mov      W1, PTGT1LIM
   mov      [W2++], W0
   mov       W0, PTGSDLIM
   mov      [W2++], W0
   mov      W0, PTGC0LIM
   mov      [W2++], W0
   mov      W0, PTGC1LIM
   mov      [W2++], W0
   mov      W0, PTGHOLD
   mov      [W2++], W0
   mov      W0, PTGADJ
   mov      [W2], W0
   mov      W0, PTGL0
   bclr      IFS9, # PTG0IF
   bclr      IFS9, # PTG1IF
   bclr      IFS9, # PTG2IF
   bclr      IFS9, # PTG3IF
   bset      IEC9, # PTG0IE
   bset      IEC9, # PTG1IE
   bset      IEC9, # PTG2IE
   bset      IEC9, # PTG3IE
   bset      PTGCST, # PTGEN
   bset      PTGCST, # PTGSTRT
   return


Продолжение следует.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Вс янв 13, 2019 13:27:17

В качестве примера приведу фрагмент блок-схемы в Сплане, который послужил основой программы для PTG в одном из режимов серийного устройства:

Изображение

Тут: http://ww1.microchip.com/downloads/en/D ... 00669b.pdf приведены простые примеры использования модуля PTG.

Повторюсь. Этот модуль стоит того, чтобы его пощупать, даже если особых планов на 16-разрядную платформу Микрочипа не предвидится.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Вс апр 07, 2019 18:35:24

Поигрался и бросил PIC24. Есть новое 8 - ми разрядное семейство K42, там и IVT, и раздельное тактирование периферии, и CLC, и PPS, DMA, аппаратный CVD, АЦП с аппаратной обработкой выходного результата

Продолжу тему.
Сейчас достаточно модно ставить встроенные фильтры в АЦП контроллеров. Однако напомню, что почти все эти фильтры являются примитивным усреднением в скользящем окне. То есть суть есть КИХ ФНЧ с прямоугольным окном. Для тех, кто не в теме, напомню, что подобный ФНЧ имеет нули АЧХ ближе всего расположенные к частоте среза (то есть полоса пропускания у него В ПРЕДЕЛАХ ГЛАВНОГО ЛЕПЕСТКА самая узкая, однако уровень первого бокового лепестка составляет всего -12 дБ и далее достаточно медленно падает у последующих. Сиречь, такой ФНЧ имеет весьма посредственные характеристики подавления вне полосы.
Чтобы обеспечить низкий уровень боковых лепестков, применяют непрямоугольные оконные функции. Например, окно Хемминга или окно Блекмана, а также множество других оконных функций, включая оконные функции ФВЧ и полосовых фильтров.
В DSP-контроллерах для реализации таких фильтров используют базовую команду MAC, которая представляет из себя одноцикловое умножение двух операндов и одновременное их сложение с текущим содержимым накопительного аккумулятора DSP высокой разрядности (обычно 2...2,5 раза выше разрядности операндов). Таким образом, несложно сообразить, что ЛЮБОЙ КИХ фильтр (фильтр с конечной импульсной характеристикой - нерекурсивный фильтр в скользящем окне) реализуется простым повторением этой команды с одновременным смещением указателей операндов по ДВУМ МАССИВАМ - массива входных фильтруемых данных (скользящий буфер) и массива коэффициентов ОКОННОЙ ФУНКЦИИ, которая может быть расположена как в программном флеше, так и перегружена из флеша в ОЗУ.
В обсуждаемой тут платформе Микрочипа DSP ядро имеет два аккумулятора по 40 разрядов. А в новейших 100 МИПСовых МК этого семейства эти аккумуляторы имеют еще 5 уровневый стек, позволяющий на лету менять контекст для пяти параллельных (при вытесняющей многозадачности) DSP задач.
Команда MAC в этой платформе помимо основной задачи так же производит предвыборку операндов для следующего повтора команды.
В качестве регистров-операндов используется специальная группа РОНов (из имеющихся в АЛУ), так же специальная группа РОНов используется для указателей на массивы. Массивы-источники операндов могут находится только в разных разделах ОЗУ контроллера - так называемой X и Y области памяти. Так как адресное пространство ОЗУ, на которое отображен программный флеш, находится целиком в Х-области, то обычно коэффициенты оконной функции именно в этой области и размещают и во флеше и в ОЗУ, если их есть смысл туда копировать.
При реализации квадратурного приемника прямого преобразования, очень помогает наличие двух аккумуляторов. Один фильтрует косинусную (Re) компоненту сигнала, а другой - синусную (Im). то есть массив загруженный из АЦП перемножают на синус и косинус, формируя два квадратурных массива, а затем эти массивы фильтруют одинаковыми ФНЧ для получения двух квадратурных компонент. Корень квадратный из суммы этих компонент даст АМ детектор, а арктангенс отношения Im/Re даст нам ЧМ или ФМ детектор.
Кроме того, в паре с DSP ядром работает два отдельных AGU - Address Generation Units - для X и Y областей памяти. Эти модули позволяют сформировать скользящее окно в кольцевом буфере, просто указав начальный и конечный адреса кольцевого буфера, а так же текущий адрес начала окна. Простой инкремент указателей на этот буфер АВТОМАТИЧЕСКИ будет приводить к кольцевому чтению буфера от текущего начала скользящего окна. Таким образом, АЦП будет заполнять кольцевой буфер по кругу, а фильтр будет его читать в скользящем окне.
Так же модуль AGU имеет битреверсный режим доступа к массивам, что позволяет сильно упростить расчет БПФ.
Все это вместе позволяет создать очень плотный код для цифровой фильтрации и максимально реализовать скоростные характеристики МК.
Формат чисел в DSP - знаковые и беззнаковые целые и дробные с фиксированной запятой. Режим с дробными числами автоматически удерживает точку аккумулятора в формате 24.16 при использовании смешанных операндов: входные массивы АЦП - целые знаковые, коэффициенты окна - дробные знаковые формата 1.15 - диапазон 0,99997(0x7FFF)....-1(0x8000). При выгрузке целой части результата из аккумулятора в РОН есть режим автоматического округления до целого дробной части (инструкция SAC.R).

Собственно АЧХ фильтра - это просто таблица коэффициентов. Меняя таблицу для одного и того же тела фильтра, мы получаем разные АЧХ.
Про примеры кода - завтра.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Вт апр 09, 2019 20:03:16

Вот так выглядит КИХ ФНЧ с длиной окна 256 и окном Хэмминга (одна точка с окна - прореживание по выходу может быть любым: от расчета на каждый новый отсчет до полного обновления окна):
Код:
LPF:
   mov      #psvpage(TabHamming), W0
   mov      W0, DSRPAG
   mov      #psvoffset(TabHamming), W8
   mov      #arrInput, W10
   clr      A, [W8]+=2, W4, [W10]+=2, W5
   repeat      #255
      mac      W4*W5, A, [W8]+=2, W4, [W10]+=2, W5
   sftac      A, #6
   sac.r      A, W0
   mov      W0, output
   return
.......
.......
TabHamming:
.fixed   0.07672, 0.07686, 0.07728, 0.07798, 0.07896, 0.08022, 0.08176, 0.08357
.fixed   0.08566, 0.08802, 0.09066, 0.09357, 0.09675, 0.10020, 0.10392, 0.10789
.fixed   0.11213, 0.11663, 0.12138, 0.12639, 0.13165, 0.13715, 0.14290, 0.14889
.fixed   0.15511, 0.16157, 0.16826, 0.17517, 0.18230, 0.18965, 0.19720, 0.20497
.fixed   0.21294, 0.22110, 0.22946, 0.23801, 0.24674, 0.25564, 0.26472, 0.27396
.fixed   0.28337, 0.29292, 0.30263, 0.31248, 0.32247, 0.33259, 0.34283, 0.35320
.fixed   0.36367, 0.37425, 0.38493, 0.39571, 0.40657, 0.41751, 0.42852, 0.43960
.fixed   0.45074, 0.46193, 0.47317, 0.48445, 0.49577, 0.50710, 0.51846, 0.52983
.fixed   0.54120, 0.55258, 0.56394, 0.57529, 0.58661, 0.59791, 0.60917, 0.62039
.fixed   0.63156, 0.64267, 0.65372, 0.66469, 0.67559, 0.68641, 0.69714, 0.70777
.fixed   0.71830, 0.72872, 0.73902, 0.74921, 0.75926, 0.76918, 0.77896, 0.78859
.fixed   0.79808, 0.80740, 0.81656, 0.82555, 0.83437, 0.84301, 0.85146, 0.85972
.fixed   0.86779, 0.87566, 0.88332, 0.89078, 0.89801, 0.90504, 0.91183, 0.91841
.fixed   0.92475, 0.93085, 0.93672, 0.94235, 0.94773, 0.95286, 0.95774, 0.96237
.fixed   0.96674, 0.97085, 0.97469, 0.97828, 0.98159, 0.98464, 0.98741, 0.98991
.fixed   0.99214, 0.99409, 0.99577, 0.99717, 0.99828, 0.99912, 0.99968, 0.99996
.fixed   0.99996, 0.99968, 0.99912, 0.99828, 0.99717, 0.99577, 0.99409, 0.99214
.fixed   0.98991, 0.98741, 0.98464, 0.98159, 0.97828, 0.97469, 0.97085, 0.96674
.fixed   0.96237, 0.95774, 0.95286, 0.94773, 0.94235, 0.93672, 0.93085, 0.92475
.fixed   0.91841, 0.91183, 0.90504, 0.89801, 0.89078, 0.88332, 0.87566, 0.86779
.fixed   0.85972, 0.85146, 0.84301, 0.83437, 0.82555, 0.81656, 0.80740, 0.79808
.fixed   0.78859, 0.77896, 0.76918, 0.75926, 0.74921, 0.73902, 0.72872, 0.71830
.fixed   0.70777, 0.69714, 0.68641, 0.67559, 0.66469, 0.65372, 0.64267, 0.63156
.fixed   0.62039, 0.60917, 0.59791, 0.58661, 0.57529, 0.56394, 0.55258, 0.54120
.fixed   0.52983, 0.51846, 0.50710, 0.49577, 0.48445, 0.47317, 0.46193, 0.45074
.fixed   0.43960, 0.42852, 0.41751, 0.40657, 0.39571, 0.38493, 0.37425, 0.36367
.fixed   0.35320, 0.34283, 0.33259, 0.32247, 0.31248, 0.30263, 0.29292, 0.28337
.fixed   0.27396, 0.26472, 0.25564, 0.24674, 0.23801, 0.22946, 0.22110, 0.21294
.fixed   0.20497, 0.19720, 0.18965, 0.18230, 0.17517, 0.16826, 0.16157, 0.15511
.fixed   0.14889, 0.14290, 0.13715, 0.13165, 0.12639, 0.12138, 0.11663, 0.11213
.fixed   0.10789, 0.10392, 0.10020, 0.09675, 0.09357, 0.09066, 0.08802, 0.08566
.fixed   0.08357, 0.08176, 0.08022, 0.07896, 0.07798, 0.07728, 0.07686, 0.07672

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пн авг 16, 2021 12:25:16

КРАМ,
Приветствую Вас!
Очень ждем продолжения.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пн авг 16, 2021 13:41:26

Я сейчас делаю проект на двухядерном dsPIC33CH512MP208. Могу поделиться опытом, если интересно.
Речь может идти о работе в среде с 2 ядрами, включая раздельную и совместную отладку, программирование слейв-ядра из мастера и запуск слейва. Межядерный обмен через мейлбоксы (FIFO обмен я не использовал). Особенности работы с осцилляторами (их там по 2 на каждое ядро). Особенности работы с PWM высокого разрешения (250 пс).

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пн авг 16, 2021 14:17:49

Я сейчас делаю проект на двухядерном dsPIC33CH512MP208. Могу поделиться опытом, если интересно.

Это очень интересная тема. Буду благодарен за любую информацию/помощь по направлению dsPIC33.

Re: Тем, кто боится перейти с 8 на 16 разрядов (PIC24/dsPIC3

Пн мар 28, 2022 08:27:15

Уважаемый КРАМ!
Очень надеюсь, что Вы сможете мне помочь.
Раньше работал с dsPIC30F5013, сейчас делаю проект на dsPIC33CK128MP208. Проект исключительно на ассемблере.
Основную таблицу прерываний MPLAB X IDE v5.40 в связке с XC16 при компиляции отрабатывает и размещает как положено по адресам 0x004 – 0x01FF.
Однако альтернативную таблицу прерываний после компиляции я не вижу.
Регистры конфигурации программирую следующим образом:
.include "p33CK128MP208.inc"
.section __FSEC.sec, code
.pword 0xFF7DB5 ; BSEN=ON, AIVTDIS=ON
.section __FBSLIM.sec, code
.pword 0xFFF000 ; Boot Segment 0x0000 – 0x0FFF
Из описания dsPIC33CK128MP208 следует, что при таком раскладе альт. таблица должна разместиться по адресу 0x0C00 (начало последней страницы загрузчика).

Перепробовал все возможные варианты, описанные в руководстве по ассемблеру – ничего не получается, при работе в режиме симуляции альтернативная таблица отсутствует.
Все _OscillatorFail, …, _U1RXInterrupt, _AltOscillatorFail, …,_AltU1RXInterrupt и пр. расставил как положено.
Ответить