Jump to content

    
Sign in to follow this  
ffs2001

xmega64a3u CRC-32

Recommended Posts

Господа, помогите советом:

 

хочу считать CRC-32 на указанном МК. Аппаратный модуль имеется.

Код использовал родной атмелевский отсюда и упрощённый вариант:

 

CRC_CTRL |= CRC_CRC32_bm;
CRC.CTRL |= CRC_SOURCE_IO_gc;
        
for (n = 0; n < 32; n++){            
    
    CRC.DATAIN = test[n]; // send data
}
        
CRC.STATUS |= CRC_BUSY_bm; // finish
while (CRC_STATUS & CRC_BUSY_bm == CRC_BUSY_bm);

itoa(CRC.CHECKSUM3,str); 
puts_usf0(str);
//и так далее

 

Сам модуль работает, но выдаёт неверные данные.

Проверял вот этим калькулятором.

Полиномы совпадают, в даташите есть описание. В эррате ничего.

Тестовый массив: uint8_t[32] = {0xFF}

 

ЧЯДНТ?

Share this post


Link to post
Share on other sites
CRC_CTRL |= CRC_CRC32_bm;

CRC.CTRL |= CRC_SOURCE_IO_gc;

Сам модуль работает, но выдаёт неверные данные.

 

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

 

CRC_CTRL = CRC_CRC32_bm | CRC_SOURCE_IO_gc;

CRC_CTRL |= CRC_RESET_RESET0_gc; // Reset CRC with CHECKSUM to all zeros

 

P.S. И вот еще:

надо вызывать функцию

ltoa(CRC.CHECKSUM3,str);

вместо

itoa(CRC.CHECKSUM3,str);

Т.к. int у XMega 16-битный.

CRC32 тогда long, а не int.

Share this post


Link to post
Share on other sites
Возможно, вы забыли сделать обнуление перед накоплением.

 

CRC_CTRL = CRC_CRC32_bm | CRC_SOURCE_IO_gc;

CRC_CTRL |= CRC_RESET_RESET0_gc; // Reset CRC with CHECKSUM to all zeros

 

Да, в атмелевском драйвере это есть. С него начал.

Там ещё есть аж две малопонятных для меня инверсии; но и с ними, и без них результат даже примерно не похож на нужный.

 

 

Share this post


Link to post
Share on other sites
Да, в атмелевском драйвере это есть.

Драйвер неправильный (или может его исправили?).

 

Попробуйте такой код, он вроде работал:

uint32_t Crc32(uint8_t * data, uint16_t data_size, bool init_zero, uint32_t xor_value) 
{

    CRC.CTRL=0
        | init_zero ? (CRC_RESET_RESET0_gc) : (CRC_RESET_RESET1_gc)
        | 1<<CRC_CRC32_bp
        | CRC_SOURCE_IO_gc
    ;
    CRC.CTRL=0
        | CRC_RESET_NO_gc
        | 1<<CRC_CRC32_bp
        | CRC_SOURCE_IO_gc
    ;
    CRC.STATUS=1<<CRC_BUSY_bp;    
    uint8_t byte_counter=0;
    for (uint8_t i=0; i<data_size; i++)
        CRC.DATAIN=*data++;

    uint32_t crc=*(volatile uint32_t *)&CRC.CHECKSUM0;
    crc^=xor_value;
    return crc;
}


typedef dma_channel<'0'> Dma0;
uint32_t CrcDma(uint8_t * data, bool init_zeros, uint16_t length)
{
    CRC.CTRL=0
        | init_zeros ? CRC_RESET_RESET1_gc : CRC_RESET_RESET0_gc
        | 1<<CRC_CRC32_bp
        | CRC_SOURCE_DMAC0_gc
    ;
    CRC.CTRL=0
        | CRC_RESET_NO_gc
        | 1<<CRC_CRC32_bp
        | CRC_SOURCE_DMAC0_gc
    ;
    Dma0::ResetChannel();
    Dma0::SetSrcAddress((uint16_t)data);
    Dma0::SetDestAddress((uint16_t)data);
    Dma0::SetAddressControl(DMA_CH_SRCRELOAD_NONE_gc, DMA_CH_SRCDIR_INC_gc, DMA_CH_DESTRELOAD_NONE_gc, DMA_CH_DESTDIR_INC_gc);
    Dma0::SetTransferSize(length);
    Dma0::SetTriggerSource(DMA_CH_TRIGSRC_OFF_gc);
    Dma0::StartRamToRamTransfer(DMA_CH_BURSTLEN_8BYTE_gc);

    while (Dma0::TransferComplete()==false);

    uint32_t crc = *(uint32_t *)&CRC.CHECKSUM0;

    return crc;
}

