NXP i.MX7D и модуль CAN

Простой пример инициализации модуля и отправки сообщения самому себе, в режиме LOOPBACK.

	@ Этот код только для справки
	@ Так как реального трансивера на ножках нет, проверить не на чём
	@ Переназначим ножки порта, для режима loopback они и не нужны совсем
	MOV32 R0, IOMUXC_BASE
	MOV R1, 3 @ Режим ALT3 для CAN1
	STR R1, [R0, SW_MUX_CTL_PAD_SAI1_RX_DATA] @ CAN1 RX
	STR R1, [R0, SW_MUX_CTL_PAD_SAI1_TX_BCLK] @ CAN1 TX

	@ Определить источник тактовых импульсов
	MOV32 R0, CCM_BASE + TARGET_ROOT89 @ CAN1_CLK_ROOT
	MOV32 R1, 1 << ROOT_ENABLE + 0 << MUX + (1-1) << PRE_PODF + (1-1) << POST_PODF
	STR R1, [R0] @ Источник: 0 = 24 МГЦ (этой частоты маловато!!)

	@ Затактировать модуль
	MOV32 R0, CCM_BASE + CCGR116 @ CAN1 clock gate
	MOV R1, 0x00003333
	STR R1, [R0]
	

Что бы иметь возможность изменять настройки модуля, он должен быть заморожен.
После сброса камня, модуль CAN уже находится во Freeze mode.
Дополнительно морозить его не требуется.

	MOV32 R0, CAN1_BASE

	LDR R1, [R0, CAN_MCR]
	BIS R1, 1 << MCR_RFEN @ Rx FIFO enable
	BIS R1, 1 << LPRIO_EN @ Использовать механизм приоритетов
	STR R1, [R0, CAN_MCR]

	@ Установить режим LOOPBACK + настроить тайминги протокола
	MOV32 R1, 1 << LPB + 7 << PRESDIV + 3 << RJW + 7 << PSEG1 + 7 << PSEG2 + 6 << PROP_SEG
	STR R1, [R0, CAN_CTRL1] @ Эти тайминги посчитаны под 250 килобит на 24 МГц тактовой

	@ 8 фильтров Rx FIFO
	MOV32 R1, 0 << RFFN
	STR R1, [R0, CAN_CTRL2]

	@ Глобальный фильтр входящих сообщений
	CLR R1 @ Принимать все сообщения
	STR R1, [R0, RXMGMASK]
	
	@ Глобальный фильтр входящих сообщений
	CLR R1 @ Принимать все сообщения
	STR R1, [R0, RXFGMASK]

	@ Разморозить модуль CAN
	LDR R1, [R0, CAN_MCR]
	BIC R1, 1 << HALT + 1 << FRZ
	STR R1, [R0, CAN_MCR]
	@ Дождаться завершения разморозки
	1:
	LDR R1, [R0, CAN_MCR]
	TST R1, 1 << FRZ
	BNE 1b
	

Модуль готов к работе. Теперь можно заполнять исходящие буферы и отправлять сообщения.
При настройках выше, для исходящих сообщений доступны буферы с номером 8 ... 63.

	@ Заполнить один исходящий буфер
	MOV32 R1, 0x01234567 @ Байты данных 0..3
	STR R1, [R0, WORD08]
	MOV32 R1, 0x89ABCDEF @ Байты данных 4..7
	STR R1, [R0, WORD18]
	MOV32 R1, 1 << PRIO + 0x100 @ Приоритет + 29 бит ID
	STR R1, [R0, ID8]
	@ Установки заполняются в последнюю очередь
	@ Передача стартует автоматически
	MOV32 R1, 0x0C << CODE + 1 << IDE + 8 << DLC
	STR R1, [R0, CS8] @ Установки буфера

	@ Всё готово --> сообщение пошло в сеть!


	@ Дождаться события приёма на нулевом буфере
	@ После сброса камня, он стоит пустой и готов к приёму сообщений
	1:
	LDR R1, [R0, CS0]
	BIC R1, 0xF0FFFFFF @ Сбросить незначащие биты
	CMP R1, 2 << CODE @ 2 = FULL
	BNE 1b

	@ Сообщение принято!
	LDR R2, [R0, WORD00] @ Принятое сообщение
	LDR R3, [R0, WORD10] @ Лежит в нулевом буфере
	

LOOPBACK работает. А с реальной сетью я не проверял..