Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум разработчиков электроники ELECTRONIX.ru _ PIC _ про PCLATH вопрос

Автор: balk Aug 14 2018, 15:35

имеется asm-программа .
в MPLAB IDE 8.33 запущен отладчик MPLAB SIM.
двигаясь по шагам , перехожу на подпрограмму с адреса 0050 на адрес 0140.
в окне WATCH наблюдаю изменение PCL на 40, а PCLATH почему-то остается в 00,
хотя отладчик двигается дальше 0142.. и в PCLATH я ожидал видеть 01.

Автор: Smen Aug 15 2018, 04:49

Цитата(balk @ Aug 14 2018, 19:35) *
в PCLATH я ожидал видеть 01.
Вы неправильно понимаете смысл регистра PCLATH.
01 (так понимаю, это - хексы, поэтому не забывайте указывать 01h, или 0x01, и т.п.) у Вас в старшем регистре програмного счётчика.
PCLATH используется, когда опкод не содержит значение для в/у регистра.
Тогда предварительно надо в PCLATH записать значение, которое будет переписано в старший регистр програмного счётчика, при выполнении команд с таким опкодом.
Ну, и как принято говорить: читайте даташит. rolleyes.gif
Там всё очень хорошо разрисовано (за что люблю Майкрочип).

Автор: balk Aug 15 2018, 06:42

да, спасибо, как водится, пока 5 раз одно и тоже в даташите не прочитаешь, не поймешь.
добавил команду MOVF PCL и увидел в PCLATH реальный сегмент адреса.
тема собственно меня забеспокоила потому, что в вызове подпрограммы, которая размещается
в произвольном месте присутствует еще подпрограмма с т.н. вычисляемым переходом ADDWF PCL,
в результате которого у меня вместо 0318h происходит перескок на 0018h

Автор: Smen Aug 15 2018, 07:19

Цитата(balk @ Aug 15 2018, 10:42) *
добавил команду MOVF PCL и увидел в PCLATH реальный сегмент адреса
Фигня какая-то.
В том-то весь и фокус, что операции с програмным счётчиком никак не влияют на содержимое регистра PCLATH.
Что туда запишите, то там и будет находиться до следующей перезаписи.
Реальный сегмент находится в PCH.

Цитата(balk @ Aug 15 2018, 10:42) *
подпрограммы, которая размещается в произвольном месте
Если в произвольном, то надо делать пару десятков строк дополнительного кода.
В двух словах так:
Сперва пишите в PCLATH старшую половину адреса метки начала таблицы переходов.
Затем производите сложение PCL с переменной перехода, но с результатом в аккумулятор.
Если поднят флаг переноса, инкрементируете PCLATH.
Опять производите сложение с PCL, но уже результат в регистр.
Если необходимо сократить код и/или повысить быстродействие (т.е. сократить количество команд), есть вариант размещать таблицу переходов строго в пределах 256-строчного сегмента адресов (чтобы при сложении PCL гарантировано не было переполнения).


Автор: balk Aug 15 2018, 08:25

Цитата(Smen @ Aug 15 2018, 11:19) *
В том-то весь и фокус, что операции с програмным счётчиком никак не влияют на содержимое регистра PCLATH.

влияют
вот даташит говорит, что содержимое PC транслируется в PCLATH при любом чтении PC.
the upper two bytes of the program
counter are transferred to PCLATH and PCLATU by an
operation that reads PCL.
проверьте в отладчике , если сомневаетесь.

Автор: Smen Aug 15 2018, 08:33

Цитата(balk @ Aug 15 2018, 13:25) *
даташит говорит
Давайте-ка по прядку.
Что у Вас за камень?

Автор: balk Aug 15 2018, 08:34

Цитата(Smen @ Aug 15 2018, 11:19) *
Реальный сегмент находится в PCH.

что такое PCH ? не нахожу в даташите на PIC18F2550
кстати, в отладчике среди SFR имеется PCLAT , тоже не понятно что это, ибо в даташите тоже не вижу,
по разрядам вроде соответствует счетчику, но изменяется тоже только в пределах 256



