Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вычисляемый GOTO на pic18f45j10
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > PIC
=GM=
Понадобилось написать на ассемблере вычисляемый GOTO, аналог switch k на си, с максимально возможным быстодействием. Пока дошёл до такого кода
Код
       movlw   HIGH v8goto
       movwf   PCLATH
       movf    k,w
       addwf   k,w
       addwf   PCL,1
v8goto
       bra     v8mf0     ;k=00
       bra     v8mf1     ;k=01
       bra     v8mf0     ;k=02-MF2(cylinder 1 & 5)
       bra     v8mf0     ;k=03
       bra     v8mf0     ;k=04
и т.д.

Проблема состоит в размещении кода в любом месте программы. После компиляции смотрю, где лежит таблица переходов, если не пересекает 256-байтную границу, то всё в порядке. Интересно бы посмотреть, как кто делает.
volodya
Цитата(=GM= @ May 19 2008, 18:31) *
Понадобилось написать на ассемблере вычисляемый GOTO, аналог switch k на си, с максимально возможным быстодействием. Пока дошёл до такого кода
Код
       movlw   HIGH v8goto
       movwf   PCLATH
       movf    k,w
       addwf   k,w
       addwf   PCL,1
v8goto
       bra     v8mf0    ;k=00
       bra     v8mf1    ;k=01
       bra     v8mf0    ;k=02-MF2(cylinder 1 & 5)
       bra     v8mf0    ;k=03
       bra     v8mf0    ;k=04
и т.д.

Проблема состоит в размещении кода в любом месте программы. После компиляции смотрю, где лежит таблица переходов, если не пересекает 256-байтную границу, то всё в порядке. Интересно бы посмотреть, как кто делает.


Попробуйте иначе:

Код
       movlw   HIGH v8goto
       movwf   PCLATH
               movlw  LOW v8goto
       addwf   k,w
       addwf   k,w
               btfsc    STATUS, C
               incf PCTATH, f
       movwf   PCL
v8goto
       bra     v8mf0    ;k=00
       bra     v8mf1    ;k=01
       bra     v8mf0    ;k=02-MF2(cylinder 1 & 5)
       bra     v8mf0    ;k=03
       bra     v8mf0    ;k=04
и т.д.

теперь граница = 0xffff если больше то PCLATH-UP добавить.
=GM=
Цитата(volodya @ May 21 2008, 05:44) *
Попробуйте иначе:
Код
   movlw  LOW v8goto
   addwf  k,w
   addwf  k,w
   btfsc  STATUS, C
   incf   PCTATH, f
   movwf  PCL

теперь граница = 0xffff если больше то PCLATH-UP добавить.

Вы считаете, что после первого сложения переноса никогда не будет, а может быть только после второго? Пусть например, LOW v8goto=0xFF, а k=2, тогда после первого сложения будет перенос, а у вас он не учитывается.
volodya
Цитата(=GM= @ May 21 2008, 13:23) *
Вы считаете, что после первого сложения переноса никогда не будет, а может быть только после второго? Пусть например, LOW v8goto=0xFF, а k=2, тогда после первого сложения будет перенос, а у вас он не учитывается.


LOW adr_ROM для команды всегда четный - поскольку команды P18 16(32)бит,
в первом сложении перенос исключен.
=GM=
Цитата(volodya @ May 22 2008, 11:13) *
LOW adr_ROM для команды всегда чётный - поскольку команды P18 16(32)бит, в первом сложении перенос исключен


Выше был выбран неудачный пример, пусть LOW v8goto=0xF0, а k=19, вполне реальные числа, у меня три таких вычисляемых GOTO с Кмах=36, 36 и 60. Как видите, адрес чётный и есть перенос при первом сложении.

Не скажу, что я не вижу способов решения задачи, они есть, но все они какие-то громоздкие, крокозябистые...или у меня руки кривые, или это следствие корявой архитектуры и системы команд для пиков, одно из двух (:-).

