реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Быстрое вычисление CRC-8, Потенциальные возможности не табличных методов
_artem_
сообщение Sep 3 2006, 16:07
Сообщение #16


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



Цитата(=GM= @ Sep 3 2006, 11:55) *
Цитата(singlskv @ Sep 1 2006, 19:37) *

Ну например, вторым шагом может быть, запоминание всех этих
констант 0x5E,0xBC,0x61,0xC2,0x9D,0x23,0x46,0x8C
в регистрах, типа чтобы для каждого байта их не грузить.
Ну или еще что-то в том же духе.
Опубликуйте код на ASM, и тогда обсудим.

Ну вот, отдаю на суд общественности.

Код
z – указатель на входной массив
bytcnt – счетчик байт минус 1
byte – рабочий регистр
temp – рабочий регистр
calcrc – рассчитанная КЦК

crc8:
    ld    byte,z+
    ldi    bytcnt,8-1;счетчик байт минус 1
orbit:
    ld    temp,x+
    eor    byte,temp
    dec    bitcnt
    brne    orbit
    clr    calcrc
    ldi    temp,0x5E
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0xBC
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0x61
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0xC2
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0x9D
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0x23
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0x46
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0x8C
    sbrc    byte,0
    ret

Всего 69 МЦ. Кстати, КЦК одного байта считается за 24 МЦ и если использовать расчет КЦК для каждого байта, то получится 24*7=161 МЦ. Сравните с 525 МЦ(:-).



=GM=, по моему небольшая ошибка есть кроме той на которую указал Oldring. В каждом sbrc , кроме того, который проверяет нулевой бит, вам надо поменять номер бита в возрастаюшем порядке, по которому вы проверяете установлен ли бит или нет.

удачи.


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 3 2006, 17:52
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(_artem_ @ Sep 3 2006, 20:07) *
=GM=, по моему небольшая ошибка есть кроме той на которую указал Oldring. В каждом sbrc , кроме того, который проверяет нулевой бит, вам надо поменять номер бита в возрастаюшем порядке, по которому вы проверяете установлен ли бит или нет.

удачи.

А если присмотреться повнимательнее, обнаруживается, что выставленный на суд общественности код в принципе нерабочий smile.gif

Вот вариант с полубайтовыми таблицами для AVR:
Код
    Указатель на начало буфера - Y,
    длина - e.
    Результат возвращается в c

crc8:
    ldi    ZH, high(crc8_tba * 2)
    ldi    c, 0x00
crc8_0:
    ld     a, Y+
    eor    a, c
    mov    ZL, a
    swap   ZL
    andi   ZL, 0x0f
    lpm
    mov    c, r0
    mov    ZL, a
    andi   ZL, 0x0f
    ori    ZL, 0x10
    lpm
    eor    c, r0
    dec    e
    brne   crc8_0
    ret


    .org    0xf00

crc8_tba:
    .db    0x00, 0x9d
    .db    0x23, 0xbe
    .db    0x46, 0xdb
    .db    0x65, 0xf8
    .db    0x8c, 0x11
    .db    0xaf, 0x32
    .db    0xca, 0x57
    .db    0xe9, 0x74

crc8_tbb:
    .db    0x00, 0x5e
    .db    0xbc, 0xe2
    .db    0x61, 0x3f
    .db    0xdd, 0x83
    .db    0xc2, 0x9c
    .db    0x7e, 0x20
    .db    0xa3, 0xfd
    .db    0x1f, 0x41


и PIC16:
Код
    FSR - Адрес
    tmp0 - количество данных

crc8
    movlw   high(crc_tba)
    movwf   PCLATH
    clrf    tmp1
crc8_0
    movf    tmp1, w
    xorwf   INDF, w
    movwf   tmp2
    andlw   0fh
    call    crc_tbb
    movwf   tmp1
    swapf   tmp2, w
    andlw   0fh
    call    crc_tba
    xorwf   tmp1, f
    incf    FSR, f
    decfsz  tmp0, f
    goto    crc8_0
    return