В драйвере не было вроде такой строки (функция Crc32):

CRC.STATUS=1<<CRC_BUSY_bp;

С ДМА как ни странно работало без проблем.

Share this post


Link to post
Share on other sites

Так, проблема, похоже, не в контроллере.

В этом калькуляторе получается то же значение, что выдаёт мой контроллер. Проблема в том, что в него я скопировал полином из этого калькулятора, где получается другое значение (с этим полиномом). Это, как говорится, какое-то фуфло; но бедная иксмега не при чём.

Когда разберусь с полиномами, отпишу, в чём соль.

 

Драйвер неправильный (или может его исправили?).

 

Мда, печально.

Расскажите подробнее, если не затруднит.

 

 

В драйвере не было вроде такой строки (функция Crc32):

CRC.STATUS=1<<CRC_BUSY_bp;

С ДМА как ни странно работало без проблем.

 

Да, уже обрабатывал этот момент; это единственная ошибка в драйвере?

 

Share this post


Link to post
Share on other sites
Мда, печально.

Расскажите подробнее, если не затруднит.

Рассказывать-то и нечего: есть стандартная функция расчёта CRC

/*
  Name  : CRC-32
  Poly  : 0x04C11DB7    x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 
                       + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
  Init  : 0xFFFFFFFF
  Revert: true
  XorOut: 0xFFFFFFFF
  Check : 0xCBF43926 ("123456789")
  MaxLen: 268 435 455 байт (2 147 483 647 бит) - обнаружение
   одинарных, двойных, пакетных и всех нечетных ошибок
*/
uint_least32_t Crc32Soft(uint8_t *buf, size_t len, uint32_t init_value)
{
    uint_least32_t crc_table[256];
    uint_least32_t crc; int i, j;

    for (i = 0; i < 256; i++)
    {
        crc = i;
        for (j = 0; j < 8; j++)
            crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320UL : crc >> 1;

        crc_table[i] = crc;
    };

    crc = init_value;

    while (len--) 
        crc = crc_table[(crc ^ *buf++) & 0xFF] ^ (crc >> 8);

    return crc ^ 0xFFFFFFFFUL;
}

Результат CRC32 который выдаёт модуль xmega не совпадает с ним для CRC32.

 

 

это единственная ошибка в драйвере?

Я драйвер подробно не рассматривал, смотрел пример который шёл вместе со AtmelStudio. И в примере результат неправильный получается.

 

драйвере?

Да в общем-то тут и драйвер-то не нужен - там весь модуль 3 регистра. Самому проще написать.

 

Share this post


Link to post
Share on other sites
Рассказывать-то и нечего: есть стандартная функция расчёта CRC

 

Благодарю!

 

 

В общем, CRC-модуль, похоже, рабочий. Теперь (немного в сторону от темы) ситуация получилась такая:

 

модуль xmega и вот этот калькулятор выдают одинаковое значение;

 

библиотека CRC-32 для VS (PC) и вот этот калькулятор тоже выдают одинаковое значение, но другое!

 

Полином везде один и тот же. Видимо, под конец они как-то хитро XOR-ятся или ещё что...

Тестовое значение (hex) 940C.

 

Буду очень рад, если кто-нибудь объяснит, как так происходит.

 

 

Share this post


Link to post
Share on other sites
Полином везде один и тот же.

Возможно они инициализируют crc перед началом подсчёта нулями, а вы единицами. Или наоборот.