Автор: Smen Aug 15 2018, 09:58

Цитата(balk @ Aug 15 2018, 12:34) *
на PIC18F2550
Тогда понятно.
Я говорил про 12-16 серии. Там такого не было, насколько помню.
В 18 подшаманили.

Цитата(balk @ Aug 15 2018, 12:34) *
что такое PCH
На десять строк выше Вашей цитаты. rolleyes.gif

Цитата(balk @ Aug 15 2018, 12:34) *
среди SFR имеется PCLAT
Это, видимо PCLATH и PCLATU вместе взятые.
Разрядов-то сколько?
Такая же фигня и с TMR1H и TMR1L, например.
Удобнее смотреть целиком (ИМХО, разумеется).

Автор: balk Aug 17 2018, 06:44

Smen спасибо за содействие

с PCLATH я пока обошелся авантюрно-
перед ADDWF PCL выставил один оператор
MOVFF TOSH,PCLATH
и он меня спасает, если таблица и ее вызов находятся в одном сегменте.
пока для простой отладки мне достаточно.

PCLAT

Цитата(Smen @ Aug 15 2018, 13:58) *
Это, видимо PCLATH и PCLATU вместе взятые.

видимо, не так. адреса разные.
а у PCL и PCLAT один и тот же адрес FF9, но разрядность у PCLAT 0x000000,
хотя изменения почему происходят только в младшем байте.
ну как водится со временем можно разобраться , если будет практическая необходимость.

Автор: Smen Aug 17 2018, 07:46

Цитата(balk @ Aug 17 2018, 10:44) *
MOVFF TOSH,PCLATH
Как-то совсем авантюрно. rolleyes.gif
Это сперва должен быть вызов ПП.
А чем не устраивает обычный
Код
        movlw  hight Label
        movwf  PCLATH


Цитата(balk @ Aug 17 2018, 10:44) *
видимо, не так. адреса разные
Да какие адреса? Это же виртуальный регистр.
Он существует только в отладчике для визуального удобства восприятия.
Судя по разрядности, это PCLATU + PCLATH + PCL

Автор: balk Aug 18 2018, 09:18

Цитата(Smen @ Aug 17 2018, 11:46) *
А чем не устраивает обычный
Код
        movlw  hight Label
        movwf  PCLATH

не совсем понимаю, что кроется под hight label.
мой замысел был таков
от строки вызова call pprog перехожу
к метке pprog ( в этом же сегменте)
делаю MOFF TOSH,PCLATH - записываю в PCLATH код сегмента вызывателя, чтоб потом
через ADDWF PCL и соответствующий retlw вернуться именно к вызывателю, а
не к вызывателю вызывателя, находящегося в другом сегменте



Цитата(Smen @ Aug 17 2018, 11:46) *
Да какие адреса? Это же виртуальный регистр.

это просто констатация того, что изображает отладчик

Автор: Марк_Я Aug 18 2018, 09:40

Цитата(balk @ Aug 18 2018, 12:18) *
не совсем понимаю, что кроется под hight label.

Под hight label кроется номер сегмента, в котором размещена таблица.
Если таблица имеет размер более одного сегмента, то hight label нужно предварительно вычислить.
При выполнении команды RETLW в таблице, возврат произойдет БЕЗ ПРИВЯЗКИ К PCLATH, поскольку стек имеет ПОЛНУЮ РАЗРЯДНОСТЬ счетчика команд.
Из чего следует, что Ваши выкрутасы с вершиной стека не имеют никакого смысла и лишь приведут к разрушению стека.
Регистр PCLATH - это просто буфер, с помощью которого синхронизируют изменение младшего байта счетчика команд с изменением старшего байта того же счетчика.
Никакого отношения PCLATH не имеет к самому PC (PCL:PCH), который собственно и управляет выборкой из программного флеша очередной команды.

