Димон Безпарольный 2 13 января, 2021 Опубликовано 13 января, 2021 (изменено) · Жалоба Считаю контрольную сумму 16-ти байт Quote 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F Формирую бинарный файл с этими данными, получаю результат 0xСECEE288(crc файла в Проводнике). Контроллер выдает 0x31311D77. Загнал алгоритм (код ниже) в C-Free компилятор. Тоже получил 0xСECEE288. Сравнил сформированные таблицы - одинаковые. Закипел. Код формирования таблицы unsigned long crc_table[256]; Таблица глобальная void Crc32Init(void) { unsigned long crc; for (int i = 0; i < 256; i++) //инициализируем таблицу расчёта Crc32 { crc = i; for (int j = 0; j < 8; j++) //цикл перебора полинома crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320UL : crc >> 1; crc_table[i] = crc; } inCRC = 0xFFFFFFFF; } Код самого подсчета unsigned long int Crc32(unsigned char Byte) { inCRC = (inCRC >> 8) ^ crc_table[(inCRC ^ Byte) & 0xFF]; return inCRC ^ 0xFFFFFFFF; } inCRC - глобальная переменная unsigned long int inCRC = 0xFFFFFFFF; в которой накапливается сумма. Может подскажет кто, где я накосячил? Изменено 13 января, 2021 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 30 13 января, 2021 Опубликовано 13 января, 2021 · Жалоба 2 * 2, конечно, "сэм-восэм", но c 1 до 15 никак не 16 чисел, входные байты могут и "зеркалиться" относительно их середины. А "если мы с вами посмотрим, то мы с вами увидим" ((с) моя школьная историчка): 0xСECEE288 инверсия 0x31311D77. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 14 января, 2021 Опубликовано 14 января, 2021 · Жалоба 8 hours ago, Obam said: 0xСECEE288 инверсия 0x31311D77 Точно инверсия. Буду разбираться откуда она берется. Сам алгоритм выдает на двух компиляторах данные без инверсии. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 19 февраля, 2021 Опубликовано 19 февраля, 2021 (изменено) · Жалоба Нашел причину. Выполнение строки: return inCRC ^ 0xFFFFFFFF; Дает разный результат на компьютерном С++ и в камне. В камне return inCRC ^ 0xFFFFFFFF; и return inCRC; дает одинаковый результат! На компьютерном С++ - дает инверсию. Так например Crc32(0x55); дает число 0x36fcb509 в камне независимо от варианта команды return. На С-Free на компьютере будет 0xC9034AF6 при команде return inCRC ^ 0xFFFFFFFF; и 0x36fcb509 при команде return inCRC; Почему в камне вычисление значения 0x36fcb509 ^ 0xFFFFFFFF; не инвертирует число, а на компьютере происходит инверсия? Подозреваю что что - то с разрядностью но не могу понять что. Изменено 19 февраля, 2021 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 19 февраля, 2021 Опубликовано 19 февраля, 2021 · Жалоба 14.01.2021 в 00:49, Димон Безпарольный сказал: Может подскажет кто, где я накосячил? Построение функций принципиально косячное. Не используйте в них глобальные переменные! Использование такого стиля дает сплошные побочные эффекты. Функции зависят черт-знает от чего и портят кучу всего в программе. Всё необходимое для своей работы функция должна получать через параметры. Нужны дополнительные хранилища вспомогательных данных - используйте локальные переменные. Нужно, чтобы локальные переменные сохраняли значения между вызовами - делайте их локальными статическими. По существу: как вы проверяли результат? Приведите полный текст тестовой программы. Вы, случаем, не значение вашей глобальной переменной inCRC32 проверяли? А вот эта функция 14.01.2021 в 00:49, Димон Безпарольный сказал: unsigned long int Crc32(unsigned char Byte) мне вообще непонятна. Зачем считать CRC32 от одного байта? А еще её результат зависит от двух глобальных объектов программы, один из которых ещё и изменяется ей же самой. Просто набор штампов, как не следует писать программы. Нормальные функции подсчета CRC32 произвольного объекта данных data размером size байт выглядят примерно так: uint32_t Crc32(const void *data, uint32_t size); Да, для платформонезависимости результата пользуйтесь именами типов из файла stdint.h. Иначе один и тот же ваш код будет давать разный результат на разных архитектурах: на 8-битных один, на 16-битных другой, на 32-битных третий, а на 64-битных четвертый. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 19 февраля, 2021 Опубликовано 19 февраля, 2021 (изменено) · Жалоба 1 hour ago, Darth Vader said: Зачем считать CRC32 от одного байта? Функция работает получая данные как с массивов, так и на лету с приема байт. Согласен что написано криво, надо причесать. Но это не решит проблемы потому что на глюк не похоже. Если инвертировать результат, функция считает CRC правильно на лету, из EEPROM 2580, из ФЛЭШ контроллера и еще бог знает откуда - проблем нет. Для проверки работы функции я написал вызов: Crc32Init(); Crc32(0x55); Так вот. В коде функции: unsigned long int Crc32(unsigned char Byte) { inCRC = (inCRC >> 8) ^ crc_table[(inCRC ^ Byte) & 0xFF]; return inCRC ^ 0xFFFFFFFF; } Есть строка return inCRC ^ 0xFFFFFFFF;. Она ничего не меняет. Т.е. возвращаемый результат будет тем же, что и при return inCRC; Это в камне. Приходится дополнительно инвертировать результат чтобы совпало с вариантом на ПК. А вот в варианте на ПК return inCRC ^ 0xFFFFFFFF; как раз инвертирует результат как и должно быть. Что мне пока непонятно. Один и тот же код работает по разному. Нашел причину. Вызов функции был неправильным. Правильно надо присваивать значение CRC локальной переменной uint32_t . CRCSUM = Crc32(Chr); Тогда результат подсчета будет правильный. Всем спасибо за советы. Пошел причесывать код. Изменено 19 февраля, 2021 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 19 февраля, 2021 Опубликовано 19 февраля, 2021 · Жалоба 1 hour ago, Darth Vader said: Не используйте в них глобальные переменные! Перед подсчетом CRC32 нужно вызвать Crc32Init(); Она в частности проинициализирует inCRC = 0xFFFFFFFF;. Переменная inCRC используется в двух функциях. Поэтому она глобальна. Как тогда реализовать иначе? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 19 февраля, 2021 Опубликовано 19 февраля, 2021 (изменено) · Жалоба 1 час назад, Димон Безпарольный сказал: Как тогда реализовать иначе? Сделать ОДНУ функцию, которая всё делает сама. Например так: // Реализация функции расчёта CRC-32 // data_p - указатель на произвольный объект // len - размер объекта в байтах uint32_t Crc32(const void *data_p, uint32_t len) { static const uint32_t Crc32Table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; const uint8_t *buf = (const uint8_t*)data_p; uint32_t crc = 0xFFFFFFFF; while (len--) { crc = (crc >> 8) ^ Crc32Table[(crc ^ *buf++) & 0xFF]; } return ~crc; }; Это быстрый табличный расчёт CRC32 с полиномом 0x04C11DB7. Для другого полинома будут другие значения в массиве Crc32Table[256]. Взято отсюда. Проведен небольшой рефакторинг: тип входного параметра-указателя для универсальности заменен на void*, константный массив спрятан внутрь функции, типы заменены на более конкретные. Изменено 19 февраля, 2021 пользователем Darth Vader Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 19 февраля, 2021 Опубликовано 19 февраля, 2021 (изменено) · Жалоба 12 minutes ago, Darth Vader said: Сделать ОДНУ функцию, которая всё делает сама. Спасибо. Хочу только заметить что мной пишется бутлоадер для камней с большим количеством ОЗУ. Ему неважно сколько ОЗУ будет съедено. Да и ПЗУ тоже. Но вот ПЗУ желательно поменьше. Чисто субъективно. Также непонятно как налету считать CRC. Файл прошивки может быть гораздо больше чем ОЗУ. А вот потеря времени на расчет таблицы малозначительна. Принятые данные напрямую пишутся в 2580 и налету считается CRC. Данные пишутся по 256 байт за раз. Как вариант можно CRC считать тоже по 256 байт. Изменено 19 февраля, 2021 пользователем Димон Безпарольный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 19 февраля, 2021 Опубликовано 19 февраля, 2021 · Жалоба 47 минут назад, Димон Безпарольный сказал: Переменная inCRC используется в двух функциях. Поэтому она глобальна. Ситуация ничего не напоминает? В С++ именно для таких ситуаций придуманы классы. Общие данные - это данные (поля) класса. Функции, оперирующие этими общими данными - это функции-члены класса. Так что в некоторых случаях, если нужна большая гибкость расчета, удобнее сделать класс CRC32. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Димон Безпарольный 2 19 февраля, 2021 Опубликовано 19 февраля, 2021 · Жалоба 1 minute ago, Darth Vader said: Ситуация ничего не напоминает? В С++ именно для таких ситуаций придуманы классы. Общие данные - это данные (поля) класса. Функции, оперирующие этими общими данными - это функции-члены класса. Так что в некоторых случаях, если нужна большая гибкость расчета, удобнее сделать класс CRC32. Код написан на Си. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 19 февраля, 2021 Опубликовано 19 февраля, 2021 (изменено) · Жалоба 35 минут назад, Димон Безпарольный сказал: Код написан на Си. Код может быть написан на чем угодно. Один файл на Си, другой на С++, третий на ассемблере. Всё равно компилируются они раздельно. А линкеру всё равно, на чем были написаны исходные коды объектных модулей. Так что писать стоит на том, на чем удобней в данный конкретный момент. Но уж если хочется чистого Си, то можно сделать закат солнца вручную и изобрести понятие класса и указателя this средствами Си: - описываем тип структуры с полями-данными, необходимыми для работы всех функций - во все функции добавляем в качестве первого параметра указатель на эту структуру с именем this - внутри функций обращаетесь к необходимым общим данным через этот указатель this - перед началом нового расчета создаете эту структуру. Причем она может быть как глобальной, так и локальной. - вызываете ваши функции, передавая им в качестве первого параметра указатель на структуру. Изменено 19 февраля, 2021 пользователем Darth Vader Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 25 марта, 2021 Опубликовано 25 марта, 2021 · Жалоба http://we.easyelectronics.ru/STM32/crc32-na-stm32-kak-na-kompe-ili-na-kompe-kak-na-stm32.html вот тух хорошо расписано почему так вышло) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 25 марта, 2021 Опубликовано 25 марта, 2021 · Жалоба On 2/19/2021 at 9:29 PM, Darth Vader said: В С++ именно для таких ситуаций придуманы классы. да и ты чтобы сбросить CRC предлагаешь создавать новый экземпляр класса? On 2/19/2021 at 6:46 PM, Darth Vader said: Построение функций принципиально косячное. Не используйте в них глобальные переменные! Использование такого стиля дает сплошные побочные эффекты. Функции зависят черт-знает от чего и портят кучу всего в программе. Всё необходимое для своей работы функция должна получать через параметры. Нужны дополнительные хранилища вспомогательных данных - используйте локальные переменные. Нужно, чтобы локальные переменные сохраняли значения между вызовами - делайте их локальными статическими. Набор штампов как не следует давать советы, подробнее о побочных эффектах пожалуйста и чем это локальная статическая отличается от глобальной кроме зоны видимости? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 1 25 марта, 2021 Опубликовано 25 марта, 2021 (изменено) · Жалоба А можно задать нескромный вопрос: что за камень используется, если у него нет блока аппаратного вычисления CRC? Зачем на STM32 вычислять CRC программно? Может, вы еще и БПФ будете вручную считать вместо использования fftw3? Примера ради открываю RM на STM32F072. В регистр CRC_POL заносим полином. В CRC_CR - порядок бит, размер полинома и т.п. Что там сложного-то? Изменено 25 марта, 2021 пользователем Eddy_Em Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться