/* * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD * All rights reserved. * * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use * exclusively with CVA's microcontroller products. This file can be freely * distributed within development tools that are supporting such microcontroller * products. * * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. */ /*! \brief bootloader demo project */ /******************************************************************************* * the includes ******************************************************************************/ #include #include #include "private_driver/mcu.h" #include "bootloader.h" #include "fls.h" #include "uds_user.h" #include "SEGGER_RTT.h" /******************************************************************************* * the defines ******************************************************************************/ #define UDS_PHYS_RECV_MSG_ID (0x731) #define UDS_FUNC_RECV_MSG_ID (0x7DF) #define UDS_PHYS_RESP_MSG_ID (0x7B1) #define UDS_TEXT_TX_MSG_ID (0x234) #define UDS_RECV_BUF (2080) #define UDS_SEND_BUF (512) #define CAN_BUFF_MAX_NUM (32) #define CAN_DATA_BUFFER_SIZE (64u) #define CAN_BUFFER_FIFO_SIZE (32u) int64_t Get_Cur_Time_Stamp(void); static int8_t FlexCanBoot_TxMessage(uint32_t msgId, const uint8_t *pData, uint8_t size); void DebugOutput(const char *message, ...); /******************************************************************************* * the typedefs ******************************************************************************/ typedef enum { UDS_MSG_IDX_STD_RX_PHYS, UDS_MSG_IDX_STD_RX_FUNC, UDS_MSG_IDX_STD_TX, UDS_MSG_IDX_STD_TEST_TX, UDS_MSG_IDX_NUM } Uds_MsgIdIdxType; typedef struct { uint32_t id; uint8_t data[CAN_DATA_BUFFER_SIZE]; uint8_t len; uint16_t timeStamp; uint32_t hrTimeStamp; } FlexCan_FrameStructureType; typedef struct { FlexCan_FrameStructureType rxMsg[CAN_BUFFER_FIFO_SIZE]; FlexCan_FrameStructureType txMsg[CAN_BUFFER_FIFO_SIZE]; uint8_t wrIdx; uint8_t rdIdx; } FlexCan_DataInfoType; /******************************************************************************* * the globals ******************************************************************************/ McuType mcu; volatile uint32_t gSystick1msEvent = 0, gSystick1msCnt = 0, gTestIoEn = 0; uint32_t gCpuClockFrequency = 0; int64_t timer_1ms = 0; uint8_t udsSendBuf[UDS_SEND_BUF] = {0}; uint8_t udsRecvBuf[UDS_RECV_BUF] = {0}; UdsType udsObj; FlexCan_DataInfoType flexCan_DataInfo; FlexCanDrv_ControllerCfgType flexCanCfg; FlexCanDrvType *flexCanDrv_DemoObj; uint8_t flexCanBoot_EnhanceRxFFCnt = 0; Uds_ParamsType udsParam = { .isotpParams.framePadding = true, .isotpParams.blockSize = 0, .isotpParams.recvPhysId = UDS_PHYS_RECV_MSG_ID, .isotpParams.recvFuncId = UDS_FUNC_RECV_MSG_ID, .isotpParams.sendid = UDS_PHYS_RESP_MSG_ID, .isotpParams.sendBuf = udsSendBuf, .isotpParams.sendBufSize = UDS_SEND_BUF, .isotpParams.recvBuf = udsRecvBuf, .isotpParams.recvBufSize = UDS_RECV_BUF, .isotpParams.debug = NULL, .isotpParams.sendCanMsg = FlexCanBoot_TxMessage, .isotpParams.getTimeMs = Get_Cur_Time_Stamp, .p2Server_ms = 50, .p2xServer_10ms = 500, .s3Server_ms = 5000, }; const FlexCanDrv_MsgCfgType msgCfgObj[UDS_MSG_IDX_NUM] = { {UDS_MSG_IDX_STD_RX_PHYS, 1, UDS_PHYS_RECV_MSG_ID, false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_PHYS */ {UDS_MSG_IDX_STD_RX_FUNC, 1, UDS_FUNC_RECV_MSG_ID, false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_FUNC */ {UDS_MSG_IDX_STD_TX, 1, UDS_PHYS_RESP_MSG_ID, false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */ {UDS_MSG_IDX_STD_TEST_TX, 1, UDS_TEXT_TX_MSG_ID, false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */ }; /******************************************************************************* * the functions ******************************************************************************/ int64_t Get_Cur_Time_Stamp(void) { return timer_1ms; } void SysTick_Handler(void) { gSystick1msEvent++; timer_1ms++; Uds_Tick(&udsObj); } void CAN_ORed_0_31_MB_Handler(void) { uint8_t i = 0; FlexCanDrv_MsgObjType msgObj; for(i = 0; i < flexCanCfg.msgNum; i++) { msgObj.msgBufId = i; if(FlexCanDrv_GetMsgObjFlag(flexCanDrv_DemoObj, &msgObj)) { if(flexCanCfg.msgCfg[i].msgType == FLEXCANDRV_MSGTYPE_RX) { /* clear message buffer interrupt flag */ FlexCanDrv_ClearMsgObjFlag(flexCanDrv_DemoObj, &msgObj); /* get the new message data */ FlexCanDrv_GetRxMsg(flexCanDrv_DemoObj, &msgObj); memcpy(flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].data, msgObj.data, msgObj.dlc); flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].id = msgObj.msgId; flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].len = msgObj.dlc; flexCan_DataInfo.wrIdx++; if(flexCan_DataInfo.wrIdx >= CAN_BUFFER_FIFO_SIZE) { flexCan_DataInfo.wrIdx = 0; } } else { /* clear message buffer interrupt flag */ FlexCanDrv_ClearMsgObjFlag(flexCanDrv_DemoObj, &msgObj); } } } } bool FlexCanBoot_ReadoutMsg(FlexCan_FrameStructureType *pRxMsgObj) { bool ret = false; if(flexCan_DataInfo.wrIdx != flexCan_DataInfo.rdIdx) { memcpy(pRxMsgObj, &flexCan_DataInfo.rxMsg[flexCan_DataInfo.rdIdx], sizeof(FlexCan_FrameStructureType)); flexCan_DataInfo.rdIdx++; if(flexCan_DataInfo.rdIdx >= CAN_BUFFER_FIFO_SIZE) { flexCan_DataInfo.rdIdx = 0; } ret = true; } return ret; } static int8_t FlexCanBoot_TxMessage(uint32_t msgId, const uint8_t *pData, uint8_t size) { FlexCanDrv_MsgObjType txMsgObj; uint8_t msgIdx = 0, i = 0; for(i = 0; i < flexCanCfg.msgNum; i++) { if(msgId == flexCanCfg.msgCfg[i].msgId) { msgIdx = i; break; } } txMsgObj.msgBufId = flexCanCfg.msgCfg[msgIdx].msgBufId; txMsgObj.dlc = size; txMsgObj.msgId = flexCanCfg.msgCfg[msgIdx].msgId; memcpy(&txMsgObj.data[0], pData, size); FlexCanDrv_SetTxMsg(flexCanDrv_DemoObj, &txMsgObj); /* transmit standard CAN Tx message */ FlexCanDrv_TransmitMsg(flexCanDrv_DemoObj, &txMsgObj); return 0; } void FlexCanBoot_Init(void) { uint32_t busClockFreq = 0; flexCanDrv_DemoObj = &mcu.flexCanDrv; /* set PTE4 as MUX 5 - CAN0.RX */ PinsDrv_SetMuxModeSel(&mcu.ptb, 0, PINSDRV_MUX_ALT5); /* set PTE5 as MUX 5 - CAN0.TX */ PinsDrv_SetMuxModeSel(&mcu.ptb, 1, PINSDRV_MUX_ALT5); /* get CAN controller default configuration */ FlexCanDrv_GetDefaultCfg(&flexCanCfg); flexCanCfg.msgNum = sizeof(msgCfgObj) / sizeof(FlexCanDrv_MsgCfgType); flexCanCfg.msgCfg = msgCfgObj; flexCanCfg.clkSrc = FLEXCANDRV_CLKSRC_CHICLK; flexCanCfg.fdEnable = false; flexCanCfg.fdISOEnable = false; flexCanCfg.fifoEnable = false;//TODO false? flexCanCfg.msgBufDataLenSel = FLEXCANDRV_MB_SIZE_BYTE_8; flexCanCfg.individualMaskEnable = true; if(flexCanCfg.clkSrc == FLEXCANDRV_CLKSRC_CHICLK) { ClockDrv_GetFreq(&mcu.clockDrv, CLOCKDRV_APB, &busClockFreq); } else { ClockDrv_GetFreq(&mcu.clockDrv, CLOCKDRV_SOSC_DIV, &busClockFreq); } if(flexCanCfg.fdEnable == true) { FlexCanDrv_BitTimingCalc(&flexCanCfg.fdBitTiming, busClockFreq, /* module clock source: 16M */ 2000000, /* baudrate: 2M */ 7500, /* sample point: 75% */ 2000, /* SJW: 20% */ 1); /* FD bit timing */ } FlexCanDrv_BitTimingCalc(&flexCanCfg.bitTiming, busClockFreq, /* module clock source: 16M */ 500000, /* baudrate: 500K */ 7500, /* sample point: 75% */ 2500, /* SJW: 20% */ 0); /* classic CAN bit timing */ /* initialize CAN module */ FlexCanDrv_Configure(flexCanDrv_DemoObj, &flexCanCfg); /* enable rx interrupt */ IrqDrv_EnableIrq(CAN_ORed_0_31_MB_IRQn); } static uint8_t testdata[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; void TxTestMsg (uint8_t * data) { for (uint8_t i = 0; i < 8; i++) { testdata[i] = data[i]; } FlexCanBoot_TxMessage(UDS_TEXT_TX_MSG_ID,testdata,8); } void DebugOutput(const char *message, ...) { va_list ParamList; va_start(ParamList, message); SEGGER_RTT_printf(0, message, &ParamList); va_end(ParamList); } uint8_t BootReqDelay = 0; uint8_t BootReqFlag = 0; void BootReqInit(void) { /* Setup the clock */ ClockDrv_ModuleClkConfigType clockConfig; /* Setup the Pll div2 clock */ clockConfig.gating = true; clockConfig.source = CLOCKDRV_PLL; clockConfig.div = 1; ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PLL_DIV, &clockConfig); } uint32_t rollingcounter; int main(void) { FlexCan_FrameStructureType rxMsg; /* Setup the clock */ ClockDrv_ModuleClkConfigType clockConfig; SEGGER_RTT_Init(); SEGGER_RTT_printf(0,"-----INTO BOOT-----\n"); IrqDrv_DisableGlobalInterrupt(); /* Initialize all MCU drivers: flash drv included */ Mcu_Init(&mcu); WdgDrv_Disable(&mcu.wdgDrv); /* CAN init */ memset(&flexCan_DataInfo, 0, sizeof(flexCan_DataInfo)); memset(&flexCanCfg, 0, sizeof(flexCanCfg)); /* Enable the clock for all port peripheral */ clockConfig.gating = true; clockConfig.div = 1; ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTA, &clockConfig); ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTB, &clockConfig); ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTC, &clockConfig); ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTD, &clockConfig); ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTE, &clockConfig); //STB /* set PTC1 MUX as GPIO */ PinsDrv_SetMuxModeSel(&mcu.ptc, 9, PINSDRV_MUX_AS_GPIO); /* set PTC1 as GPIO output */ PinsDrv_SetPinDirection(&mcu.ptc, 9, 1); PinsDrv_WritePin(&mcu.ptc, 9, 0); /* get CAN controller default configuration */ FlexCanBoot_Init(); /* UDS init */ Uds_UserInit(&udsObj, &udsParam); Bootloader_Init(&mcu.flashDrv, &udsObj, &Uds_PositiveResponse, &Uds_NegativeResponse); /* Set system tick clock, 1ms event */ ClockDrv_GetFreq(&mcu.clockDrv, CLOCKDRV_SYS, &gCpuClockFrequency); SysTick_Config(gCpuClockFrequency / 1000u); IrqDrv_EnableIrq(SysTick_IRQn); #if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 1u Fls_Init(&mcu.flashDrv); #endif IrqDrv_EnableGlobalInterrupt(); while(1) { if(gSystick1msEvent > 0u) { gSystick1msEvent = 0; gSystick1msCnt++; if (gSystick1msCnt % 10 == 0) { } if(gSystick1msCnt >= 1000) { gSystick1msCnt = 0; //TxTestMsg(testdata); } Bootloader_TimingProcess(1); Uds_Run(&udsObj); Bootloader_StateProc(); } /* Handler user routine */ if(FlexCanBoot_ReadoutMsg(&rxMsg) == true) { if((rxMsg.id == UDS_PHYS_RECV_MSG_ID) || (rxMsg.id == UDS_FUNC_RECV_MSG_ID)) { IsoTp_HandleIncomingCanMsg(&udsObj.isotp, rxMsg.id, rxMsg.data, rxMsg.len); } } } }