Цитата
5.1.1 PROGRAM COUNTER
The Program Counter (PC) specifies the address of the
instruction to fetch for execution. The PC is 21 bits wide
and is contained in three separate 8-bit registers. The
low byte, known as the PCL register, is both readable
and writable. The high byte, or PCH register, contains
the PC<15:8> bits; it is not directly readable or writable.
Updates to the PCH register are performed through the
PCLATH register. The upper byte is called PCU. This
register contains the PC<20:16> bits; it is also not
directly readable or writable. Updates to the PCU
register are performed through the PCLATU register.
The contents of PCLATH and PCLATU are transferred
to the program counter by any operation that writes
PCL. Similarly, the upper two bytes of the program
counter are transferred to PCLATH and PCLATU by an
operation that reads PCL. This is useful for computed
offsets to the PC (see Section 5.1.4.1 ”Computed
GOTO”).

Автор: Smen Aug 20 2018, 05:17

Цитата(balk @ Aug 18 2018, 14:18) *
что кроется под hight label
Старший (точнее средний) байт адреса метки (т.е. то, что должно находиться в PCLATH). rolleyes.gif
Выше я расписывал алгоритм.

Цитата(Марк_Я @ Aug 18 2018, 14:40) *
При выполнении команды RETLW в таблице, возврат произойдет БЕЗ ПРИВЯЗКИ К PCLATH
Для retlw PCLATH не нужен, но он необходим при переходе на этот retlw.
И никакого разрушения стэка быть не должно, хотя я тоже считаю, что данная конструкция "через Ж".

balk, если у Вас вся таблица только из retlw (т.е. долько данные), то 18 семейство позволяет использовать специальные команды табличного чтения.
Может Вам посмотреть в эту сторону?

Автор: Марк_Я Aug 20 2018, 06:28

Цитата(Smen @ Aug 20 2018, 08:17) *
18 семейство позволяет

Нынче и все относительно новые 12...16-ые тоже позволяют. Причем даже проще, чем 18-ые. Флеш доступен, начиная с адреса оперативной памяти 0x8000.

Автор: Smen Aug 20 2018, 06:36

У ТС 18F2550. rolleyes.gif

Автор: Марк_Я Aug 20 2018, 06:39

Я в курсе. Речь шла о Вашем упоминании.

Автор: balk Aug 22 2018, 16:08

Спасибо, друзья , за ценные замечания !
всё-таки один момент мне не стал понятнее,
как по команде ADDWF PCL программа перейдет на нужную RETLW, если при
выполнении ADDWF произойдет запись в PCH из PCLATH, в котором адресный байт другого сегмента. ?

Цитата(Марк_Я @ Aug 18 2018, 13:40) *
При выполнении команды RETLW в таблице, возврат произойдет БЕЗ ПРИВЯЗКИ К PCLATH,

в том то и дело , что до RETLW не доходим, а срываемся в другой сегмент.
вот собственно хребет , который всё наглядно может продемонстрировать
#include <p18f2550.inc>
org 0
goto start
nop
nop
nop
nop

org 0x20
start
call module

org 0x100
table
addwf PCL,1,0
retlw 0x50
retlw 0xde
retlw 0x62
retlw 0xc2
retlw 0xcc
retlw 0xc1

module
movlw 0x06
call table
nop
nop
END
после addwf программа перепрыгивает на выделенный жирным nop ,
а не возвращается в module.

Автор: Smen Aug 23 2018, 10:26

Цитата(balk @ Aug 22 2018, 21:08) *
после addwf программа перепрыгивает на выделенный жирным nop
В PCLATH - ноль (а в реале может быть любое число, поскольку нет инициализации регистра), вот он и подставляется в старший байт адреса.
Что ж тут непонятного?
Вставьте перед movlw
Код
            mowlw  high table
            movwf  PCLATH,0

И попадёте куда нужно.
P.S.: Только конструкция всё-равно кривая.
И для записи листинга программы на форуме пользуйтесь тэгом code (см. кнопочки вверху окна сообщения).


Автор: balk Aug 27 2018, 13:06

спасибо! вопросы остаются, но свернём тему , чтоб по второму кругу не начинать.

Автор: balk Aug 28 2018, 12:51

