Итак, сценарий.
Есть некий тест, который шлет по шнурку буфер. Содержимое буфера дополняется в конце двумя байтами сабжа. Для простоты, буфер длиннее максимального блока данных на два байта, црц16 добавляется в конец, шлется суммарно длина буфера плюс 2.
Содержимое буфера не важно (ибо просто тест линии), и собственно никем не задается. Это важно.
Еще в тесте есть опция - длина буфера, которую можно изменять на лету.
Итак, тест.
В буфере 0х01, длина равна один байт. На осциллографе видно: 0х01, 0xF1, 0xD1.
Нажимаю увеличить длину (2 байта). На осциллографе: 0х01, 0xF1, 0xD1, 0x00.
Снова нажимаю увеличить длину (уже 3 байта). На осциллографе: 0х01, 0xF1, 0xD1, 0x00, 0x00. И так до бесконечности.
То есть, глаза видят две вещи:
1. Црц не меняется (как предполагалось, в конце).
2. Црц равна два нуля.
В коде примерно такое:
- Code: Select all
void send_dblock(u8 *ptr, u8 num)
{
*(u16*)&ptr[num] = crc::calc_crc16(ptr, num);
uart_ext_out.put(ptr, num + 2);
}
Вроде и неговнокод, вроде и негде ошибиться.
Проверил функции, честно спижженные из GCC. Все спижжено верно.
Полез на сайт - багу воспроизвел.
Фактически, если в блоке данных попадается комбинация, совпадающая с црц16 на момент вычисления, текущее значение црц16 обнуляется, и если до конца буфера идут нули, мы нули же в црц16 и получим.
Теперь с этим жить.