|
|
  |
Вычисление CRC с помощью sRecord |
|
|
|
Apr 29 2015, 05:48
|

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Доброго всем времени суток! Задача: есть исходный файл (бинарник) из 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 нужно указывать начало и конец исходных данных?
|
|
|
|
|
Apr 29 2015, 06:44
|

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Цитата(Сергей Борщ @ Apr 29 2015, 12:28)  С полиномом 0xA001 сдвиг осуществляется вправо. "crc16-b-e" как бы намекает на сдвиг влево. Попробуйте crc16-l-e, хоть я такого в документации и не нашел (но я там и crc16-b-e нашел только в примерах). Пробовал эту команду - выходные байты просто меняются местами (0x1E 0x14). Мне кажется здесь дело либо в неправильном указании границ данных, либо в указании формата (--binary).
Сообщение отредактировал Sprite - Apr 29 2015, 06:46
|
|
|
|
|
Apr 29 2015, 06:45
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

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

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Цитата(esaulenka @ Apr 29 2015, 12:45)  Документация сообщает нам, что значение полинома надо передавать просто числом, без -poly. Ключ poly - это ИМЯ полинома. Да, но я пробовал делать так: указал полином ccitt в качестве параметра, получил результат (0xCE 0x79), затем нашел в описание, посмотрел значение полинома для ccitt (0x1021) и подставил 0x1021 вместо ccitt - результат получился тот же. Из чего я сделал вывод, что полином можно скармливать любой в hex-формате, а не только в виде строковых значений (asci, modbus, ccitt и т.д.).
Сообщение отредактировал Sprite - Apr 29 2015, 07:05
|
|
|
|
|
Apr 29 2015, 07:05
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(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", который, вероятно, нам и нужен.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 29 2015, 07:26
|

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Цитата(Сергей Борщ @ 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), но не правильный (
|
|
|
|
|
Apr 29 2015, 07:32
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(Sprite @ Apr 29 2015, 10:04)  Да, но я пробовал делать так: указал полином ccitt в качестве параметра, получил результат (0xCE 0x79), затем нашел в описание, посмотрел значение полинома для ccitt (0x1021) и подставил 0x1021 вместо ccitt - результат получился тот же. srecord использует CCITT по умолчанию, так что результат эксперимента, скорее всего, получился некорректный.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Apr 29 2015, 07:39
|

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Цитата(mcheb @ Apr 29 2015, 13:26)  Пока разберетесь с документацией, проще самому в GCC написать короткую консольную программу. Ну да, может Вы и правы  Я пишу загрузчик, точнее уже написал. Просто хочется добавить в него CRC и сделать какое-нибудь шифрование прошивки. Люди посоветовали для этих целей использовать Srecord - там уже есть все возможности - решил не изобретать велосипед. Да и программа мне нравится - только вот работает пока не так как надо  Цитата(esaulenka @ Apr 29 2015, 13:32)  srecord использует CCITT по умолчанию, так что результат эксперимента, скорее всего, получился некорректный. При изменении значения полинома (0x1021) меняется конечный результат.
|
|
|
|
|
Apr 29 2015, 11:53
|

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Пробовал считать 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)); Вопрос по прежнему открыт.
|
|
|
|
|
May 6 2015, 05:01
|

Частый гость
 
Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414

|
Цитата(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 Всем спасибо!
|
|
|
|
|
May 22 2015, 05:56
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Решал аналогичную задачу. Во-первых, 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(), которая переворачивает байты, чтобы результат совпадал со стандартными реализациями.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|