PIC18, ASM - расширенный режим

PIC
PIC18 ASM — для начала — рассширенная система команд

В новых и большинстве старых контроллеров PIC18 есть возможность включить режим раширенной системы команд.
Какие особенности данного режима и как его можно использовать — в этой статье.
1. Режим расширенной системы комманд.

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

Данный режим включается установкой бита XINST в слове конфигурации:

CONFIG XINST=ON


Таким образом в процессе работы нет возможности переключаться из расширенного режима работы в стандартный и обратно.

В MPLAB надо также установить флажок в проекте.



Новый вид адресации.

Для команд обращения к ОЗУ — вида

ADDWF    f,d,a   
CLRF     f,a  


когда обращаемся к Access Bank ( a = 0 )

если f >= 60h то выбирается область SFR [ F60h — FFFh ]

если f < 60h то адрес вычисляется — [ FSR2 + f ]

т.е. адресация индексная со смещением f = [ 00h — 5Fh ]

Быстрый доступ к банку 0 теперь полностью* отсутствует

* в некоторых контроллерах доступ к банку 0 остаётся в диапазоне f = [ 60h-7Fh ]
так как область SFR у них только [ F80h — FFFh ]


Запись комманд с новым видом адресации тоже имеет новый вид.

ADDWF    [f],d   
CLRF     [f]  


Если FSR2 использовать как регистр указатель на стек данных, то получаем быстрый доступ к данным на вершине стека. Да забыл напомнить ведь не просто так FSR2 и вдруг организация стека, ведь надо данные выкладывать в стек (push) и снимать со стека (pop). На помощь приходит косвенная адресация в PIC18 (POSTDECx PREINCx).
MOVWF   POSTDEC2          ; push   W  
MOVFF   PRODL, POSTDEC2   ; push   PRODL
MOVFF   PREINC2, PRODL    ; pop    PRODL


Вот и так далее.

MOVLW   22h               ; W=22h
MOVWF   POSTDEC2          ; push   W 


Да записали байтик — число в стек — плохо получается используется регистр W.
Вот тут приходит на помощь одна из новых команд — она как раз заменяет эти две

PUSHL   22h               ; [FSR2--]=22h


Да вы будете правы большинство новых команд для этого и нужны, чтобы испоьзовать FSR2 как указатель стека данных. Будем постепенно знакомиться с ними.
Вот копирование внутри вершины стека и вне со стека.

MOVSS   [2],[3]               ; [FSR2 + 3]=[FSR2 + 2]
MOVSF   [2],PRODL             ; PRODL=[FSR2 + 2]

Инкремент и декремент регистров FSR будет нужен не только FSR2 для управлением стеком.

ADDFSR   FSR2,8               ; FSR2 = FSR2 + 8
SUBFSR   FSR2,10              ; FSR2 = FSR2 - 10


Инкремент и декремент FSR2 с возвратом из подпрограммы очень даже неплохо.

ADDULNK   8               ; FSR2 = FSR2 + 8  (+RETURN)
SUBULNK   10              ; FSR2 = FSR2 - 10 (+RETURN)


Так вот осталась одна команда и она к FSR регистрам не имеет никакого отношения.

CALLW          ; вызов подпрограммы PCL=W; PCH=PCLATH; PCU=PCLATU


Немного отвлекся от темы — к чему вот идет расказ.

2. Подпрограммы и стек данных.

И сразу полный пример который и будем разбирать!

LIST P=18F14K50             ;directive to define processor
    #include "P18F14K50.INC"    ;processor specific variable definitions
    #include "macro.inc"
    errorlevel    -207

    CONFIG    XINST=ON         

            UDATA   
gTempL      res     1
gTempH      res     1

stack       UDATA   0x100
            res     .128

;**** Reset vector ****
RST     CODE    0x0000
        goto    Main        ;go to start of main code

;**** Start of main program ****
Main:
        clr         BSR                 ; фиксируем BSR на странице 0
        scnend_lfsr FSR2, stack         ; FSR2 = последний адрес блока stack

        pushf   gTempH                  ; загрузка в стек параметра А - глоб перем
        pushf   gTempL
        pushl   .100                    ; загрузка в стек параметра В - число
        rcall   umul_16x8

; forever loop   
mxx:    goto    mxx       

;*******************************************
; procedure umul_16_8
;    in  A16,B8  ->  out  Res24
;
#define     pParamAH    [4]
#define     pParamAL    [3]
#define     pParamBL    [2]
#define     sLocalBL    [1]
 
#define     pResU        [4]
#define     pResH        [3]
#define     pResL        [2]
     
umul_16x8:
            pushs       [1]                  ; создаем лок перем = B
            mulff       pParamBL, pParamAL   ; AL * B
            movfs       PRODL, pResL         ; сохраняем рез умножения
            movfs       PRODH, pResH
            mulff       sLocalBL, pParamAH   ; AH * B
            addff       PRODL, pResH         ; добавляем к результату
            addffc      PRODH, pResU
            retulnk     1                    ; возврат с освобождением 1 байта

        END


