AT91SAM7: проблема установки бита MRDY в регистре статуса CAN mailbox |
![]() |
Добавил(а) microsin |
Недавно столкнулся с неприятной проблемой, когда по непонятной для меня причине при интенсивной работе на передачу не устанавливался бит MRDY регистра CAN_MSRx в передающем CAN-mailbox (поле MOT в регистре CAN_MMRx установлено в значение 3). Таким образом, ящик становится заблокированным, и его нельзя использовать на передачу. После долгих экспериментов выяснилось, что нельзя слишком часто опрашивать чтением регистр статуса ящика CAN_MSRx. Например, следующий код при слишком интенсивной передаче через один ящик приводит к бесконечной блокировке этого ящика, бит MRDY навсегда переходит в 0: void SendCAN (TCAN_msg* msg) { // Передача через ящик 4: AT91PS_CAN_MB pmb = AT91C_BASE_CAN_MB0+4; // Бесконечный цикл ожидания освобождения ящика с опросом бита MRDY // в регистре CAN_MSR4: while (0 == (AT91C_CAN_MRDY & AT91F_CAN_GetMessageStatus(pmb))); // Ящик освободился (MRDY==1), передача пакета msg: AT91F_InitMailboxRegisters(pmb, AT91C_CAN_MOT_TX, 0x3F, ((u32)msg->msg_adress << 18), msg->candata.d32[0], msg->candata.d32[1], ((u32)msg->msg_DLC << 16) |AT91C_CAN_MTCR); } Если показанная выше процедура SendCAN используется интенсивно, то в цикле ожидания while происходит бесконечное зависание. Бит MRDY после пяти-шести идущих друг за другом (без паузы) передач наглухо оказывается в лог. 0, сигнализируя о занятости ящика. Явный глюк, потому что в документации эта проблема не описана. Исправить проблему может следующий код, с ним бит MRDY устанавливается нормально: bool SendCAN (TCAN_msg* msg) { AT91PS_CAN_MB pmb = AT91C_BASE_CAN_MB0+4; // Проверка освобождения ящика 4: if (AT91C_CAN_MRDY & AT91F_CAN_GetMessageStatus(pmb)) { //Ящик 4 освободился (MRDY==1), передача пакета msg: AT91F_InitMailboxRegisters(pmb, AT91C_CAN_MOT_TX, 0x3F, ((u32)msg->msg_adress << 18), msg->candata.d32[0], msg->candata.d32[1], ((u32)msg->msg_DLC << 16) |AT91C_CAN_MTCR); return true; } else return false; } Функция SendCAN может вызываться во внешнем цикле. Возвращенный 0 сигнализирует о неудачной передаче, когда попытка передачи должна быть повторена, а лог. 1 означает, что пакет был успешно передан. [Ссылки] 1. AT91SAM7X: контроллер CAN. |