Опять же, для расчёта количества оборотов двигателя в минуту написал программу деления двух 32-битных чисел, еле поместился в 900 с лишком машинных циклов, ну можно скинуть сотню-другую циклов, но...как-то некрасиво всё выходит (:-(.
volodya
Цитата(=GM= @ May 22 2008, 16:03) *
Выше был выбран неудачный пример, пусть LOW v8goto=0xF0, а k=19, вполне реальные числа, у меня три таких вычисляемых GOTO с Кмах=36, 36 и 60. Как видите, адрес чётный и есть перенос при первом сложении.

Не скажу, что я не вижу способов решения задачи, они есть, но все они какие-то громоздкие, крокозябистые...или у меня руки кривые, или это следствие корявой архитектуры и системы команд для пиков, одно из двух (:-).

Опять же, для расчёта количества оборотов двигателя в минуту написал программу деления двух 32-битных чисел, еле поместился в 900 с лишком машинных циклов, ну можно скинуть сотню-другую циклов, но...как-то некрасиво всё выходит (:-(.


Да ВЫ правы корректнее
Код
       movlw   HIGH v8goto
       movwf   PCLATH
      
       bcf STATUS, C
       rlcf  k, w
       btfsc    STATUS, C      
               incf PCTATH, f  
      
        addlw  LOW v8goto      
        btfsc    STATUS, C
               incf PCTATH, f
       movwf   PCL
TablJMP code 0xYYY00  ;для принудительного расположения в ПЗУ программ
                                ;переносы можно упустить при к < 128
v8goto
       bra     v8mf0 ;k=00
       bra     v8mf1 ;k=01
       bra     v8mf0 ;k=02-MF2(cylinder 1 & 5)
       bra     v8mf0 ;k=03
       bra     v8mf0 ;k=04
и т.д.

Лучше стараться поместится в страницу 128 переодов и распологать принудительно внутри страници ПЗУ - тогда можно не принимать во внимение перенос - экономить такты и восплользоваться Вашим первым вариантом кода.
Архитектура имеет свои плюсы и минусы. Думаю спор о приемуществах и недостатках приведет к maniac.gif .
Хотя согласен с Вами - математика большой производительностью не блещет. Деление занимет много времени. - ограничение ситемы команд.
Тут наверное или мириться или менять CPU.
Удачи!
=GM=
Цитата(volodya @ May 23 2008, 03:59) *
Лучше стараться поместить в страницу 128 переходов и располагать принудительно внутри страницы ПЗУ - тогда можно не принимать во внимание перенос - экономить такты и воспользоваться Вашим первым вариантом кода


Пожалуй, воспользуюсь я вашим советом и размещу три таблицы в начале трёх страниц. С учётом того, что пока k<61 (а в обозримом будущем вряд ли будет больше) код получится более-менее приличный

Код
   movlw   HIGH v8goto
   movwf   PCLATH
   bcf     STATUS,C
   rlcf    k,w   ;k<128, no carry
   movwf   PCL,f

v8goto
   bra    v8mf0 ;k=00
   bra    v8mf1 ;k=01
   bra    v8mf0 ;k=02-MF2(cylinder 1 & 5)
   bra    v8mf0 ;k=03
   bra    v8mf0 ;k=04
и т.д.

Так лучше, чем мой первоначальный код, потому что здесь код вычисления перехода не обязательно размещать прямо перед таблицей. А в том коде ещё одна проблема возникнет с вычислением адреса перехода, если таблица займёт целую страницу (для k=128).
volodya
Цитата(=GM= @ May 23 2008, 18:10) *
Пожалуй, воспользуюсь я вашим советом и размещу три таблицы в начале трёх страниц. С учётом того, что пока k<61 (а в обозримом будущем вряд ли будет больше) код получится более-менее приличный

Код
   movlw   HIGH v8goto
   movwf   PCLATH
   bcf     STATUS,C
   rlcf    k,w ;k<128, no carry
   movwf   PCL,f

v8goto
   bra    v8mf0;k=00
   bra    v8mf1;k=01
   bra    v8mf0;k=02-MF2(cylinder 1 & 5)
   bra    v8mf0;k=03
   bra    v8mf0;k=04
и т.д.

Так лучше, чем мой первоначальный код, потому что здесь код вычисления перехода не обязательно размещать прямо перед таблицей. А в том коде ещё одна проблема возникнет с вычислением адреса перехода, если таблица займёт целую страницу (для k=128).



Может Вы спешили(и я зря повторюсь sad.gif ) - но перед меткой пропущен оператор :
Код
TablJMP code 0xYYY00;для принудительного расположения в ПЗУ программ

v8goto:

для линкера. Иначе фокус не прйдет.
=GM=
Цитата(volodya @ May 26 2008, 08:53) *
Может Вы спешили (и я зря повторяюсь) - но перед меткой пропущен оператор :
TablJMP code 0xYYY00;для принудительного расположения в ПЗУ программ для линкера. Иначе фокус не пройдет.

Всё нормально, спасибо. Просто там должно быть три таблицы, не хотел их все три писать, да и не надо вроде, а одна осталась по инерции...

Вот поискал на форуме и в сети программы реализации арифметики 16-24-32 разряда, в частности деление, и вы знаете, не так уж много нашёл, а то что нашёл, проигрывает по скорости моим программам, надо будет, пожалуй, открыть соответствующую тему, поделиться с народом, глядишь и сам что-то новенькое узнаю...
buka_2004
Для 18 серии еще возможен вот такой вариант на все случаи жизни и код будет перемещаемым, и размер k любой.
Код
    clrf    PCLATH
    rlcf    k, w
    btfsc    STATUS, C              ;это можно опустить если k<128
    incf    PCLATH, f            ;это можно опустить если k<128
    addlw    low    TAB_GOTO
    movlw    high  TAB_GOTO
    addwfc    PCLATH, f
    rlcf    k, w
    addlw    low    TAB_GOTO
    movwf    PCL

TAB_GOTO
    bra    L_1
    bra    L_2
...
ant333
Код
UART2_State_tbl
        bra        UART2_wt_strt
        bra        UART2_wait
        bra        UART2_reci

UART2_State_tbl_end
        if(high(UART2_State_tbl)!=high(UART2_State_tbl_end))
        error "UART2_State_tbl broken"
        endif
=GM=
Цитата(buka_2004 @ Jun 17 2008, 06:40) *
Для 18 серии еще возможен вот такой вариант на все случаи жизни, и код будет перемещаемым, и размер k любой.
Код
    clrf    PCLATH
    rlcf    k, w
    btfsc    STATUS, C        ;это можно опустить если k<128
    incf    PCLATH, f        ;это можно опустить если k<128

Здесь у вас возможна неуловимая ошибка во второй строке, если при выполнении фрагмента бит переноса будет установлен. Такие ошибки весьма опасны, поскольку их трудно отследить. Лучше код переписать так
Код
     clrf   PCLATH
     bcf    STATUS,C
     rlcf   k,w
     rlcf   PCLATH
и далее по тексту

Но код всё равно получается длинный, если сравнивать с моим последним вариантом, а стоит он у меня в прерывании.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.