- 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;
- }