Попробуйте посчитать CRC по функции из сообщения 6.

    uint8_t Test10[10]={1,2,3,4,5,6,7,8,9,10}; 
    volatile uint32_t soft_crc[2];
    soft_crc[0]=Crc32Soft(Test, sizeof(Test), 0xFFFFFFFFUL);
    soft_crc[1]=Crc32Soft(Test, sizeof(Test), 0);

 

Share this post


Link to post
Share on other sites

Результаты работы приведённого кода идентичны результатам библиотеки для PC (собственно, и код идентичен).

 

Крайне смущает совпадение результатов из xmega'вского генератора с другим калькулятором.

Хочу использовать hardware генератор, т.к. нужно считать CRC app-table из бутлодера.

 

Буду копать дальше.

Share this post


Link to post
Share on other sites
Хочу использовать hardware генератор, т.к. нужно считать CRC app-table из бутлодера.

Тогда лучше использовать подсчёт CRC через команду NVM-контроллера Flash range CRC - оно само подсчитает.

Share this post


Link to post
Share on other sites
Тогда лучше использовать подсчёт CRC через команду NVM-контроллера Flash range CRC - оно само подсчитает.

 

Так будет использоваться тот же самый хардварный генератор. А он выдаёт не то.

 

Совпадение калькулятора и генератора, похоже, было случайным. Совпадают только значения, генерируемые из массива [32] = {0xFF}

 

Делаю вывод, что хардварный генератор нерабочий.

Странно, что этого нет в эррате.

 

При возможности проверю на другом контроллере, отпишусь.

 

Ещё интересный нюанс относительно приведённого в сообщении 6 кода:

 

crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320UL : crc >> 1;

 

Visual studio ругнулась тут на невозможность привести int к bool, и я ничтоже сумняшеся привёл код к виду

 

for (j = 0; j < 8; j++)
                {
                    if ((crc & 1) == 1)
                    {
                        crc = (crc >> 1) ^ 0xedb88320u;
                    }
                    else
                    {
                        crc = (crc >> 
                };

                crc_table[i] = crc;

 

тем более что так это реализовано в библиотеке, которую я использовал для PC.

 

 

Компилятор для Атмеги (работаю в CVAVR) на эту строку не ругнулся.

Но если не привести код к тому же виду, результат получается РАЗНЫЙ.

Share this post


Link to post
Share on other sites
Так будет использоваться тот же самый хардварный генератор. А он выдаёт не то.

То он выдаёт.

 

Совпадение калькулятора и генератора, похоже, было случайным. Совпадают только значения, генерируемые из массива [32] = {0xFF}

Ну да,случайность...

У меня при входных данных из комментария к функции

/*

Name : CRC-32

Poly : 0x04C11DB7 x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11

+ x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

Init : 0xFFFFFFFF

Revert: true

XorOut: 0xFFFFFFFF

Check : 0xCBF43926 ("123456789")

MaxLen: 268 435 455 байт (2 147 483 647 бит) - обнаружение

одинарных, двойных, пакетных и всех нечетных ошибок

*/

результат получался всеми тремя способами одинаковый - 0xCBF43926. Случайно...

Проверял в симуляторе - плату лень искать. На PC не проверял - не нашёл реализацию.

 

Делаю вывод, что хардварный генератор нерабочий.

Странно, что этого нет в эррате.

Описан он в мануале как-то криво. Но работает.

 

При возможности проверю на другом контроллере, отпишусь.

У меня проверялось в atxmega256A3U

 

Компилятор для Атмеги (работаю в CVAVR) на эту строку не ругнулся.

Но если не привести код к тому же виду, результат получается РАЗНЫЙ.

Вот проект для GCC:

crc32_02.rar

 

Share this post


Link to post
Share on other sites

Проверил на двух 64ых, результаты разные для hard и soft в обоих случаях. Правильное значение выдаёт soft.

Очень странно.

Edited by ffs2001

Share this post


Link to post
Share on other sites
результаты разные для hard и soft в обоих случаях.

Очень странно.

Проверил на xmega256A3U - hard, soft и dma дают одинаковый результат.

 

Проверил на двух 64ых

На двух? Тенденция , однако...Выложите проект, а вдруг и правда в 64х ошибка.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this