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 работает. А с реальной сетью я не проверял..