Цитата Сообщение от Patron Посмотреть сообщение
Вычисление CRC начинается в момент записи маркера, поэтому возникают два вопроса:

1. Что именно запускает генератор CRC при записи:

1.1. Установка бита WM (9) ;
1.2. То же + байт 0xA1 в сдвиговом регистре.
Установка бита WM игнорируется, достаточно обнаружения 0xA1 в сдвиговом регистре.
Я сейчас выполил такое моделирование:
Код:
qbus_write(16'O177130, 16'O000000);
qbus_write(16'O177132, 16'H0000);
qbus_waitr();
qbus_write(16'O177132, 16'H0000);
qbus_waitr();
qbus_write(16'O177132, 16'HA1A1);
qbus_waitr();
qbus_write(16'O177132, 16'H3130);
qbus_waitr();
qbus_write(16'O177132, 16'H3332);
qbus_waitr();
На выходе записываемых данных получилось:
Код:
0x00
0x00
0x00
0x00
0xA1 (в этот момент обнулился регистр CRC и началось вычисление с этого маркера, еще я пробовал писать снова 0xA1A1 но сброса боьлше не было - это однократный процесс после перехода от чтения к записи)
0xA1
0x30 (то есть, сначала МЛАДШИЙ байт, старший бит первым)
0x31 (то есть, потом СТАРШИЙ байт, старший бит первым)
0x32
0x33 (после этого байта содержимое регистра CRC = 0x6EE9)
0x91 (инвертированное 0x6E. Сначала пишется СТАРШИЙ байт инвертированной суммы)
0x16 (инвертированное 0xE9. Потом пишется МЛАДШИЙ байт инвертированной суммы)
Вот текст программки которая соответствует извлеченному алгоритму:
(она отличается от канонического вида - на инверсию влияет XOR входного бита и выдвигаемого):
Код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

unsigned short int crc16(unsigned short crc, unsigned char data)
{
	int i, bit;

	printf("\r\n %02X(%04X,", data, crc);
	for(i=0; i<8; i++)
	{
		bit = (data >> 7) & 1;
		if (crc & 0x8000)
		{
			bit ^= 1;
		}
		crc <<= 1;
		crc |= bit;
		if (bit == 0)
		{
			crc ^= 0x1020;
		}
		data <<= 1;
	}
	printf("%04X)", crc);
	return crc;
}

int main(int argc, char *argv[])
{
	unsigned short crc, tmp;

	crc = 0;
	crc = crc16(crc, 0xA1);
	crc = crc16(crc, 0xA1);
	crc = crc16(crc, 0x30);
	crc = crc16(crc, 0x31);
	crc = crc16(crc, 0x32);
	crc = crc16(crc, 0x33);
	tmp = ~crc;
	printf("\r\nCRC: %04X", tmp);

	crc = 0;
	crc = crc16(crc, 0xA1);
	crc = crc16(crc, 0xA1);
	crc = crc16(crc, 0x30);
	crc = crc16(crc, 0x31);
	crc = crc16(crc, 0x32);
	crc = crc16(crc, 0x33);
	crc = crc16(crc, (tmp >> 8) & 0xFF);
	crc = crc16(crc, (tmp >> 0) & 0xFF);
	printf("\r\nTMP: %04X", crc);
	if (crc == 0xFFFF) printf(" CRC OK");

	printf("\r\n");
    return 0;
}
2. Если генератор CRC в ходе записи не был запущен - будет ли выполнена запись CRC ( 0xFFFF ) в момент пропуска требования ?
Да (промоделировал, заменил в примере выше A1 на A2), будет выполнена запись, но поскольку регистр CRC не был правильно проинициализирован нулем, запишется два мусорных байта (взависимости что там в регистре CRC было при начале записи)

Также ( если я правильно понял ) при чтении CRC проверяется так - если требование выполнено, то содержимое регистра данных интерпретируется как данные и включается в расчёт CRC, если же требование не выполнено - содержимое регистра данных интерпретируется как CRC, прибавляется к рассчитанному значению CRC и результат проверяется на равенство 0xFFFF.
Похоже что тут ситуация такая - CRC читается как обычные данные, и после того как они прочитаны просто проверяется регистра CRC на 0xFFFF. Невыполнение требования (чтения) просто приводит к защелкиванию признака CRC_VALID и дальнейшее вычисление СRC на потоке вычисляемых данных уже никак на этот признак не влияет. То есть - просто идет поток данных чтения, без разбора - CRC/данные. Как только прекратили выполнять требование чтения - защелкнулся признак VALID (триггер J34) и дальше хранится, а поток продолжает обрабатываться, регистр CRC изменяется итд.