/************************************************************************************//** * \file Source/ARMCM4_XMC4/can.c * \brief Bootloader CAN communication interface source file. * \ingroup Target_ARMCM4_XMC4 * \internal *---------------------------------------------------------------------------------------- * C O P Y R I G H T *---------------------------------------------------------------------------------------- * Copyright (c) 2016 by Feaser http://www.feaser.com All rights reserved * *---------------------------------------------------------------------------------------- * L I C E N S E *---------------------------------------------------------------------------------------- * This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any later * version. * * OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You have received a copy of the GNU General Public License along with OpenBLT. It * should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. * * \endinternal ****************************************************************************************/ /**************************************************************************************** * Include files ****************************************************************************************/ #include "boot.h" /* bootloader generic header */ #include "xmc_can.h" /* CAN driver header */ #include "xmc_gpio.h" /* GPIO driver header */ #if (BOOT_COM_CAN_ENABLE > 0) /**************************************************************************************** * Macro definitions ****************************************************************************************/ /** \brief Timeout for transmitting a CAN message in milliseconds. */ #define CAN_MSG_TX_TIMEOUT_MS (50u) /** \brief Macro for accessing the CAN channel handle in the format that is expected * by the XMClib CAN driver. */ #define CAN_CHANNEL ((CAN_NODE_TypeDef *)(canChannelMap[BOOT_COM_CAN_CHANNEL_INDEX])) /** \brief Message object dedicated to message transmission. */ #define CAN_TX_MSBOBJ (CAN_MO0) /** \brief Index of the message object dedicated to message transmission */ #define CAN_TX_MSBOBJ_IDX (0) /** \brief Message object dedicated to message reception. */ #define CAN_RX_MSBOBJ (CAN_MO1) /** \brief Index of the message object dedicated to message reception. */ #define CAN_RX_MSBOBJ_IDX (1) /**************************************************************************************** * Local constant declarations ****************************************************************************************/ /** \brief Helper array to quickly convert the channel index, as specific in the boot- * loader's configuration header, to the associated channel handle that the * XMClib's CAN driver requires. */ static const CAN_NODE_TypeDef *canChannelMap[] = { CAN_NODE0, /* BOOT_COM_CAN_CHANNEL_INDEX = 0 */ CAN_NODE1, /* BOOT_COM_CAN_CHANNEL_INDEX = 1 */ CAN_NODE2, /* BOOT_COM_CAN_CHANNEL_INDEX = 2 */ CAN_NODE3, /* BOOT_COM_CAN_CHANNEL_INDEX = 3 */ CAN_NODE4, /* BOOT_COM_CAN_CHANNEL_INDEX = 4 */ CAN_NODE5 /* BOOT_COM_CAN_CHANNEL_INDEX = 5 */ }; /**************************************************************************************** * Local data declarations ****************************************************************************************/ /** \brief Transmit message object data structure. */ static XMC_CAN_MO_t transmitMsgObj; /** \brief Receive message object data structure. */ static XMC_CAN_MO_t receiveMsgObj; /************************************************************************************//** ** \brief Initializes the CAN controller and synchronizes it to the CAN bus. ** \return none. ** ****************************************************************************************/ void CanInit(void) { blt_int8u byteIdx; blt_int32u canModuleFreqHz; XMC_CAN_NODE_NOMINAL_BIT_TIME_CONFIG_t baud; blt_int32u transmitId; blt_int32u receiveId; /* the current implementation supports CAN_NODE0 to CAN_NODE5. throw an assertion error * in case a different CAN channel is configured. */ ASSERT_CT((BOOT_COM_CAN_CHANNEL_INDEX >= 0) && (BOOT_COM_CAN_CHANNEL_INDEX <= 5)); /* decide on fCAN frequency. it should be in the 5-120MHz range. according to the * datasheet, it must be at least 12MHz if 1 node (channel) is used with up to * 16 message objects. This is sufficient for this CAN driver. */ canModuleFreqHz = XMC_SCU_CLOCK_GetPeripheralClockFrequency(); /* increase if too low */ while (canModuleFreqHz < 12000000) { canModuleFreqHz *= 2; /* keep the watchdog happy */ CopService(); } /* decrease if too high */ while (canModuleFreqHz > 120000000) { canModuleFreqHz /= 2; /* keep the watchdog happy */ CopService(); } /* configure CAN module*/ XMC_CAN_Init(CAN, XMC_CAN_CANCLKSRC_FPERI, canModuleFreqHz); /* configure CAN node baudrate */ baud.can_frequency = canModuleFreqHz; baud.baudrate = BOOT_COM_CAN_BAUDRATE; baud.sample_point = 8000; baud.sjw = 1, XMC_CAN_NODE_NominalBitTimeConfigure(CAN_CHANNEL, &baud); /* set CCE and INIT bit NCR for node configuration */ XMC_CAN_NODE_EnableConfigurationChange(CAN_CHANNEL); XMC_CAN_NODE_SetInitBit(CAN_CHANNEL); /* configure the transmit message object */ transmitMsgObj.can_mo_ptr = CAN_TX_MSBOBJ; transmitMsgObj.can_priority = XMC_CAN_ARBITRATION_MODE_IDE_DIR_BASED_PRIO_2; /* set the transmit CAN identifier and negate the bit that configures it as a * 29-bit extended CAN identifier. */ transmitId = BOOT_COM_CAN_TX_MSG_ID; transmitId &= ~0x80000000; if ((BOOT_COM_CAN_TX_MSG_ID & 0x80000000) == 0) { /* 11-bit standard CAN identifier */ transmitMsgObj.can_identifier = transmitId; transmitMsgObj.can_id_mask = transmitId; transmitMsgObj.can_id_mode = XMC_CAN_FRAME_TYPE_STANDARD_11BITS; XMC_CAN_MO_AcceptOnlyMatchingIDE(&transmitMsgObj); } else { /* 29-bit extended CAN identifier */ transmitMsgObj.can_identifier = transmitId; transmitMsgObj.can_id_mask = transmitId; transmitMsgObj.can_id_mode = XMC_CAN_FRAME_TYPE_EXTENDED_29BITS; XMC_CAN_MO_AcceptOnlyMatchingIDE(&transmitMsgObj); } transmitMsgObj.can_data_length = BOOT_COM_CAN_TX_MAX_DATA; for (byteIdx=0; byteIdx timeout) { break; } } } /*** end of CanTransmitPacket ***/ /************************************************************************************//** ** \brief Receives a communication interface packet if one is present. ** \param data Pointer to byte array where the data is to be stored. ** \param len Pointer where the length of the packet is to be stored. ** \return BLT_TRUE is a packet was received, BLT_FALSE otherwise. ** ****************************************************************************************/ blt_bool CanReceivePacket(blt_int8u *data, blt_int8u *len) { blt_int8u byteIdx; blt_bool result = BLT_FALSE; /* check if a new message was received */ if ((XMC_CAN_MO_GetStatus(&receiveMsgObj) & XMC_CAN_MO_STATUS_RX_PENDING) != 0) { /* read out and process the newly received data */ if (XMC_CAN_MO_Receive(&receiveMsgObj) == XMC_CAN_STATUS_SUCCESS) { *len = receiveMsgObj.can_data_length; for (byteIdx=0; byteIdx 0 */ /*********************************** end of can.c **************************************/