crc_tba
    addwf    PCL, f
    dt    00h, 9dh, 23h, 0beh, 46h, 0dbh, 65h, 0f8h
    dt    8ch, 11h, 0afh, 32h, 0cah, 57h, 0e9h, 74h

crc_tbb
    addwf    PCL, f
    dt    00h, 5eh, 0bch, 0e2h, 61h, 3fh, 0ddh, 83h
    dt    0c2h, 9ch, 7eh, 20h, 0a3h, 0fdh, 1fh, 41h


В порядке разжигания религиозной розни замечу, что код для PIC'a получается гораздо эстетичнее за счет более красивой реализации работы с таблицами.
Go to the top of the page
 
+Quote Post
Oldring
сообщение Sep 3 2006, 19:13
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(aaarrr @ Sep 3 2006, 21:52) *
А если присмотреться повнимательнее, обнаруживается, что выставленный на суд общественности код в принципе нерабочий smile.gif


Ну не в принципе - но не рабочий. Студенту явно нужно начинать учиться отлаживать свой код на симуляторе smile.gif

Цитата(aaarrr @ Sep 3 2006, 21:52) *
Вот вариант с полубайтовыми таблицами для AVR:
Код
    Указатель на начало буфера - Y,
    длина - e.
    Результат возвращается в c

crc8:
    ldi    ZH, high(crc8_tba * 2)
    ldi    c, 0x00
crc8_0:
    ld     a, Y+
    eor    a, c
    mov    ZL, a
    swap   ZL
    andi   ZL, 0x0f
    lpm
    mov    c, r0
    mov    ZL, a
    andi   ZL, 0x0f
    ori    ZL, 0x10
    lpm
    eor    c, r0
    dec    e
    brne   crc8_0
    ret


    .org    0xf00

crc8_tba:
    .db    0x00, 0x9d
    .db    0x23, 0xbe
    .db    0x46, 0xdb
    .db    0x65, 0xf8
    .db    0x8c, 0x11
    .db    0xaf, 0x32
    .db    0xca, 0x57
    .db    0xe9, 0x74

crc8_tbb:
    .db    0x00, 0x5e
    .db    0xbc, 0xe2
    .db    0x61, 0x3f
    .db    0xdd, 0x83
    .db    0xc2, 0x9c
    .db    0x7e, 0x20
    .db    0xa3, 0xfd
    .db    0x1f, 0x41


В порядке расжигания религиозной розни замечу, что код для PIC'a получается гораздо эстетичнее за счет более красивой реализации работы с таблицами.


В порядке защиты AVR замечу, что для него можно написать красивше и только с одной таблицей. Умножение на x^8 по модулю порождающего полинома кода должно выглядеть как дважды повторенный участок кода, реализующий модульное умножение на x^4:

Код
    mov    ZL, c
    andi    ZL, 0x0f
    ld    r0, Z
    eor    c, r0
    swap    c


Кому нравится, может использовать lpm, вместо ld. Данный код приведен для LSB-first варианта алгоритма, как и первоначальный сишный код. Преобразовать его в MSB-first просто, переместив swap в начало последовательности инструкций.

Таблицу вычислять не буду.

P.S. Правда, при использовании двух 16-байтных таблиц, хранящихся в RAM, можно сэкономить еще три такта на обрабатываемый байт.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Sep 3 2006, 20:31
Сообщение #19


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(Oldring @ Sep 3 2006, 09:16) *
Цитата(=GM= @ Sep 3 2006, 12:55) *

Код
    sbrc    byte,0
    ret

Это круто smile.gif))
P.S. Соревноваться в крутости оптимизации с сишным компилятором глупо, так как результат заранее очевиден.
P.P.S. Предлагаемый алгоритм - 3 такта на бит - не дает никаких преимуществ по сравнению с просто развернутым побитовым циклом со сдвигами. Ускорение примерно в два раза может дать обработка по нибблам - при этом таблицу констант размером 16 байт следует предварительно скопировать в RAM и разместить в начале или конце 256-байтной страницы. См. инструкцию SWAP.

