Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вычисление CRC с помощью sRecord
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Sprite
Доброго всем времени суток!
Задача: есть исходный файл (бинарник) из 8 байт, забитых значением 0x11. Надо в конец файла (т.е. с адреса 0x08) вставить 2 байта CRC16 (вычисленное с полиномом 0xA001) программой Srecord. Делаю так:
Код
srec_cat sec.bin --binary -crc16-b-e 0x08 -poly 0xA001 --output sec_new.bin --binary

Значения добавляются (0x14 0x1E), но не те (0xED 0xE7).
В чем может быть проблема? Может srecord нужно указывать начало и конец исходных данных?
Сергей Борщ
С полиномом 0xA001 сдвиг осуществляется вправо. "crc16-b-e" как бы намекает на сдвиг влево. Попробуйте crc16-l-e, хоть я такого в документации и не нашел (но я там и crc16-b-e нашел только в примерах).
Sprite
Цитата(Сергей Борщ @ Apr 29 2015, 12:28) *
С полиномом 0xA001 сдвиг осуществляется вправо. "crc16-b-e" как бы намекает на сдвиг влево. Попробуйте crc16-l-e, хоть я такого в документации и не нашел (но я там и crc16-b-e нашел только в примерах).

Пробовал эту команду - выходные байты просто меняются местами (0x1E 0x14). Мне кажется здесь дело либо в неправильном указании границ данных, либо в указании формата (--binary).
esaulenka
Пользовался только "стандартным" CRC, так что мысли чисто теоретические, но...

Документация сообщает нам, что значение полинома надо передавать просто числом, без -poly. Ключ poly - это ИМЯ полинома.