Красиво смотрится, а вот забыл надо же не красивые макросы показать.

#define FSR0W   FSR0L
#define FSR1W   FSR1L
#define FSR2W   FSR2L

pushw   macro  
          movwf   POSTDEC2
        endm

pushf   macro   rf
          movff   rf, POSTDEC2
        endm

pushs   macro   rs
          movsf   rs, POSTDEC2
        endm

pushl_16 macro   rl
          pushl   high(rl)
          pushl   low(rl)
         endm

pushf_16 macro   rf
          movff   rf+1, POSTDEC2
          movff   rf, POSTDEC2
         endm

pushs_16 macro   rs
          movsf   rs, POSTDEC2
          movsf   rs, POSTDEC2
         endm

popw    macro
          movf    PREINC2, W
        endm

popf    macro   rf
          movff   PREINC2, rf
        endm

popf_16  macro   rf
          movff   PREINC2, rf
          movff   PREINC2, rf+1
         endm

movff_16 macro   rfs, rfd
          movff   rfs+1, rfd+1
          movff   rfs, rfd
        endm

movfs   macro   rfs, rsd
          movf    rfs, W
          movwf   rsd
        endm

mulff   macro   rfs, rfd
          movf    rfs, W
          mulwf   rfd
        endm

addff   macro   rfs, rfd
          movf    rfs, W
          addwf   rfd
        endm

addffc  macro   rfs, rfd
          movf    rfs, W
          addwfc  rfd
        endm

link    macro   ri
          subfsr FSR2,ri
        endm

retulnk macro   ri
          addulnk ri
        endm


Макросов больше чем надо для примера — да ничего потом пригодятся.

По программе — процедура имеет два параметра А-16 бит и В-8 бит а результат 24 бита.
Самое интересное что результат мы сохраняем там же в стеке в том же месте где и были параметры!
Да и еще раз да — это очень сильно похоже на внутренности языка программирования FORTH.
Все операции производятся на вершине стека.
(ностальгия — калькулятор МК61 — к слову у коллеги есть все еще рабочий и он им пользуется!)

По алгоритму программы итак все ясно.

Выводы данной части.

— Достаточно просто и понятно организуется стек данных постедством FSR2 (да когда система команд заточена под это!)
— Глобальным переменным выделено 256 байт (неплохо) в банке 0 и не дергаемся с банками. (если что-то большое то это уже массив и тут помогут другие FSR).
— В стеке можно не только передавать параметры, но и возвращать!!! И даже небольшие массивы.
— Многозадачка — каждой задаче по FSR2 и свой стек данных!
— и т. д.

Дополнительно по обращению к банкам.
Когда устанавливается расшитенный режим, то комманды вида

ADDWF    f,d,a   
CLRF     f,a 


при опускании параметра <а> замещаются

ADDWF    f,d,BANKED   
CLRF     f,BANKED  


т.е a=1

На сегодня достаточно, потом может быть еще статейки будут.

Сразу прошу извинить — я фанат ASM — и теоретик (документация,MPLAB) — практик (pickit2,LUT,...) только начинающий!
  • +2
  • 03 июня 2011, 11:55
  • XuMuK

Комментарии (32)

RSS свернуть / развернуть
… а какие максимальные частоты на которых работают PIC-и?
0
Для оценки скорости нужно смотреть на MIPS'ы (Мега Инстракшнс Пер Секонд), а не на МГц, т.к. в разных пиках разное количество тактов на цикл.

PIC10, PIC12 — до 1 MIPS
PIC12, PIC16 — до 5 MIPS (отдельные версии до 10)
PIC16 расширенные — до 8 MIPS
PIC18 — до 10, до 12, до 16 MIPS
PIC24, dsPIC — до 16, до 40, до 64 MIPS
PIC32 — до 80 MIPS