Да, спасибо за замеченные опечатки и ошибки (копи-паст, понимаете ли(:-(). Вот исправленный вариант.
Код
crc8:
    ld    byte,z+
    ldi    bytcnt,8-1;счетчик байт минус 1
orbit:
    ld    temp,x+
    eor    byte,temp
    dec    bitcnt
    brne    orbit
    clr    calcrc
    ldi    temp,0x5E
    sbrc    byte,0
    eor    calcrc,temp
    ldi    temp,0xBC
    sbrc    byte,1
    eor    calcrc,temp
    ldi    temp,0x61
    sbrc    byte,2
    eor    calcrc,temp
    ldi    temp,0xC2
    sbrc    byte,3
    eor    calcrc,temp
    ldi    temp,0x9D
    sbrc    byte,4
    eor    calcrc,temp
    ldi    temp,0x23
    sbrc    byte,5
    eor    calcrc,temp
    ldi    temp,0x46
    sbrc    byte,6
    eor    calcrc,temp
    ldi    temp,0x8C
    sbrc    byte,7
    eor    calcrc,temp
    ret

Oldring, здесь на 7*8=56 бит расходуется 69 машинных циклов или вгрубе по 69/56=1.23 МЦ на бит.

Сообщение отредактировал =GM= - Sep 3 2006, 20:35


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Oldring
сообщение Sep 3 2006, 20:44
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(=GM= @ Sep 4 2006, 00:31) *
Oldring, здесь на 7*8=56 бит расходуется 69 машинных циклов или вгрубе по 69/56=1.23 МЦ на бит.


без учета ret - да. Только это - не CRC biggrin.gif Вот теперь я понял, что имел в виду aaarrr когда писал про неработоспособность кода в принципе. Цикл по байтам в самом начале я и не заметил за остальными ошибками smile.gif

Добавлю. Кодовое расстояние получившегося кода равно 2. Вероятность необнаружения этим кодом случайных ошибок практически не отличается от вычисления контрольного байта как простого исключающего или всех семи байт передаваемого блока. Так ради чего было так мучаться? biggrin.gif


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 3 2006, 21:28
Сообщение #21


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Oldring @ Sep 4 2006, 00:44) *
Цитата(=GM= @ Sep 4 2006, 00:31) *

Oldring, здесь на 7*8=56 бит расходуется 69 машинных циклов или вгрубе по 69/56=1.23 МЦ на бит.


без учета ret - да. Только это - не CRC biggrin.gif

Это точно не CRC.

ИМХО, проблемма в том что у Вас не обнуляеться временное
значение CRC при переходе к следующему байту.


Вот так:
Код
crc8:        ;Input: r31:r30 buffer; r18 - number of bytes    
             ;Output: r16 = CRC
        ldi        r16,0x5e
        mov        r8,r16
        ldi        r16,0xbc
        mov        r9,r16
        ldi        r16,0x61
        mov        r10,r16
        ldi        r16,0xc2
        mov        r11,r16
        ldi        r16,0x9d
        mov        r12,r16
        ldi        r16,0x23
        mov        r13,r16
        ldi        r16,0x46
        mov        r14,r16
        ldi        r16,0x8c
        mov        r15,r16
        clr        r16

crc8_0:
        ld        r17,z+
        eor        r17,r16
        clr        r16
        sbrc    r17,0
        eor        r16,r8
        sbrc    r17,1
        eor        r16,r9
        sbrc    r17,2
        eor        r16,r10
        sbrc    r17,3
        eor        r16,r11
        sbrc    r17,4
        eor        r16,r12
        sbrc    r17,5
        eor        r16,r13
        sbrc    r17,6
        eor        r16,r14
        sbrc    r17,7
        eor        r16,r15

        dec        r18
        brne    crc8_0
        ret


Получаем 177 тактов (не учитывая ret)
НО, используем 8 лишних регистров sad.gif
Go to the top of the page
 
+Quote Post
Oldring
сообщение Sep 3 2006, 22:22
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Для тех кто интересуется добавлю, что рассматриваемый CRC-8 для блоков до 127 бит имеет кодовое расстояние 4. Длина 127 бит ограничивает длину блока данных, для которой код эффективен, 14 байтами. Если же длина блока данных ограничена 7 байтами, как в данном случае, то можно применить CRC-7 с кодовым расстоянием также равным 4. При этом освободившийся бит проверочного байта можно использовать произвольным образом - но помня что он не контролируется кодом. CRC-7 также имеет в два раза большую вероятность необнаружения сильного искажения блока - 1/128 против 1/256 для CRC-8. Это может быть существенно, например, если высока вероятность потери винхронизации в середине блока. C другой стороны, как показывает практика, при заметной вероятности сильного искажения вероятность 1/256 все равно слишком высока и нужно закладывать существенно большее количество проверочных бит. При этом оба кода, являясь кодами Хэмминга, дополненными проверкой на четность, позволяют детектировать все тройные ошибки, либо детектировать все двойные ошибки и легко исправлять все одиночные ошибки.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
ivstech
сообщение Sep 4 2006, 05:11
Сообщение #23


Местный
***

Группа: Свой
Сообщений: 204
Регистрация: 5-01-06
Пользователь №: 12 860



Вот мой код расчета CRC16,
не скажу, что я придумал такой алгоритм, т.к. видел аналог для другого полинома, но это и не таблица и не цикл

; По модулю 0x11021
; IN R18 - DATA
; IN, OUT R4, R5 - аккумулятор
CRC16Update:
push R18
push R19
eor R4, R18
ldi R18, 0x00
mov R19, R4
andi R19, 0xF0
eor R18, R19
swap R19
eor R4, R19
add R19, R19
eor R5, R19
mov R19, R4
andi R19, 0x0F
eor R18, R19
swap R19
eor R5, R19
add R19, R19
brcc CRC16Skip
clr R4
inc R4
eor R5, R4
CRC16Skip:
eor R18, R19
mov R4, R5
mov R5, R18
pop R19
pop R18
ret

Сообщение отредактировал ivstech - Sep 4 2006, 05:28
Go to the top of the page
 
+Quote Post
_Bill
сообщение Sep 4 2006, 07:41
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(aaarrr @ Sep 3 2006, 20:52) *
В порядке разжигания религиозной розни замечу, что код для PIC'a получается гораздо эстетичнее за счет более красивой реализации работы с таблицами.

Без всякого разжигания религиозной розни хочу заметить, что обращение к таблицам выполняется посредством инструкций call - retlw, в результате чего время выполнения функции существенно увеличивается. Другой неприятностью является необходимость использования стека, размер которого в PIC16 очень небольшой.

Сообщение отредактировал _Bill - Sep 4 2006, 07:42
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 4 2006, 08:00
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(_Bill @ Sep 4 2006, 11:41) *
Без всякого разжигания религиозной розни хочу заметить, что обращение к таблицам выполняется посредством инструкций call - retlw, в результате чего время выполнения функции существенно увеличивается.

В свою очередь замечу, что в AVR обращение к таблицам производится только с использованием регистровой пары Z, что влечет значительные накладные расходы в том случае, если таблица пересекает границу 256 байт.

Цитата(_Bill @ Sep 4 2006, 11:41) *
Другой неприятностью является необходимость использования стека, размер которого в PIC16 очень небольшой.

Очень небольшой, но вполне достаточный для построения любой разумной программы.
Go to the top of the page
 
+Quote Post
_Bill
сообщение Sep 4 2006, 10:22
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(aaarrr @ Sep 4 2006, 11:00) *
Цитата(_Bill @ Sep 4 2006, 11:41) *

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

В свою очередь замечу, что в AVR обращение к таблицам производится только с использованием регистровой пары Z, что влечет значительные накладные расходы в том случае, если таблица пересекает границу 256 байт.

Цитата(_Bill @ Sep 4 2006, 11:41) *
Другой неприятностью является необходимость использования стека, размер которого в PIC16 очень небольшой.

Очень небольшой, но вполне достаточный для построения любой разумной программы.

Накладные расходы невелики и не зависят от расположения таблицы. В AVR отсутствует понятие страницы памяти. Но я говорю, в первую очередь, об увеличении скорости вычислений. А насчет стека могу сказать, что в PIC16 его необходимо расходовать очень экономно. Особенно при использовании прерываний. Поэтому при программировании на PIC16 я старался использовать подпрограммы лишь там, где это действительно было необходимо, например, при доступе к таблицам. В других случаях там, где можно было бы использовать подпрограммы, мне приходилось вставлять фрагменты одного и того же кода. Это неизбежно приводило к разрастанию программного кода. И тогда появлялись другие проблемы, связанные с ипользованием нескольких страниц программной памяти. Ну, да Вам эти проблемы известны не хуже меня.
Go to the top of the page
 
+Quote Post
Oldring
сообщение Sep 4 2006, 11:07
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(ivstech @ Sep 4 2006, 09:11) *
Вот мой код расчета CRC16,
не скажу, что я придумал такой алгоритм, т.к. видел аналог для другого полинома, но это и не таблица и не цикл


Ах да, точно. Спасибо. Про такие варианты я уже забыл.

Легко найти, что для рассматриваемого полинома вычисление модульного умножения на x^8 можно выполнить за 15 тактов. Если же использовать код с взаимным полиномом (0x119), то то вообще за 12. Это конечно не 9 тактов - но и вообще без таблиц. Если я нигде не ошибся, вот так:

Код
    mov r17, r16
    swap r16
    andi r17, 0x0f
    eor r16, r17
    lsl r17
    eor r16, r17

    mov r17, r16
    swap r16
    andi r17, 0x0f
    eor r16, r17
    lsl r17
    eor r16, r17


С накладными расходами на прокрутку цикла получаем 18 тактов на байт данных.
Напоминаю, что это LSB-first код.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 4 2006, 11:31
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(_Bill @ Sep 4 2006, 14:22) *
Накладные расходы невелики и не зависят от расположения таблицы.

Как это не зависят?
Одно дело, когда таблица выровнена по границе 256 байт, и не пересекает следующую:
Код
ldi    ZH, high(table * 2)
mov    ZL, offset
lpm
...

другое, когда таблица не выровнена по границе 256 байт:
Код
ldi    ZH, high(table * 2)
ldi    ZL, low(table * 2)
add    ZL, offset
lpm
...

и совсем другое, когда не выровнена по границе 256 байт, и пересекает следующую:
Код
ldi    ZH, high(table * 2)
ldi    ZL, low(table * 2)
add    ZL, offset
brcc   PC+0x02
inc    ZH
lpm
...


Разница по скорости почти в 2 раза: 5 и 8 тактов.

Цитата(_Bill @ Sep 4 2006, 14:22) *
А насчет стека могу сказать, что в PIC16 его необходимо расходовать очень экономно...

"Расход" стека случается только при использовании вложенных подпрограмм. Как правило, программы уровня PIC16 позволяют обойтись минимальным количеством вложений.
Go to the top of the page
 
+Quote Post
Oldring
сообщение Sep 4 2006, 11:51
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(aaarrr @ Sep 4 2006, 15:31) *
Цитата(_Bill @ Sep 4 2006, 14:22) *

Накладные расходы невелики и не зависят от расположения таблицы.

Как это не зависят?
Одно дело, когда таблица выровнена по границе 256 байт, и не пересекает следующую:


Зависит, но это не имеет большого значения. У иаровского ассемблера есть директива размещения сегмента с произвольным выравниванием, равным степени двойки. Например, 256.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Sep 4 2006, 12:09
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Oldring @ Sep 4 2006, 15:51) *
Зависит, но это не имеет большого значения.

Большого не имеет. Мне просто показалось, что в этом топике готовы удавиться за такт, вот и стараюсь smile.gif
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th July 2025 - 17:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.01561 секунд с 7
ELECTRONIX ©2004-2016