Сергей, crc16-l-e / -b-e в документации есть (http://srecord.sourceforge.net/man/man1/srec_input.html, искать "crc16"). Другой вопрос, что документации могло бы быть и побольше, без чЮдных фразочек "и вообще, это опенсорс, смотрите в исходниках".
Sprite
Цитата(esaulenka @ Apr 29 2015, 12:45) *
Документация сообщает нам, что значение полинома надо передавать просто числом, без -poly. Ключ poly - это ИМЯ полинома.

Да, но я пробовал делать так: указал полином ccitt в качестве параметра, получил результат (0xCE 0x79), затем нашел в описание, посмотрел значение полинома для ccitt (0x1021) и подставил 0x1021 вместо ccitt - результат получился тот же. Из чего я сделал вывод, что полином можно скармливать любой в hex-формате, а не только в виде строковых значений (asci, modbus, ccitt и т.д.).
Сергей Борщ
Цитата(esaulenka @ Apr 29 2015, 09:45) *
Сергей, crc16-l-e / -b-e в документации есть (http://srecord.sourceforge.net/man/man1/srec_input.html, искать "crc16").
Спасибо. Я искал именно "crc16-b-e", а там описана полная форма "−CRC16_Big_Endian". "Догадайся, мол, сама". Там есть и описание двух ключей - "−Most_To_Least" (по умолчанию) и "−Least_To_Most", который, вероятно, нам и нужен.


Sprite
Цитата(Сергей Борщ @ Apr 29 2015, 13:05) *
Спасибо. Я искал именно "crc16-b-e", а там описана полная форма "−CRC16_Big_Endian". "Догадайся, мол, сама". Там есть и описание двух ключей - "−Most_To_Least" (по умолчанию) и "−Least_To_Most", который, вероятно, нам и нужен.

Попробовал -Least_To_Most:
Код
srec_cat sec.bin --binary -crc16-b-e 0x08 -Least_To_Most -poly 0xA001 --output sec_new.bin --binary
Результат получается другой (0x45 0xC7), но не правильный (
mcheb
Пока разберетесь с документацией, проще самому в GCC написать короткую консольную программу.
esaulenka
Цитата(Sprite @ Apr 29 2015, 10:04) *
Да, но я пробовал делать так: указал полином ccitt в качестве параметра, получил результат (0xCE 0x79), затем нашел в описание, посмотрел значение полинома для ccitt (0x1021) и подставил 0x1021 вместо ccitt - результат получился тот же.

srecord использует CCITT по умолчанию, так что результат эксперимента, скорее всего, получился некорректный.
Sprite
Цитата(mcheb @ Apr 29 2015, 13:26) *
Пока разберетесь с документацией, проще самому в GCC написать короткую консольную программу.

Ну да, может Вы и правы wink.gif Я пишу загрузчик, точнее уже написал. Просто хочется добавить в него CRC и сделать какое-нибудь шифрование прошивки. Люди посоветовали для этих целей использовать Srecord - там уже есть все возможности - решил не изобретать велосипед. Да и программа мне нравится - только вот работает пока не так как надо wink.gif

Цитата(esaulenka @ Apr 29 2015, 13:32) *
srecord использует CCITT по умолчанию, так что результат эксперимента, скорее всего, получился некорректный.

При изменении значения полинома (0x1021) меняется конечный результат.
Sprite
Пробовал считать CRC32. Код такой:
Код
srec_cat sec.bin --binary -crc32-b-e 0x08 --output sec_new.bin --binary
Результат получился 0x4DB8ECF5. Нашел онлайн калькулятор CRC - результат совпал. Но попробовал посчитать то же самое на stm - не вышло, считал как программным, так и аппаратным методом - в обоих методах результат одинаковый (0xEC5DBEA0)
Код
//===================================================================
uint32_t sw_calculate_soft_crc(uint32_t *pinput, uint32_t length)
{
    uint32_t initial_crc = 0xFFFFFFFF; // начальное значение                
    uint32_t* input_data = pinput;
    uint32_t polynom     = 0x4C11DB7; // полином
    uint32_t crc         = 0        ; // контрольная сумма
    uint32_t index       = 0;          
    uint32_t bindex      = 0;

    while( index<length )
    {
    if(index==0){   crc = initial_crc ^ input_data[index];}
    else        {   crc = crc ^ input_data[index];        }

        while(   bindex<(sizeof(input_data[index])*8)   )
        {    // if MSB of CRC = 1
            if((crc>>31)==1){crc=(crc<<1)^polynom;}
            else            {crc=(crc<<1);        }
            bindex++;
        }

    bindex=0;
    index++;
    }

    return crc;
}

//===================================================================
uint32_t sw_calculate_crc(uint32_t *input_data, uint32_t length)
{
    // присваиваем адрес начала данных
    uint32_t* pBuffer    = input_data;
    uint32_t index      = 0;
    uint32_t result     = 0;

    __CRC_CLK_ENABLE();             //Включить тактирование
    CRC->CR = CRC_CR_RESET;         //Сброс контрольного регистра

    while(index<length)                //Запись данных в регистр данных для расчета
    {
        CRC->DR = pBuffer[index++];
        tmp++;
    }

    result = CRC->DR;                //Извлечь просчитаную контрольную сумму
    __CRC_CLK_DISABLE();               //Выключить тактирование                      
    return result;
}

А вот, собственно, вызов функций:
Код
    uint32_t CRC_val = 0;
    uint32_t CRC_val2 = 0;    
    uint32_t data_table[]={0x11111111,0x11111111};    
    
    CRC_val = sw_calculate_crc(data_table, sizeof(data_table)/sizeof(uint32_t));
    CRC_val2= sw_calculate_soft_crc(data_table, sizeof(data_table)/sizeof(uint32_t));

Вопрос по прежнему открыт.
Sprite
Всем спасибо, разобрался.
AHTOXA
Может быть, расскажете, как правильно?
Sprite
Цитата(AHTOXA @ Apr 29 2015, 21:49) *
Может быть, расскажете, как правильно?

Чтобы значение CRC в srecord совпадало с расчетами CRC stm32 нужно использовать ключ -STM32_Big_Endian
Код
::вычисляем контрольную сумму и вставляем ее в начало файла
srec_cat part123.bin -bin -offset 0x04 -STM32_Big_Endian 0x00 -o part123_crc.bin -bin

Всем спасибо!
esaulenka
Решал аналогичную задачу.
Во-первых, CRC по алгоритму от ST - это -STM32_Little_Endian. Странно, что у Вас совпало. Переворачивали вручную, что-ли?..

А во-вторых, лучше прикрутить переворачивалку битов в нужное положение и использовать стандартный алгоритм CRC32.


CODE

/**
* stm32tpl -- STM32 C++ Template Peripheral Library
*
* Copyright © 2015 Anton B. Gusev aka AHTOXA
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
* file : stm32_crc.h
* description : STM32 Hardware CRC32 calculator
*
*/

#ifndef STM32TPL_STM32_CRC_H_INCLUDED
#define STM32TPL_STM32_CRC_H_INCLUDED

namespace STM32
{

class CrcCalculator
{
public:
CrcCalculator()
{
RCC->AHBENR |= RCC_AHBENR_CRCEN;
__DSB();
CRC->CR = 1;
__asm__ volatile ("nop");
__asm__ volatile ("nop");
__asm__ volatile ("nop");
}
~CrcCalculator() { RCC->AHBENR &= ~RCC_AHBENR_CRCEN; }
void Add(uint32_t w) { CRC->DR = w; }
uint32_t Result() { return CRC->DR; }

// вычисление по нестандартному алгоритму ST
// длина буфера указывается в uint32_t !
static uint32_t Calc(void const* buf, size_t len)
{
CrcCalculator crc;
uint32_t const * p = reinterpret_cast<uint32_t const *>(buf);
for (size_t i = 0; i < len; ++i)
crc.Add (p[i]);
return crc.Result ();
}

// вычисление по стандартному алгоритму Ethernet/ZLib/...
// длина буфера указывается в uint32_t !
static uint32_t CalcStd (void const* buf, size_t len)
{
CrcCalculator crc;
uint32_t const * p = reinterpret_cast<uint32_t const *>(buf);
for (size_t i = 0; i < len; ++i)
crc.Add (__RBIT (p[i]));
//crc.Add (__RBIT (crc.Result ()));
return ~ __RBIT (crc.Result ());
}
};

} // namespace STM32

#endif // STM32TPL_STM32_CRC_H_INCLUDED

Это микро-библиотека подсчёта, автор - присутствующий тут AHTOXA (ещё раз спасибо!)
Я дописал CalcStd(), которая переворачивает байты, чтобы результат совпадал со стандартными реализациями.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.