Привет!
Wed Apr 20 2005 22:50, Vadik Akimoff wrote to George Shepelev:
...
VA>>> Аналог лдира для произвольных мест во внешней 64кб памяти и блока VA>>> <=256 байт: VA>>> ld r4,X+ VA>>> st Y+,r4 VA>>> dec r5 VA>>> brne $-3 VA>>> Для произвольной длины блока dec заменить на sbiw
Итого имеем 4 цикла на пересылку и 3,012 (выгоднее 16-разрядное но без SBIW') на зацикливание. Т.е. 4 цикла на байт это предел совершенстовования.
Пересылки в памяти данных для PIC18 выглядят таким образом:
L1: movff postinc0,postinc1 ; 2 decfsz cnt+0,f ; 1 bra L1 ; 2 decfsz cnt+1,f bra L1
Пересылка занимает 2 цикла, зацикливание -- 3,012 цикла, в пределе -- 2 цикла. Итого 7 против 5 или 4 против 2-х. Для dsPIC ещё проще, там будет один цикл на слово без всякой оптимизации. Для PIC16 ноборот намного сложнее
-- там только один указатель и если нужна скорость работаем через буфер, но общий случай из-за банков выглядит довольно кучеряво и вряд ли так уже интересен.
...
VA> Hу вот речь идёт о конкретной задаче - сделать ldir во внешней памяти. VA> Аналог для авра приведён, приведи для пика. =)
Весь вопрос, что собственно за внешняя память? К существующим PIC16 и dsPIC параллельная внешняя память штатными средствами вообще не цепляется, к PIC18 можно подцепить внешнюю память программ; тебя интересует именно этот вариант? Если пересылка выполняется между памятью данных и памятью программ то в вышеуказанный пример добавляются лишь 2 цикла команды tblrd/tblwt. Если же хочется увидеть пересылку в рамках памяти программ, то я бы это сделал по аналогии с PIC16, работая через буфер:
L3 movff ptr1+0,tblptrl ; 2 movff ptr1+1,tblptrh ; 2 movff ptr1+2,tblptru ; 2
lfsr 0,Buff ; 2 movlw 32 ; 1 L1 tblrd*+ ; 2 movff tablat,postinc0 ; 2 decfsz wreg ; 1 bra L1 ; 2
movff tblptrl,ptr1+0 ; 2 movff tblptrh,ptr1+1 ; 2 movff tblptru,ptr1+2 ; 2
movff ptr2+0,tblptrl ; 2 movff ptr2+1,tblptrh ; 2 movff ptr2+2,tblptru ; 2
lfsr 0,Buff ; 2 movlw 32 ; 1 L2 movff postinc0,tablat ; 2 tblwt*+ ; 2 decfsz wreg,f ; 1 bra L2 ; 2
movff tblptrl,ptr2+0 ; 2 movff tblptrh,ptr2+1 ; 2 movff tblptru,ptr2+2 ; 2
decfsz cnt,f ; 1 bra L3 ; 2
Вот так в лоб, при буфере 32 байта это даст около 15 циклов на байт. При размножение кода, можно получить около 8,7 цикла на байт:
L3 movff ptr1+0,tblptrl ; 2 movff ptr1+1,tblptrh ; 2 movff ptr1+2,tblptru ; 2
tblrd*+ ; 2 movff tablat,Buff+0 ; 2 ... ; Ещё 31 раз
movff ptr2+0,tblptrl ; 2 movff ptr2+1,tblptrh ; 2 movff ptr2+2,tblptru ; 2
movff Buff+0,tablat ; 2 tblwt*+ ; 2 ... ; Ещё 31 раз
movlw 32 ; 1 addwf ptr1+0 ; 1 bnc L1 ; 2 infsnz ptr1+1 ; 1 incf ptr1+2 ; 1 L1 addwf ptr2+0 ; 1 bnc L2 ; 2 infsnz ptr2+1 ; 1 incf ptr2+2 ; 1
L2 decfsz cnt,f ; 1 bra L3 ; 2
(Показываю только внутренний цикл, последний проход, конечно, будет по-медленнее.) Дальше экономить большого смысла нет (предел -- 8 циклов), даже может имеет смысл выбрать буфер 16 байтов, что даст около 9,4 цикла.
Можно констатировать не такую уж глобальную разницу при сравнении крайне невыгодой пересылки внутри программной памяти для PIC18 с предельно оптимальной пересылкой в памяти данных для AVR. Но и это будет лишь полуправдой, поскольку в отличие от AVR PIC18 осуществляет эти пересылки в
2-мегабайтной области.
Кстати, интересно было бы увидеть аналогичный код для AVR, работающего с внешней памятью, скажем 512 КБ.
Александр Голов, Москва, snipped-for-privacy@mail.ru