Кажется, ничего не напутал
+1
Мега Инстракшнс Пер Секонд
… каких именно инструкшн? если он одну асм инструкцию выполняет как 4 то 3/4 этих МИПСов самообман
0
Отдельных ассемблерных команд. Если у PIC'а 4 такта на машинный цикл и большинство команд выполняются за один цикл — то производительность его при тактовой 4МГц будет около 1MIPS (около — потому, что часть команд не одноцикловые). А, скажем, у 8051 — 1MIPS/12MHz, у AVR — 1MIPS/1MHz.
0
Не понял, о чем Вы.
1 MIPS — это один миллион инструкций в секунду в независимости от того, за сколько тактов выполняется каждая инструкция.
0
Блин. Как пост отредактировать? «вне зависимости» с ошибкой написал…
0
… вы правы, но както не эстетично, хочется имея кварц на 1.0 MHz, иметь и 1МИПС, ато и больше
0
Зачем? Какая разница-то?
0
Да пожалуйста! ARM в руки и вперед! Или Core 2, у него еще больше инструкций на такт)
0
… сморозил я однако :((, чета показалось мне что выполнение одной инструкции можно разбить, а кстать как там прерывания работают?
0
12-разрядные (PIC10 и т.п.) — нет прерываний
PIC12, PIC16 — один вектор на все источники
PIC18 — два вектора
PIC24, dsPIC, PIC32 — много векторов
0
Как в детском саду прям. Нет елочек, одна елочка, две елочки, много елочек!
0
Укажи заодно, сколько у них тактов на цикл.
0
Какая разница?

PIC10, PIC12, PIC14, PIC16, PIC18 — 4 такта
PIC24, dsPIC — 2 такта
PIC32 — 1 такт
0
… например чтоб подобрать соответствующий кварц
0
пики18 гдето около 40-48 мегагерц
ну и пик32 72-80 мегагерц
остальные не знаю
0
А сколько такстов у них машинный цикл?
0
4ре вроде бы
0
… нибось класcические
fetch
decode
execute
store
:))… только все остальные производители умудряются их выполнять параллельно
0
Для кого статью писал??!
Микроконтроллеры PIC. Вводная.
Надо кстати про МИПСы туда добавить…
0
ну и срань этот пиковский ассеблер… пробовал как-то из любопытства PIC10 закодить — под конец попривык, конечно, но как же все нелогично…
-2
может расскажите что показалось нелогичным? ато как то пользуемся и не в курсе…
0
касательно ассемблера — в первую очередь разные мнемоники для операций с регистрами и константами (movlw/movfw и пр.). по архитектуре тоже не все хорошо — разные банки, входные порты без защелки, один аккумулятор, один вектор прерывания… после x86 и AVR ассемблеров как-то скудно. ну и самое главное разные системы команд и архитектуры у разных семейств. у AVR портабельнее код
-1
вы о pic16? Ну да, там есть такие бяки с архитектурой. Но и свет клином не сошелся же на них.

А чем плохи разные мнемоники? как раз логично, видно откуда берутся данные. Иначе были бы проблемы как с чтением так и выполнением кода(включать телепатию и гадать что с этим делать, сразу брать или считать адресом)

команды разные, да. потому что разные семейства внутри устроены по разному(AVR вроде как все очень схожи, только список команд расширяется(не претендует на абсолютную истину, об AVR только из википедии знаю)). команды как минимум в 10,12,16,18 похожи и портируются без особых проблем
0
ну я не спорю, что может быть это и оправдано. просто после х86 и AVR ассемблеров показалось как-то «не так»
0
если нужны МИПСы, то не надо брать PIC. Архитектура упрощенная.
0
Какая связь архитектуры с МИПСами?
МК от Scenix (впоследствии Ubicom, в последствии Parallax) SX20, SX28 и т.п., имеющие архитектуру почти один в один, как у 12-разрядных ПИКов (т.е. самого младшего семейства), имели производительность в 100 МИПС (при 100 MHz тактовой)
0
Инструкции простые, операции через рабочий регистр. То что другие процы за одну команду делают, на пике делается 2-3 инструкциями, а то и больше. Разрядность данных 8бит. Математика на 8-битных данных размещается очень плохо, хотя бы 16бит надо, а лучше 32. Две 16битных переменных сложить — опять несколько инструкций. Получается, что 100мипс расходуются в пустую.
0
Глупости Вы пишете. Ваши слова: «То что другие процы за одну команду делают, на пике делается 2-3 инструкциями, а то и больше.» — можно спроецировать на любую архитектуру. Подменить недостаточное понимание программистом конкретной архитектуры или неумение использовать ее особенности (или использовать их к месту) термином «урощенная архитектура» — это простительно любителю, но не профессионалу.

Ну, а сравнивать МИПСы 8-битника и 32-битника — это уже «абы че ляпнуть», т.е. вообще не к теме.
+1
Если взять PIC12 и контроллер TI C2000 на одинаковой скорости по MIPS, работая только с 8 битными данными, решая равные задачи, угадайте, какой контроллер будет успевать поспать? А почему не PIC? потому что у С2000 более производительная архитектура. Конечно МИПСы 8битника и 32битника разные, но дело не только в битах
0
смеетесь? сравнивать 12й пик и нечто 32хбитное, имеющее DMA, аппаратный умножитель и устройство операций с плавающей точкой. Несколько разные «весовые категории», вам не кажется? если уж и сравнивать это, то с pic24 хотяб.H серию.
0
Выигрыш будет даже без использования DMA, умножителя и FPU. Архитектура пика очень минималистическая (я про младшие и средние) малое число команд, операции через аккумулятор, деление памяти на банки. Все это не просто так, а ради упрощения и уменьшения кристалла(заодно уменьшается потребление и стоимость производства). Периферия + управляющий контроллер в микрокорпусе малоногом, либо в паябельном корпусе и по демократичной цене. Да, у старших пиков больше производительность, они совершеннее младших и средних, но за те же деньги я могу поставить 32битный контроллер, который и ногой дергать сможет побыстрее и математику сделать проще и периферии скоростной имеет достаточно.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.