Перейти к содержанию
    

Помогите по CRC32. На компьютерном Си работает, в микроконтролере дает неверный результат

9 часов назад, MasterElectric сказал:

и ты чтобы сбросить CRC предлагаешь создавать новый экземпляр класса?

Я этого нигде не предлагал.

Подход в стиле С++ предполагает описание класса CRC32 с некоторым набором публичных методов и приватных данных. Для расчета создаем объект класса (локально), вызываем нужные нам методы, получаем результат. При выходе из области видимости, объект автоматически освобождает занимаемую им в стеке память. Понадобилось посчитать CRC в другом месте - создали там локальный объект, использовали его, он снова разрушился при выходе из области видимости и т.д.

9 часов назад, MasterElectric сказал:

чем это локальная статическая отличается от глобальной кроме зоны видимости? 

Областью видимости, очевидно. Глобальную переменную может поменять кто угодно в любой момент времени. Никто не может гарантировать её неизменности между вызовами функции. Кто мешает поменять её, например, в обработчике прерывания или в любой другой функции? А локальную статическую переменную может изменить только та функция, в которой она определена. Она гарантированно останется неизменной от выхода из функции до следующего входа в неё.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

24 minutes ago, Darth Vader said:

Подход в стиле С++ предполагает описание класса CRC32 с некоторым набором публичных методов и приватных данных. Для расчета создаем объект класса (локально), вызываем нужные нам методы, получаем результат. При выходе из области видимости, объект автоматически освобождает занимаемую им в стеке память. Понадобилось посчитать CRC в другом месте - создали там локальный объект, использовали его, он снова разрушился при выходе из области видимости и т.д.

А почему это нельзя сделать простой функцией?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 минут назад, Tpeck сказал:

А почему это нельзя сделать простой функцией?

Можно, я даже пример выше привёл полного расчёта одной функцией.

Но, иногда требуется большая гибкость в расчёте. Самый простой пример - посчитать СRC области памяти с разрывами. Т.е надо посчитать от А до Б, потом, не сбрасывая расчет, продолжить с В до Г и т.д. И вот тогда одной функцией уже не обойдешься. Нужно семейство взаимосвязанных функций, имеющих доступ к общему набору данных, скрытому от всей другой программы. А это уже класс С++ в чистом виде.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Когда требуется считать CRC данных с "разрывами", то в функцию, выполняющую расчёт CRC, дополнительным параметром можно передать CRC, которое было рассчитано для предыдущего блока данных. И так повторить для требуемого количества блоков.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, ivan24190 сказал:

в функцию, выполняющую расчёт CRC, дополнительным параметром можно передать CRC, которое было рассчитано для предыдущего блока данных.

Можно и так.

Я просто обратил внимание автора топика на то, что делать так, как он некрасиво. Общие для его функций данные не должны быть видны никому, кроме этих функций. Их надо скрыть. И вот мы не спеша приходим к концепции класса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Слегка модифицировав предыдущий пример функции расчета, можно получить такую, которой можно считать данные с разрывами

#include <stdint.h>


//--------------------------------------------------------------------------------------------------------------------------	
// Тип расчёта: начать новый или продолжить старый
//--------------------------------------------------------------------------------------------------------------------------	
typedef enum {
  CALC_NEW,
  CALC_CONTINUE
} CalcVariant_t;


//--------------------------------------------------------------------------------------------------------------------------	
// Функция расчёта КС CRC-32
// obj_p - указатель на объект
// len - размер объекта в байтах
// variant - тип расчёта: начать новый или продолжить старый
//--------------------------------------------------------------------------------------------------------------------------	
uint32_t calc(const void *obj_p, uint32_t len, CalcVariant_t variant) {
  // Таблица предвычисленных констант для быстрого расчёта
  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
  };
  
  static uint32_t CurrVal = 0xFFFFFFFF;                 // текущее накопленное значение суммы
  const uint8_t   *CurrByte_p  = (const uint8_t*)obj_p; // указатель на текущий байт данных
  
  if(variant==CALC_NEW) {
    CurrVal = 0xFFFFFFFF;                               // для нового расчёта сбрасываем накопленную сумму
  }
  
  while (len--) {
    CurrVal = (CurrVal >> 8) ^ Crc32Table[(CurrVal ^ *CurrByte_p++) & 0xFF];
  }
  
  return ~CurrVal;                                      // возвращаем значение CRC32, как инверсии накопленной суммы
};

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, Darth Vader said:

для нового расчёта сбрасываем накопленную сумму

Я бы просто начальное значение передавал... Избавив себя от головной боли про хранимое состояние. И про thread-safe. Оно или начальное или результат расчета про предидущему сегменту.

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, MasterElectric сказал:

нужно еще улучшать

#include "crc32.h"


//--------------------------------------------------------------------------------------------------------------------------	
// Функция расчёта КС CRC-32
// obj_p - указатель на объект
// len - размер объекта в байтах
// start_val - начальное значение для расчёта: 
//  - для начала нового надо передать 0
//  - для продолжения предыдущего надо передать предыдущее значение КС
//--------------------------------------------------------------------------------------------------------------------------	
uint32_t calc(const void *obj_p, uint32_t len, uint32_t start_val) {
  // Таблица предвычисленных констант для быстрого расчёта
  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
  };
  
  start_val = ~start_val;                               // начальное значение суммы для расчёта
  const uint8_t   *CurrByte_p  = (const uint8_t*)obj_p; // указатель на текущий байт данных
  // Накапливаем значение
  while (len--) {
    start_val = (start_val >> 8) ^ Crc32Table[(start_val ^ *CurrByte_p++) & 0xFF];
  }
  
  return ~start_val;                                    // возвращаем значение CRC32, как инверсии накопленной суммы
};

Это потоково-безопасный вариант, за счет отказа от статической локальной переменной, хранящей предыдущее рассчитанное значение. Теперь оно передаётся параметром. Собственно, это главное достоинство именно такой реализации перед предыдущей.

Стоит заметить, что вариант реализации через класс С++, о котором я говорил ранее, изначально по-определению потоково-безопасный. Там накапливаемая сумма является приватным членом класса. Если надо посчитать КС, то каждый поток создает свой локальный экземпляр класса. В результате потоки никак не влияют друг на друга, каждый из них использует и меняет только свои данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 3/25/2021 at 11:02 AM, Eddy_Em said:

А можно задать нескромный вопрос: что за камень используется, если у него нет блока аппаратного вычисления CRC?

Зачем на STM32 вычислять CRC программно?

 

Хороший вопрос !

Присоединяюсь.

Только почему-то его все, включая топик-стартера, проигнорировали :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, dimka76 сказал:

Только почему-то его все, включая топик-стартера, проигнорировали :(

Не всегда возможно использовать встроенный, даже если он есть. Может быть полином не устраивает, а может например - аппаратный блок нереентерабелен. Или аппаратный CRC занят в данный момент. Мало ли почему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня например софтовый CRC потому что уже есть программа для формирования криптованных образов прошивок для раздачи заказчикам. И сразу закладываюсь что возможно новая версия изделия будет на другом процессоре (с отсутствующим или другим блоком CRC), чтобы не менять ПО у себя и Программу-загрузчик на ПК у заказчика.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну я сразу давал ссылку на статью про аппаратный блок CRC, но судя по всему ТС нужен CRC для обновления прошивки, а свободного времени в бутлоадере 99%, тем более с аппаратным CRC при расчете CRC32 не все нормально. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...