Цитата(balk @ Aug 27 2018, 17:06) *
вопросы остаются

Smenв смежной теме Вы предложили вернуться к PCLATH.
Кстати вопрос у меня остался такой
в Вашем коде
Код
            movlw  high table
            movwf  PCLATH,0

используются две команды, кроме того ещё задействован регистр W, который должен передавать в таблицу
вектор перехода, соответственно нужно предусматривать дополнительные манипуляции с W.
В коде
Код
            movff tosh,pclath
            addwf pcl,1,0

не нахожу ничего такого, чем бы он уступал Вашему .

Автор: Smen Aug 28 2018, 13:12

Цитата(balk @ Aug 28 2018, 16:51) *
Вы предложили вернуться к PCLATH
Возвращаться я не предлагал, мне просто показалась несколько странной последовательность Ваших действий. rolleyes.gif

Цитата(balk @ Aug 28 2018, 16:51) *
не нахожу ничего такого, чем бы он уступал Вашему
Команда movff занимает два МЦ и два слова памяти программ, ровно столько же, сколько и в/у две команды (читайте уже наконец даташит), так что с точки зрения времени выполнения/размера обе конструкции одинаковы.
А вот относительно логики. rolleyes.gif
В моей последовательности загружается адрес таблицы, а в Вашей, указатель стека. Разницу чувствуете?
Насчёт волнений по поводу аккумулятора, вообще не понятно. На то он и аккумулятор, что б его активно использовать.
У Вас следом пойдёт ещё одна movlw, так какая разница, что там в аккумуляторе будет находиться?

Автор: balk Aug 28 2018, 13:36

Цитата(Smen @ Aug 28 2018, 17:12) *
Команда movff занимает два МЦ

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



Цитата(Smen @ Aug 28 2018, 17:12) *
В моей последовательности загружается адрес таблицы, а в Вашей, указатель стека. Разницу чувствуете?

Извините, здесь, должен признаться, не чувствую разницы. Был бы признателен за разъяснения


и мне кажется в этом контексте уместней говорить не "загружается", а читается

Автор: Smen Aug 29 2018, 05:26

Цитата(balk @ Aug 28 2018, 18:36) *
я имел ввиду краткость кода
Если Вы имеете ввиду про то, что в/у команда пишется в одну строчку, так какая разница, будет в программе 3000 строк, или 3001? rolleyes.gif
Вообще, говорить о краткости листинга, используя АСМ как-то стрёмно. Переходите уж тогда на СИ.

Про "команды, которые нужно внедрить для манипуляций с аккумулятором" я что-то вообще не понял.
Что Вы там ещё внедрять хотите? Кроме в/у двух команд ничего не требуется.

Кстати, Ваши двойные вызовы ПП вовсе не сокращают листинг, да вдобавок ещё и стэк забивают, а ведь он не резиновый.


Цитата(balk @ Aug 28 2018, 18:36) *
не чувствую разницы
Это очень плохо. Попробую ещё раз пояснить.
В PCLATH необходимо загрузить (именно "загрузить") адрес "таблицы переходов".
В моём примере он туда и загружается, а в Вашем в него загружается указатель вершины стэка, в котором оказывается нужное значение.
Сейчас это сработало, но когда-нибудь может в указателе оказаться совсем не то, что нужно, а вот адрес таблицы всегда останется адресом.
Я уже молчу о совместимости кода с другими семействами.
И если Вы возразите, что никуда его переносить не собираетесь, то я отвечу, что тогда Вам вообще нужно использовать команды табличного чтения.

Автор: balk Aug 29 2018, 06:57

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

Автор: Марк_Я Aug 30 2018, 05:29

Цитата(balk @ Aug 29 2018, 09:57) *
приятно получить

Чуть добавлю.
Смысл команды movff совсем не в краткости записи. Эта команда, не модифицирует контекст (аккумулятор и флаги состояния АЛУ). И именно в таком качестве ее следует применять. Если аккумулятор и флаги могут быть произвольно изменены, то нет никакого практического смысла в применении movff.

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)