CAN_MSG_BUF_T wakeupFrame;
CAN_DATA_INFO_T txDataInfo;
CAN_MSG_BUF_T rxFrame0;
CAN_MSG_BUF_T rxFrame1;
void CanEventCallback(
uint8_t instance,
CAN_EVENT_TYPE_T eventType,
uint32_t mbIndex,
CAN_STATE_T *driverState)
{
uint8_t payload[64];
CAN_DATA_INFO_T txDataInfo;
//唤醒事件处理
if (eventType == CAN_EVENT_WAKEUP_MATCH)
{
LED_Off(LED_BLUE);
LED_On(LED_GREEN);
}
//接收事件处理
if (eventType == CAN_EVENT_RX_COMPLETE)
{
//VCU把收到的加密报文稍做处理,发到总线上去。可以理解为它指示动作机构执行动作(比如:关窗)
if (mbIndex == 0)
{
memcpy(payload, rxFrame0.data, rxFrame0.dataLen);
payload[1] = 0xBB;
txDataInfo.msgIdType = CAN_ID_STANDARD;
txDataInfo.dataLen = rxFrame0.dataLen;
txDataInfo.fdEnable = false;
txDataInfo.isRemote = false;
CAN_SendNonBlocking(CAN0_INSTANCE, 2, &txDataInfo, rxFrame0.messageId+1, payload);
//再次开始接收
CAN_ReceiveNonBlocking(CAN0_INSTANCE, 0, &rxFrame0);
}
if (mbIndex == 1)
{
memcpy(payload, rxFrame0.data, rxFrame1.dataLen);
payload[1] = 0xCC;
txDataInfo.msgIdType = CAN_ID_EXTENDED;
txDataInfo.dataLen = rxFrame1.dataLen;
txDataInfo.fdEnable = false;
txDataInfo.isRemote = false;
CAN_SendNonBlocking(CAN0_INSTANCE, 2, &txDataInfo, rxFrame1.messageId+1, payload);
//再次开始接收
CAN_ReceiveNonBlocking(CAN0_INSTANCE, 1, &rxFrame1);
}
LED_On(LED_RED);
}
}
int main(void)
{
STATUS_T status = STATUS_ERROR;
CAN_STATE_T canState;
/* Initialize clock */
CLOCK_SYS_Init(&g_clockConfig);
/* Initialize pins */
PINS_Init(NUM_OF_CONFIGURED_PINS0, g_pinsConfig);
/* Initialize LEDs */
LED_Init();
/* Initialize the power manager */
POWER_SYS_Init(&g_powerConfigs,
POWER_CONFIG_COUNT,
&g_powerManagerCallbacks,
POWER_CALLBACK_CNT);
/* Initialize the CAN controller, bitrate is 250K */
CAN_Init(CAN0_INSTANCE, &canState, &g_canConfig);
/* Set the CAN event callback handler */
CAN_InstallEventCallback(CAN0_INSTANCE, &CanEventCallback, NULL);
/* Configure Rx MB0, it will receive standard frames with ID 0xEE */
CAN_DATA_INFO_T rxMb0Info = {
.msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
.dataLen = 8, /* Max data length for classic CAN is 8 bytes */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureRxMb(CAN0_INSTANCE, 0, &rxMb0Info, 0xEE);
CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_STANDARD, 0, 0xFFFFFFFF);
/* Configure Rx MB1, it will receive extended frames with ID 0xEE */
CAN_DATA_INFO_T rxMb1Info = {
.msgIdType = CAN_ID_EXTENDED, /* Extended CAN ID */
.dataLen = 8, /* Max data length for classic CAN is 8 bytes */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureRxMb(CAN0_INSTANCE, 1, &rxMb1Info, 0xEE);
CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_EXTENDED, 1, 0xFFFFFFFF);
//开始接收CAN报文
CAN_ReceiveNonBlocking(CAN0_INSTANCE, 0, &rxFrame0);
CAN_ReceiveNonBlocking(CAN0_INSTANCE, 1, &rxFrame1);
/**
* Enable pretended networking.
* The device will be woke up when this CAN frame is received:
* - CAN ID = 0xEE
*/
CAN_PN_CONFIG_T pnConfig = {
.wakeupByTimeout = false, /* Wakeup by timeout event is disabled */
.wakeupByMatch = true, /* Wakeup by message match event is enabled */
.matchCount = 1, /* Match once */
.matchTimeout = 0, /* No timeout */
.filterType = CAN_PN_FILTER_ID, /* Match both CAN ID */
.idFilterScheme = CAN_PN_MATCH_EXACT, /* Match the exact CAN ID */
.payloadFilterScheme = CAN_PN_MATCH_EXACT, /* Match the exact payload */
.idFilter1 =
{
.isExtended = false, /* Standard CAN ID */
.isRemote = false,
.idFilter = 0xEE /* CAN ID = 0xEE */
},
.idFilter2 =
{
.isExtended = false,
.isRemote = false,
.idFilter = 0xFFFFFFFF /* Masks for CAN ID */
},
.payloadFilter =
{
.minPayloadLen = 8, /* Lower limit of the payload size: 8 byte */
.maxPayloadLen = 8, /* Upper limit of the payload size: 8 byte */
.payloadFilter1 = {}, /* Match the complete 8 bytes of payload */
.payloadFilter2 = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Masks for the payload */
}
};
CAN_ConfigurePretendedNetworking(CAN0_INSTANCE, true, &pnConfig);
/* Go to sleep and wait */
while (1)
{
/* Before going to sleep mode: blue LED = ON, green LED = OFF */
LED_On(LED_BLUE);
LED_Off(LED_GREEN);
LED_Off(LED_RED);
status = POWER_SYS_ConfigPowerMode(POWER_MODE_STOP2, POWER_POLICY_FORCIBLE);
//此时,VCU已睡眠......而CAN的PE仍在工作,维持“假装联网”的状态,等待CAN唤醒报文
if (status != STATUS_SUCCESS)
{
break;//如果进入睡眠失败,则会执行到这里
}
//此时,VCU被CAN报文唤醒,查看是谁执行了唤醒,留下了什么报文
CAN_GetWakeupMessage(CAN0_INSTANCE, 0, &wakeupFrame);
//如果唤醒者恰恰是自己关心的,则按原ID发回密钥,进行安全通信
if(wakeupFrame.messageId == 0xEE)
{
OSIF_TimeDelay(100);
txDataInfo.msgIdType = CAN_ID_STANDARD;
txDataInfo.dataLen = wakeupFrame.dataLen;
txDataInfo.fdEnable = false;
txDataInfo.isRemote = false;
//因为上位机不便做密钥计算,此处借修改第0字节数据,象征VCU把真随机数密钥发给唤醒它的ECU
wakeupFrame.data[0] = 0xAA;
CAN_SendNonBlocking(CAN0_INSTANCE, 2, &txDataInfo, wakeupFrame.messageId, wakeupFrame.data);
}
//等待对方发来加密后的正式数据报文。5秒之后,VCU再进被窝继续睡大觉
OSIF_TimeDelay(5000);
}
CAN_DeInit(CAN0_INSTANCE);
LED_On(LED_RED);
return 0;
}