/* ----------------------------------------------------------------------------- * Copyright (c) 2013-2018 Arm Limited * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. Permission is granted to anyone to use this * software for any purpose, including commercial applications, and to alter * it and redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in * a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source distribution. * * * $Date: 11. September 2018 * $Revision: V1.9 * * Driver: Driver_CAN1/2 * Configured: via RTE_Device.h configuration file * Project: CAN Driver for ST STM32F1xx * -------------------------------------------------------------------------- * Use the following configuration settings in the middleware component * to connect to this driver. * * Configuration Setting Value CAN Interface * --------------------- ----- ------------- * Connect to hardware via Driver_CAN# = 1 use CAN1 * Connect to hardware via Driver_CAN# = 2 use CAN2 * -------------------------------------------------------------------------- * Defines used for driver configuration (at compile time): * * CAN_CLOCK_TOLERANCE: defines maximum allowed clock tolerance in 1/1024 steps * - default value: 15 (approx. 1.5 %) * CAN1_FILTER_BANK_NUM: defines maximum number of Filter Banks used for CAN1 controller (0..28) * (sum of maximum number of Filter Banks used for CAN1 and CAN2 must not exceed 28) * - default value: 14 * CAN2_FILTER_BANK_NUM: defines maximum number of Filter Banks used for CAN2 controller (0..28) * (sum of maximum number of Filter Banks used for CAN1 and CAN2 must not exceed 28) * - default value: 14 * -------------------------------------------------------------------------- */ /* History: * Version 1.9 * Corrected MessageSend function to only access required data for sending * Version 1.8 * Corrected abort message send functionality (IRQ deadloop) * Version 1.7 * Corrected SetBitrate function * Version 1.6 * Corrected filter setting for adding/removing maskable Standard ID * Version 1.5 * Corrected clearing of overrun flag in interrupt routine * Version 1.4 * Corrected CAN2 initialization was disabling CAN1 filters * Version 1.3 * Corrected receive overrun signaling * Version 1.2 * Corrected functionality when NULL pointer is provided for one or both * signal callbacks in Initialize function call * Version 1.1 * Corrected functionality when only one CAN controller is used * Corrected pin remap configuration for CAN2 port pins * Version 1.0 * Initial release */ #include "CAN_STM32F10x.h" // Externally overridable configuration definitions // Maximum allowed clock tolerance in 1/1024 steps #ifndef CAN_CLOCK_TOLERANCE #define CAN_CLOCK_TOLERANCE (15U) // 15/1024 approx. 1.5 % #endif // Maximum number of Message Objects used for CAN1 controller #ifndef CAN1_FILTER_BANK_NUM #define CAN1_FILTER_BANK_NUM (14UL) #endif // Maximum number of Message Objects used for CAN2 controller #ifndef CAN2_FILTER_BANK_NUM #define CAN2_FILTER_BANK_NUM (14UL) #endif #if ((CAN1_FILTER_BANK_NUM + CAN2_FILTER_BANK_NUM) > 28U) #error Too many Filter Banks defined, maximum sum of Filter Banks for both CAN1 and CAN2 is 28 !!! #endif #define CAN_RX_OBJ_NUM (2U) // Number of receive objects #define CAN_TX_OBJ_NUM (3U) // Number of transmit objects #define CAN_TOT_OBJ_NUM (CAN_RX_OBJ_NUM + CAN_TX_OBJ_NUM) // CAN Driver ****************************************************************** #define ARM_CAN_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,9) // CAN driver version // Driver Version static const ARM_DRIVER_VERSION can_driver_version = { ARM_CAN_API_VERSION, ARM_CAN_DRV_VERSION }; // Driver Capabilities static const ARM_CAN_CAPABILITIES can_driver_capabilities = { CAN_TOT_OBJ_NUM, // Number of CAN Objects available 1U, // Supports reentrant calls to ARM_CAN_MessageSend, ARM_CAN_MessageRead, ARM_CAN_ObjectConfigure and abort message sending used by ARM_CAN_Control. 0U, // Does not support CAN with flexible data-rate mode (CAN_FD) 0U, // Does not support restricted operation mode 1U, // Supports bus monitoring mode 1U, // Supports internal loopback mode 1U // Supports external loopback mode #if (defined(ARM_CAN_API_VERSION) && (ARM_CAN_API_VERSION >= 0x101U)) , 0U // Reserved bits #endif }; // Object Capabilities static const ARM_CAN_OBJ_CAPABILITIES can_object_capabilities_rx = { 0U, // Object does not support transmission 1U, // Object supports reception 0U, // Object does not support RTR reception and automatic Data transmission 0U, // Object does not support RTR transmission and automatic Data reception 1U, // Object allows assignment of multiple filters to it 1U, // Object supports exact identifier filtering 0U, // Object does not support range identifier filtering 1U, // Object supports mask identifier filtering 3U // Object can buffer 3 messages #if (defined(ARM_CAN_API_VERSION) && (ARM_CAN_API_VERSION >= 0x101U)) , 0U // Reserved bits #endif }; static const ARM_CAN_OBJ_CAPABILITIES can_object_capabilities_tx = { 1U, // Object supports transmission 0U, // Object does not support reception 0U, // Object does not support RTR reception and automatic Data transmission 0U, // Object does not support RTR transmission and automatic Data reception 0U, // Object does not allow assignment of multiple filters to it 0U, // Object does not support exact identifier filtering 0U, // Object does not support range identifier filtering 0U, // Object does not support mask identifier filtering 1U // Object can only buffer 1 message #if (defined(ARM_CAN_API_VERSION) && (ARM_CAN_API_VERSION >= 0x101U)) , 0U // Reserved bits #endif }; #define CAN_FRx_32BIT_IDE ((uint32_t)1U << 2) #define CAN_FRx_32BIT_RTR ((uint32_t)1U << 1) #define CAN_FRx_16BIT_L_IDE ((uint32_t)1U << 3) #define CAN_FRx_16BIT_L_RTR ((uint32_t)1U << 4) #define CAN_FRx_16BIT_H_IDE ((uint32_t)1U << 19) #define CAN_FRx_16BIT_H_RTR ((uint32_t)1U << 20) typedef enum _CAN_FILTER_TYPE { CAN_FILTER_TYPE_EXACT_ID = 0U, CAN_FILTER_TYPE_MASKABLE_ID = 1U } CAN_FILTER_TYPE; static CAN_TypeDef * const ptr_CANx[2] = { (CAN_TypeDef *)CAN1, (CAN_TypeDef *)CAN2 }; // Local variables and structures static uint8_t can_driver_powered [CAN_CTRL_NUM]; static uint8_t can_driver_initialized[CAN_CTRL_NUM]; static uint8_t can_obj_cfg [CAN_CTRL_NUM][CAN_TOT_OBJ_NUM]; static ARM_CAN_SignalUnitEvent_t CAN_SignalUnitEvent [CAN_CTRL_NUM]; static ARM_CAN_SignalObjectEvent_t CAN_SignalObjectEvent [CAN_CTRL_NUM]; // Helper Functions /** \fn int32_t CANx_AddFilter (uint32_t obj_idx, CAN_FILTER_TYPE filter_type, uint32_t id, uint32_t mask, uint8_t x) \brief Add receive filter for specified id or id with mask. \param[in] obj_idx Receive object index assignment \param[in] filter_type Type of filter to add - CAN_FILTER_TYPE_EXACT_ID: exact id filter (id only) - CAN_FILTER_TYPE_MASKABLE_ID: maskable filter (id and mask) \param[in] id Identifier \param[in] mask Identifier Mask \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_AddFilter (uint32_t obj_idx, CAN_FILTER_TYPE filter_type, uint32_t id, uint32_t mask, uint8_t x) { uint32_t fa1r, frx, fry, msk; uint8_t bank, bank_end; int32_t status; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (obj_idx >= CAN_RX_OBJ_NUM) { return ARM_DRIVER_ERROR_PARAMETER; } if (x == 1U) { bank = CAN1_FILTER_BANK_NUM; bank_end = CAN1_FILTER_BANK_NUM + CAN2_FILTER_BANK_NUM; } else { bank = 0U; bank_end = CAN1_FILTER_BANK_NUM; } if (bank >= bank_end) { return ARM_DRIVER_ERROR; } status = ARM_DRIVER_OK; CAN1->FMR |= CAN_FMR_FINIT; // Enter filter initialization mode fa1r = CAN1->FA1R; msk = (uint32_t)1U << bank; if ((id & ARM_CAN_ID_IDE_Msk) != 0U) { // Extended Identifier frx = (id << 3) | CAN_FRx_32BIT_IDE; // id + IDE switch (filter_type) { case CAN_FILTER_TYPE_EXACT_ID: fry = (id << 3) | CAN_FRx_32BIT_IDE | CAN_FRx_32BIT_RTR; // id + IDE + RTR while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if ((fa1r & msk) == 0U) { // If filter is not active CAN1->FM1R |= msk; // Select identifier list mode CAN1->FS1R |= msk; // Select single 32-bit scale configuration if (obj_idx & 1U) { CAN1->FFA1R |= msk; // Assign to FIFO1 } else { CAN1->FFA1R &= ~msk; // Assign to FIFO0 } CAN1->sFilterRegister[bank].FR1 = frx; // id + IDE CAN1->sFilterRegister[bank].FR2 = fry; // id + IDE + RTR break; } msk <<= 1U; bank++; } break; case CAN_FILTER_TYPE_MASKABLE_ID: fry = (mask << 3) | CAN_FRx_32BIT_IDE; // mask + IDE while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if ((fa1r & msk) == 0U) { // If filter is not active CAN1->FM1R &= ~msk; // Select identifier mask mode CAN1->FS1R |= msk; // Select single 32-bit scale configuration if (obj_idx & 1U) { CAN1->FFA1R |= msk; // Assign to FIFO1 } else { CAN1->FFA1R &= ~msk; // Assign to FIFO0 } CAN1->sFilterRegister[bank].FR1 = frx; // id + IDE CAN1->sFilterRegister[bank].FR2 = fry; // mask + IDE break; } msk <<= 1U; bank++; } break; default: status = ARM_DRIVER_ERROR_PARAMETER; break; } } else { // Standard Identifier switch (filter_type) { case CAN_FILTER_TYPE_EXACT_ID: frx = ((id & 0xFFFFU) << 5) | // Low 16 bits = id ((id & 0xFFFFU) << 21) | CAN_FRx_16BIT_H_RTR; // High 16 bits = id + RTR while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if ((fa1r & msk) == 0U) { // If filter is not active CAN1->FM1R |= msk; // Select identifier list mode CAN1->FS1R &= ~msk; // Select dual 16-bit scale configuration if (obj_idx & 1U) { CAN1->FFA1R |= msk; // Assign to FIFO1 } else { CAN1->FFA1R &= ~msk; // Assign to FIFO0 } CAN1->sFilterRegister[bank].FR1 = frx; CAN1->sFilterRegister[bank].FR2 = 0xFFFFFFFFU; // Disable unused slots break; } else if (((CAN1->FM1R & msk) != 0U) && // If identifier list mode ((CAN1->FS1R & msk) == 0U) && // If dual 16-bit scale configuration (((CAN1->FFA1R >> bank) & 1U) == obj_idx)) { // If bank has same FIFO assignment as requested if (CAN1->sFilterRegister[bank].FR1==0xFFFFFFFFU) { // If n and n+1 entry are not used CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR1 = frx; // id and id + RTR break; } else if (CAN1->sFilterRegister[bank].FR2==0xFFFFFFFFU) { // If n+2 and n+3 entry are not used CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR2 = frx; // id and id + RTR break; } } msk <<= 1U; bank++; } break; case CAN_FILTER_TYPE_MASKABLE_ID: frx = ((id & 0xFFFFU) << 5) | // Low 16 bits = id ((mask & 0xFFFFU) << 21) ; // High 16 bits = mask if ((mask & ARM_CAN_ID_IDE_Msk) != 0U) { // If IDE masking enabled frx |= CAN_FRx_16BIT_H_RTR; // High 16 bits = mask + IDE } while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if ((fa1r & msk) == 0U) { // If filter is not active CAN1->FM1R &= ~msk; // Select identifier mask mode CAN1->FS1R &= ~msk; // Select dual 16-bit scale configuration if (obj_idx & 1U) { CAN1->FFA1R |= msk; // Assign to FIFO1 } else { CAN1->FFA1R &= ~msk; // Assign to FIFO0 } CAN1->sFilterRegister[bank].FR1 = frx; CAN1->sFilterRegister[bank].FR2 = 0xFFFFFFFFU; // Disable unused slots break; } else if ((((CAN1->FM1R | CAN1->FS1R) & msk) == 0U) && // If identifier mask mode and dual 16-bit scale configuration (((CAN1->FFA1R >> bank) & 1U) == obj_idx)) { // If bank has same FIFO assignment as requested if (CAN1->sFilterRegister[bank].FR1==0xFFFFFFFFU) { // If n entry is not used CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR1 = frx; // id and mask break; } else if (CAN1->sFilterRegister[bank].FR2==0xFFFFFFFFU) { // If n+1 entry is not used CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR2 = frx; // id and mask break; } } msk <<= 1U; bank++; } break; default: status = ARM_DRIVER_ERROR_PARAMETER; break; } } if (status == ARM_DRIVER_OK) { CAN1->FA1R |= msk; // Put filter in active mode } CAN1->FMR &= ~CAN_FMR_FINIT; // Exit filter initialization mode return status; } /** \fn int32_t CANx_RemoveFilter (uint32_t obj_idx, CAN_FILTER_TYPE filter_type, uint32_t id, uint32_t mask, uint8_t x) \brief Remove receive filter for specified id or id with mask. \param[in] obj_idx Receive object index assignment \param[in] filter_type Type of filter to remove - CAN_FILTER_TYPE_EXACT_ID: exact id filter (id only) - CAN_FILTER_TYPE_MASKABLE_ID: maskable filter (id and mask) \param[in] id Identifier \param[in] mask Identifier Mask \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_RemoveFilter (uint32_t obj_idx, CAN_FILTER_TYPE filter_type, uint32_t id, uint32_t mask, uint8_t x) { uint32_t fa1r, frx, fry, msk; int32_t status; uint8_t bank, bank_end; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (obj_idx >= CAN_RX_OBJ_NUM) { return ARM_DRIVER_ERROR_PARAMETER; } if (x == 1U) { bank = CAN1_FILTER_BANK_NUM; bank_end = CAN1_FILTER_BANK_NUM + CAN2_FILTER_BANK_NUM; } else { bank = 0U; bank_end = CAN1_FILTER_BANK_NUM; } if (bank >= bank_end) { return ARM_DRIVER_ERROR; } status = ARM_DRIVER_OK; CAN1->FMR |= CAN_FMR_FINIT; // Enter filter initialization mode fa1r = CAN1->FA1R; msk = (uint32_t)1U << bank; if ((id & ARM_CAN_ID_IDE_Msk) != 0U) { // Extended Identifier frx = (id << 3) | CAN_FRx_32BIT_IDE; // id + IDE switch (filter_type) { case CAN_FILTER_TYPE_EXACT_ID: fry = (id << 3) | CAN_FRx_32BIT_IDE | CAN_FRx_32BIT_RTR; // id + IDE + RTR while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if (((fa1r & msk) != 0U) && // If filter is active (((CAN1->FM1R & CAN1->FS1R) & msk) != 0U) && // If identifier list mode and single 32-bit scale configuration (((CAN1->FFA1R >> bank) & 1U) == obj_idx) && // If bank has same FIFO assignment as requested (CAN1->sFilterRegister[bank].FR1 == frx) && (CAN1->sFilterRegister[bank].FR2 == fry)) { CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR1 = 0xFFFFFFFFU; CAN1->sFilterRegister[bank].FR2 = 0xFFFFFFFFU; break; } msk <<= 1U; bank++; } break; case CAN_FILTER_TYPE_MASKABLE_ID: fry = (mask << 3) | CAN_FRx_32BIT_IDE; // mask + IDE while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if (((fa1r & msk) != 0U) && // If filter is active ((CAN1->FM1R & msk) == 0U) && // If identifier mask mode ((CAN1->FS1R & msk) != 0U) && // If single 32-bit scale configuration (((CAN1->FFA1R >> bank) & 1U) == obj_idx) && // If bank has same FIFO assignment as requested (CAN1->sFilterRegister[bank].FR1 == frx) && (CAN1->sFilterRegister[bank].FR2 == fry)) { CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR1 = 0xFFFFFFFFU; CAN1->sFilterRegister[bank].FR2 = 0xFFFFFFFFU; break; } msk <<= 1U; bank++; } break; default: status = ARM_DRIVER_ERROR_PARAMETER; break; } } else { // Standard Identifier switch (filter_type) { case CAN_FILTER_TYPE_EXACT_ID: frx = ((id & 0xFFFFU) << 5) | // Low 16 bits = id ((id & 0xFFFFU) << 21) | CAN_FRx_16BIT_H_RTR; // High 16 bits = id + RTR while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if (((fa1r & msk) != 0U)&& // If filter is active ((CAN1->FM1R & msk) != 0U) && // If identifier list mode ((CAN1->FS1R & msk) == 0U) && // If dual 16-bit scale configuration (((CAN1->FFA1R >> bank) & 1U) == obj_idx)) { // If bank has same FIFO assignment as requested if (CAN1->sFilterRegister[bank].FR1 == frx) { CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR1 = 0xFFFFFFFFU; break; } else if (CAN1->sFilterRegister[bank].FR2 == frx) { CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR2 = 0xFFFFFFFFU; break; } } msk <<= 1U; bank++; } break; case CAN_FILTER_TYPE_MASKABLE_ID: frx = ((id & 0xFFFFU) << 5) | // Low 16 bits = id ((mask & 0xFFFFU) << 21) ; // High 16 bits = mask if ((mask & ARM_CAN_ID_IDE_Msk) != 0U) { // If IDE masking enabled frx |= CAN_FRx_16BIT_H_IDE; // High 16 bits = mask + IDE } while (bank <= bank_end) { // Find empty place for id if (bank == bank_end) { // If no free found exit status = ARM_DRIVER_ERROR; break; } if (((fa1r & msk) != 0U) && // If filter is active (((CAN1->FM1R | CAN1->FS1R) & msk) == 0U) && // If identifier mask mode and dual 16-bit scale configuration (((CAN1->FFA1R >> bank) & 1U) == obj_idx)) { // If bank has same FIFO assignment as requested if (CAN1->sFilterRegister[bank].FR1 == frx) { CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR1 = 0xFFFFFFFFU; break; } else if (CAN1->sFilterRegister[bank].FR2 == frx) { CAN1->FA1R &= ~msk; // Put filter in inactive mode CAN1->sFilterRegister[bank].FR2 = 0xFFFFFFFFU; break; } } msk <<= 1U; bank++; } break; default: status = ARM_DRIVER_ERROR_PARAMETER; break; } } if ((status == ARM_DRIVER_OK) && ((CAN1->sFilterRegister[bank].FR1 != 0xFFFFFFFFU) || (CAN1->sFilterRegister[bank].FR2 != 0xFFFFFFFFU))) { CAN1->FA1R |= msk; // Put filter in active mode } CAN1->FMR &= ~CAN_FMR_FINIT; // Exit filter initialization mode return status; } // CAN Driver Functions /** \fn ARM_DRIVER_VERSION CAN_GetVersion (void) \brief Get driver version. \return ARM_DRIVER_VERSION */ static ARM_DRIVER_VERSION CAN_GetVersion (void) { return can_driver_version; } /** \fn ARM_CAN_CAPABILITIES CAN_GetCapabilities (void) \brief Get driver capabilities. \return ARM_CAN_CAPABILITIES */ static ARM_CAN_CAPABILITIES CAN_GetCapabilities (void) { return can_driver_capabilities; } /** \fn int32_t CANx_Initialize (ARM_CAN_SignalUnitEvent_t cb_unit_event, ARM_CAN_SignalObjectEvent_t cb_object_event, uint8_t x) \brief Initialize CAN interface and register signal (callback) functions. \param[in] cb_unit_event Pointer to ARM_CAN_SignalUnitEvent callback function \param[in] cb_object_event Pointer to ARM_CAN_SignalObjectEvent callback function \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_Initialize (ARM_CAN_SignalUnitEvent_t cb_unit_event, ARM_CAN_SignalObjectEvent_t cb_object_event, uint8_t x) { if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (can_driver_initialized[x] != 0U) { return ARM_DRIVER_OK; } CAN_SignalUnitEvent [x] = cb_unit_event; CAN_SignalObjectEvent[x] = cb_object_event; #if (MX_CAN1 == 1U) if (x == 0U) { #if defined (MX_CAN1_RX_Pin) GPIO_PortClock (MX_CAN1_RX_GPIOx, true); GPIO_AFConfigure (MX_CAN1_RX_GPIO_AF); GPIO_PinConfigure (MX_CAN1_RX_GPIOx, MX_CAN1_RX_GPIO_Pin, MX_CAN1_RX_GPIO_Conf, MX_CAN1_RX_GPIO_Mode); #endif #if defined (MX_CAN1_TX_Pin) GPIO_PortClock (MX_CAN1_TX_GPIOx, true); GPIO_AFConfigure (MX_CAN1_TX_GPIO_AF); GPIO_PinConfigure (MX_CAN1_TX_GPIOx, MX_CAN1_TX_GPIO_Pin, MX_CAN1_TX_GPIO_Conf, MX_CAN1_TX_GPIO_Mode); #endif } #endif #if (MX_CAN2 == 1U) if (x == 1U) { #if defined (MX_CAN2_RX_Pin) GPIO_PortClock (MX_CAN2_RX_GPIOx, true); GPIO_AFConfigure (MX_CAN2_RX_GPIO_AF); GPIO_PinConfigure (MX_CAN2_RX_GPIOx, MX_CAN2_RX_GPIO_Pin, MX_CAN2_RX_GPIO_Conf, MX_CAN2_RX_GPIO_Mode); #endif #if defined (MX_CAN2_TX_Pin) GPIO_PortClock (MX_CAN2_TX_GPIOx, true); GPIO_AFConfigure (MX_CAN2_TX_GPIO_AF); GPIO_PinConfigure (MX_CAN2_TX_GPIOx, MX_CAN2_TX_GPIO_Pin, MX_CAN2_TX_GPIO_Conf, MX_CAN2_TX_GPIO_Mode); #endif } #endif can_driver_initialized[x] = 1U; return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) static int32_t CAN1_Initialize (ARM_CAN_SignalUnitEvent_t cb_unit_event, ARM_CAN_SignalObjectEvent_t cb_object_event) { return CANx_Initialize (cb_unit_event, cb_object_event, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_Initialize (ARM_CAN_SignalUnitEvent_t cb_unit_event, ARM_CAN_SignalObjectEvent_t cb_object_event) { return CANx_Initialize (cb_unit_event, cb_object_event, 1U); } #endif /** \fn int32_t CANx_Uninitialize (uint8_t x) \brief De-initialize CAN interface. \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_Uninitialize (uint8_t x) { if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } #if (MX_CAN1 == 1U) if (x == 0U) { #if defined (MX_CAN1_RX_Pin) GPIO_PinConfigure (MX_CAN1_RX_GPIOx, MX_CAN1_RX_GPIO_Pin, GPIO_IN_FLOATING, GPIO_MODE_INPUT); GPIO_AFConfigure (AFIO_CAN_PA11_PA12); #endif #if defined (MX_CAN1_TX_Pin) GPIO_PinConfigure (MX_CAN1_TX_GPIOx, MX_CAN1_TX_GPIO_Pin, GPIO_IN_FLOATING, GPIO_MODE_INPUT); GPIO_AFConfigure (AFIO_CAN_PA11_PA12); #endif } #endif #if (MX_CAN2 == 1U) if (x == 1U) { #if defined (MX_CAN2_RX_Pin) GPIO_PinConfigure (MX_CAN2_RX_GPIOx, MX_CAN2_RX_GPIO_Pin, GPIO_IN_FLOATING, GPIO_MODE_INPUT); GPIO_AFConfigure (AFIO_CAN2_NO_REMAP); #endif #if defined (MX_CAN2_TX_Pin) GPIO_PinConfigure (MX_CAN2_TX_GPIOx, MX_CAN2_TX_GPIO_Pin, GPIO_IN_FLOATING, GPIO_MODE_INPUT); GPIO_AFConfigure (AFIO_CAN2_NO_REMAP); #endif } #endif can_driver_initialized[x] = 0U; return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) static int32_t CAN1_Uninitialize (void) { return CANx_Uninitialize (0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_Uninitialize (void) { return CANx_Uninitialize (1U); } #endif /** \fn int32_t CANx_PowerControl (ARM_POWER_STATE state, uint8_t x) \brief Control CAN interface power. \param[in] state Power state - ARM_POWER_OFF : power off: no operation possible - ARM_POWER_LOW : low power mode: retain state, detect and signal wake-up events - ARM_POWER_FULL : power on: full operation at maximum performance \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_PowerControl (ARM_POWER_STATE state, uint8_t x) { CAN_TypeDef *ptr_CAN; uint32_t msk; uint8_t bank, bank_end; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (x == 1U) { bank = CAN1_FILTER_BANK_NUM; bank_end = CAN1_FILTER_BANK_NUM + CAN2_FILTER_BANK_NUM; } else { bank = 0U; bank_end = CAN1_FILTER_BANK_NUM; } if (bank >= bank_end) { return ARM_DRIVER_ERROR; } ptr_CAN = ptr_CANx[x]; switch (state) { case ARM_POWER_OFF: can_driver_powered[x] = 0U; #if (MX_CAN1 == 1U) if (x == 0U) { NVIC_DisableIRQ (CAN1_TX_IRQn); NVIC_DisableIRQ (CAN1_RX0_IRQn); NVIC_DisableIRQ (CAN1_RX1_IRQn); NVIC_DisableIRQ (CAN1_SCE_IRQn); } #endif #if (MX_CAN2 == 1U) if (x == 1U) { NVIC_DisableIRQ (CAN2_TX_IRQn); NVIC_DisableIRQ (CAN2_RX0_IRQn); NVIC_DisableIRQ (CAN2_RX1_IRQn); NVIC_DisableIRQ (CAN2_SCE_IRQn); } #endif #if (MX_CAN1 == 1U) if (x == 0U) { // Enable clock for CAN1 peripheral RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; } #endif #if (MX_CAN2 == 1U) if (x == 1U) { // Enable clock for CAN1 and CAN2 peripheral RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; RCC->APB1ENR |= RCC_APB1ENR_CAN2EN; } #endif ptr_CAN->IER = 0U; // Disable Interrupts ptr_CAN->MCR = CAN_MCR_RESET; // Reset CAN controller while ((ptr_CAN->MCR & CAN_MCR_RESET) != 0U); memset((void *)&can_obj_cfg[x][0], 0, CAN_TOT_OBJ_NUM); #if (MX_CAN1 == 1U) if (x == 0U) { RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST; __NOP(); __NOP(); __NOP(); __NOP(); RCC->APB1ENR &= ~RCC_APB1ENR_CAN1EN; } #endif #if (MX_CAN2 == 1U) if (x == 1U) { RCC->APB1RSTR |= RCC_APB1RSTR_CAN2RST; __NOP(); __NOP(); __NOP(); __NOP(); RCC->APB1ENR &= ~RCC_APB1ENR_CAN2EN; #if (MX_CAN1 == 0U) RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST; __NOP(); __NOP(); __NOP(); __NOP(); RCC->APB1ENR &= ~RCC_APB1ENR_CAN1EN; #endif } #endif break; case ARM_POWER_FULL: if (can_driver_initialized[x] == 0U) { return ARM_DRIVER_ERROR; } if (can_driver_powered[x] != 0U) { return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) if (x == 0U) { RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST; __NOP(); __NOP(); __NOP(); __NOP(); RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST; } #endif #if (MX_CAN2 == 1U) if (x == 1U) { RCC->APB1ENR |= RCC_APB1ENR_CAN2EN; RCC->APB1RSTR |= RCC_APB1RSTR_CAN2RST; __NOP(); __NOP(); __NOP(); __NOP(); RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN2RST; if ((RCC->APB1ENR & RCC_APB1ENR_CAN1EN) == 0U) { // If CAN1 (master) clock is not enabled, enable it as it is necessary for filter operation RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST; __NOP(); __NOP(); __NOP(); __NOP(); RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST; } } #endif ptr_CAN->MCR = CAN_MCR_RESET; // Reset CAN controller while ((ptr_CAN->MCR & CAN_MCR_RESET) != 0U); // Initialize filter banks CAN1->FMR = CAN_FMR_FINIT | (CAN1_FILTER_BANK_NUM << 8); msk = ((uint32_t)1U << bank_end) - ((uint32_t)1U << bank); CAN1->FMR |= CAN_FMR_FINIT; // Enter filter initialization mode CAN1->FA1R &= ~msk; // Put all filters in inactive mode CAN1->FM1R &= ~msk; // Initialize all filters mode CAN1->FS1R &= ~msk; // Initialize all filters scale configuration while (bank <= bank_end) { // Go through all banks if (bank == bank_end) { break; } CAN1->sFilterRegister[bank].FR1 = 0U; CAN1->sFilterRegister[bank].FR2 = 0U; bank++; } memset((void *)&can_obj_cfg[x][0], 0, CAN_TOT_OBJ_NUM); ptr_CAN->IER = CAN_IER_TMEIE | // Enable Interrupts CAN_IER_FMPIE0 | CAN_IER_FOVIE0 | CAN_IER_FMPIE1 | CAN_IER_FOVIE1 | CAN_IER_EWGIE | CAN_IER_EPVIE | CAN_IER_BOFIE | CAN_IER_ERRIE ; can_driver_powered[x] = 1U; #if (MX_CAN1 == 1U) if (x == 0U) { if ((CAN_SignalUnitEvent[0] != NULL) || (CAN_SignalObjectEvent[0] != NULL)) { NVIC_ClearPendingIRQ (CAN1_TX_IRQn); NVIC_EnableIRQ (CAN1_TX_IRQn); NVIC_ClearPendingIRQ (CAN1_RX0_IRQn); NVIC_EnableIRQ (CAN1_RX0_IRQn); NVIC_ClearPendingIRQ (CAN1_RX1_IRQn); NVIC_EnableIRQ (CAN1_RX1_IRQn); } if (CAN_SignalUnitEvent[0] != NULL) { NVIC_ClearPendingIRQ (CAN1_SCE_IRQn); NVIC_EnableIRQ (CAN1_SCE_IRQn); } } #endif #if (MX_CAN2 == 1U) if (x == 1U) { if ((CAN_SignalUnitEvent[1] != NULL) || (CAN_SignalObjectEvent[1] != NULL)) { NVIC_ClearPendingIRQ (CAN2_TX_IRQn); NVIC_EnableIRQ (CAN2_TX_IRQn); NVIC_ClearPendingIRQ (CAN2_RX0_IRQn); NVIC_EnableIRQ (CAN2_RX0_IRQn); NVIC_ClearPendingIRQ (CAN2_RX1_IRQn); NVIC_EnableIRQ (CAN2_RX1_IRQn); } if (CAN_SignalUnitEvent[1] != NULL) { NVIC_ClearPendingIRQ (CAN2_SCE_IRQn); NVIC_EnableIRQ (CAN2_SCE_IRQn); } } #endif break; default: return ARM_DRIVER_ERROR_UNSUPPORTED; } return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) static int32_t CAN1_PowerControl (ARM_POWER_STATE state) { return CANx_PowerControl (state, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_PowerControl (ARM_POWER_STATE state) { return CANx_PowerControl (state, 1U); } #endif /** \fn uint32_t CAN_GetClock (void) \brief Retrieve CAN base clock frequency. \return base clock frequency */ uint32_t CAN_GetClock (void) { return RTE_PCLK1; } /** \fn int32_t CANx_SetBitrate (ARM_CAN_BITRATE_SELECT select, uint32_t bitrate, uint32_t bit_segments, uint8_t x) \brief Set bitrate for CAN interface. \param[in] select Bitrate selection - ARM_CAN_BITRATE_NOMINAL : nominal (flexible data-rate arbitration) bitrate - ARM_CAN_BITRATE_FD_DATA : flexible data-rate data bitrate \param[in] bitrate Bitrate \param[in] bit_segments Bit segments settings \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_SetBitrate (ARM_CAN_BITRATE_SELECT select, uint32_t bitrate, uint32_t bit_segments, uint8_t x) { CAN_TypeDef *ptr_CAN; uint32_t mcr, sjw, prop_seg, phase_seg1, phase_seg2, pclk, brp, tq_num; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (select != ARM_CAN_BITRATE_NOMINAL) { return ARM_CAN_INVALID_BITRATE_SELECT; } if (can_driver_powered[x] == 0U) { return ARM_DRIVER_ERROR; } prop_seg = (bit_segments & ARM_CAN_BIT_PROP_SEG_Msk ) >> ARM_CAN_BIT_PROP_SEG_Pos; phase_seg1 = (bit_segments & ARM_CAN_BIT_PHASE_SEG1_Msk) >> ARM_CAN_BIT_PHASE_SEG1_Pos; phase_seg2 = (bit_segments & ARM_CAN_BIT_PHASE_SEG2_Msk) >> ARM_CAN_BIT_PHASE_SEG2_Pos; sjw = (bit_segments & ARM_CAN_BIT_SJW_Msk ) >> ARM_CAN_BIT_SJW_Pos; if (((prop_seg + phase_seg1) < 1U) || ((prop_seg + phase_seg1) > 16U)) { return ARM_CAN_INVALID_BIT_PROP_SEG; } if (( phase_seg2 < 1U) || ( phase_seg2 > 8U)) { return ARM_CAN_INVALID_BIT_PHASE_SEG2; } if (( sjw < 1U) || ( sjw > 4U)) { return ARM_CAN_INVALID_BIT_SJW; } ptr_CAN = ptr_CANx[x]; tq_num = 1U + prop_seg + phase_seg1 + phase_seg2; pclk = CAN_GetClock (); if (pclk == 0U) { return ARM_DRIVER_ERROR; } brp = pclk / (tq_num * bitrate); if (brp > 1024U) { return ARM_CAN_INVALID_BITRATE; } if (pclk > (brp * tq_num * bitrate)) { if ((((pclk - (brp * tq_num * bitrate)) * 1024U) / pclk) > CAN_CLOCK_TOLERANCE) { return ARM_CAN_INVALID_BITRATE; } } else if (pclk < (brp * tq_num * bitrate)) { if (((((brp * tq_num * bitrate) - pclk) * 1024U) / pclk) > CAN_CLOCK_TOLERANCE) { return ARM_CAN_INVALID_BITRATE; } } mcr = ptr_CAN->MCR; ptr_CAN->MCR = CAN_MCR_INRQ; // Activate initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK) == 0U); // Wait to enter initialization mode ptr_CAN->BTR = ((brp - 1U) & CAN_BTR_BRP) | ((sjw - 1U) << 24) | ((phase_seg2 - 1U) << 20) | ((prop_seg + phase_seg1 - 1U) << 16); ptr_CAN->MCR = mcr; // Return to previous mode return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) static int32_t CAN1_SetBitrate (ARM_CAN_BITRATE_SELECT select, uint32_t bitrate, uint32_t bit_segments) { return CANx_SetBitrate (select, bitrate, bit_segments, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_SetBitrate (ARM_CAN_BITRATE_SELECT select, uint32_t bitrate, uint32_t bit_segments) { return CANx_SetBitrate (select, bitrate, bit_segments, 1U); } #endif /** \fn int32_t CANx_SetMode (ARM_CAN_MODE mode, uint8_t x) \brief Set operating mode for CAN interface. \param[in] mode Operating mode - ARM_CAN_MODE_INITIALIZATION : initialization mode - ARM_CAN_MODE_NORMAL : normal operation mode - ARM_CAN_MODE_RESTRICTED : restricted operation mode - ARM_CAN_MODE_MONITOR : bus monitoring mode - ARM_CAN_MODE_LOOPBACK_INTERNAL : loopback internal mode - ARM_CAN_MODE_LOOPBACK_EXTERNAL : loopback external mode \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_SetMode (ARM_CAN_MODE mode, uint8_t x) { CAN_TypeDef *ptr_CAN; uint32_t event; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } ptr_CAN = ptr_CANx[x]; event = 0U; switch (mode) { case ARM_CAN_MODE_INITIALIZATION: CAN1->FMR |= CAN_FMR_FINIT; // Filter initialization mode ptr_CAN->MCR = CAN_MCR_INRQ; // Enter initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK)==0U); // Wait to enter initialization mode event = ARM_CAN_EVENT_UNIT_BUS_OFF; break; case ARM_CAN_MODE_NORMAL: ptr_CAN->BTR &=~(CAN_BTR_LBKM | CAN_BTR_SILM); ptr_CAN->MCR = CAN_MCR_ABOM | // Activate automatic bus-off CAN_MCR_AWUM ; // Enable automatic wakeup mode while ((ptr_CAN->MSR&CAN_MSR_INAK)!=0U); // Wait to exit initialization mode CAN1->FMR &= ~CAN_FMR_FINIT; // Filter active mode event = ARM_CAN_EVENT_UNIT_ACTIVE; break; case ARM_CAN_MODE_RESTRICTED: return ARM_DRIVER_ERROR_UNSUPPORTED; case ARM_CAN_MODE_MONITOR: ptr_CAN->MCR |= CAN_MCR_INRQ; // Enter initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK)==0U); // Wait to enter initialization mode ptr_CAN->BTR &= ~CAN_BTR_LBKM; // Deactivate loopback ptr_CAN->BTR |= CAN_BTR_SILM; // Activate silent ptr_CAN->MCR &= ~CAN_MCR_INRQ; // Deactivate initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK)!=0U); // Wait to exit initialization mode event = ARM_CAN_EVENT_UNIT_PASSIVE; break; case ARM_CAN_MODE_LOOPBACK_INTERNAL: ptr_CAN->MCR |= CAN_MCR_INRQ; // Enter initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK)==0U); // Wait to enter initialization mode ptr_CAN->BTR |= CAN_BTR_LBKM; // Activate loopback ptr_CAN->BTR |= CAN_BTR_SILM; // Activate silent ptr_CAN->MCR &= ~CAN_MCR_INRQ; // Deactivate initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK)!=0U); // Wait to exit initialization mode event = ARM_CAN_EVENT_UNIT_PASSIVE; break; case ARM_CAN_MODE_LOOPBACK_EXTERNAL: ptr_CAN->MCR |= CAN_MCR_INRQ; // Enter initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK)==0U); // Wait to enter initialization mode ptr_CAN->BTR &= ~CAN_BTR_SILM; // Deactivate silent ptr_CAN->BTR |= CAN_BTR_LBKM; // Activate loopback ptr_CAN->MCR &= ~CAN_MCR_INRQ; // Deactivate initialization mode while ((ptr_CAN->MSR&CAN_MSR_INAK)!=0U); // Wait to exit initialization mode event = ARM_CAN_EVENT_UNIT_ACTIVE; break; default: return ARM_DRIVER_ERROR_PARAMETER; } if ((CAN_SignalUnitEvent[x] != NULL) && (event != 0U)) { CAN_SignalUnitEvent[x](event); } return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) static int32_t CAN1_SetMode (ARM_CAN_MODE mode) { return CANx_SetMode (mode, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_SetMode (ARM_CAN_MODE mode) { return CANx_SetMode (mode, 1U); } #endif /** \fn ARM_CAN_OBJ_CAPABILITIES CANx_ObjectGetCapabilities (uint32_t obj_idx, uint8_t x) \brief Retrieve capabilities of an object. \param[in] obj_idx Object index \param[in] x Controller number (0..1) \return ARM_CAN_OBJ_CAPABILITIES */ ARM_CAN_OBJ_CAPABILITIES CANx_ObjectGetCapabilities (uint32_t obj_idx, uint8_t x) { ARM_CAN_OBJ_CAPABILITIES obj_cap_null; if ((x >= CAN_CTRL_NUM) || (obj_idx >= CAN_TOT_OBJ_NUM)) { memset ((void *)&obj_cap_null, 0, sizeof(ARM_CAN_OBJ_CAPABILITIES)); return obj_cap_null; } if (obj_idx >= CAN_RX_OBJ_NUM) { return can_object_capabilities_tx; } else { return can_object_capabilities_rx; } } #if (MX_CAN1 == 1U) ARM_CAN_OBJ_CAPABILITIES CAN1_ObjectGetCapabilities (uint32_t obj_idx) { return CANx_ObjectGetCapabilities (obj_idx, 0U); } #endif #if (MX_CAN2 == 1U) ARM_CAN_OBJ_CAPABILITIES CAN2_ObjectGetCapabilities (uint32_t obj_idx) { return CANx_ObjectGetCapabilities (obj_idx, 1U); } #endif /** \fn int32_t CANx_ObjectSetFilter (uint32_t obj_idx, ARM_CAN_FILTER_OPERATION operation, uint32_t id, uint32_t arg, uint8_t x) \brief Add or remove filter for message reception. \param[in] obj_idx Object index of object that filter should be or is assigned to \param[in] operation Operation on filter - ARM_CAN_FILTER_ID_EXACT_ADD : add exact id filter - ARM_CAN_FILTER_ID_EXACT_REMOVE : remove exact id filter - ARM_CAN_FILTER_ID_RANGE_ADD : add range id filter - ARM_CAN_FILTER_ID_RANGE_REMOVE : remove range id filter - ARM_CAN_FILTER_ID_MASKABLE_ADD : add maskable id filter - ARM_CAN_FILTER_ID_MASKABLE_REMOVE : remove maskable id filter \param[in] id ID or start of ID range (depending on filter type) \param[in] arg Mask or end of ID range (depending on filter type) \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_ObjectSetFilter (uint32_t obj_idx, ARM_CAN_FILTER_OPERATION operation, uint32_t id, uint32_t arg, uint8_t x) { int32_t status; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (obj_idx >= CAN_RX_OBJ_NUM) { return ARM_DRIVER_ERROR_PARAMETER; } if (can_driver_powered[x] == 0U) { return ARM_DRIVER_ERROR; } CAN1->FMR |= CAN_FMR_FINIT; // Filter initialization mode switch (operation) { case ARM_CAN_FILTER_ID_EXACT_ADD: status = CANx_AddFilter (obj_idx, CAN_FILTER_TYPE_EXACT_ID, id, 0U, x); break; case ARM_CAN_FILTER_ID_MASKABLE_ADD: status = CANx_AddFilter (obj_idx, CAN_FILTER_TYPE_MASKABLE_ID, id, arg, x); break; case ARM_CAN_FILTER_ID_EXACT_REMOVE: status = CANx_RemoveFilter(obj_idx, CAN_FILTER_TYPE_EXACT_ID, id, 0U, x); break; case ARM_CAN_FILTER_ID_MASKABLE_REMOVE: status = CANx_RemoveFilter(obj_idx, CAN_FILTER_TYPE_MASKABLE_ID, id, arg, x); break; case ARM_CAN_FILTER_ID_RANGE_ADD: case ARM_CAN_FILTER_ID_RANGE_REMOVE: default: status = ARM_DRIVER_ERROR_UNSUPPORTED; break; } CAN1->FMR &= ~CAN_FMR_FINIT; // Filter active mode return status; } #if (MX_CAN1 == 1U) static int32_t CAN1_ObjectSetFilter (uint32_t obj_idx, ARM_CAN_FILTER_OPERATION operation, uint32_t id, uint32_t arg) { return CANx_ObjectSetFilter (obj_idx, operation, id, arg, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_ObjectSetFilter (uint32_t obj_idx, ARM_CAN_FILTER_OPERATION operation, uint32_t id, uint32_t arg) { return CANx_ObjectSetFilter (obj_idx, operation, id, arg, 1U); } #endif /** \fn int32_t CANx_ObjectConfigure (uint32_t obj_idx, ARM_CAN_OBJ_CONFIG obj_cfg, uint8_t x) \brief Configure object. \param[in] obj_idx Object index \param[in] obj_cfg Object configuration state - ARM_CAN_OBJ_INACTIVE : deactivate object - ARM_CAN_OBJ_RX : configure object for reception - ARM_CAN_OBJ_TX : configure object for transmission - ARM_CAN_OBJ_RX_RTR_TX_DATA : configure object that on RTR reception automatically transmits Data Frame - ARM_CAN_OBJ_TX_RTR_RX_DATA : configure object that transmits RTR and automatically receives Data Frame \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_ObjectConfigure (uint32_t obj_idx, ARM_CAN_OBJ_CONFIG obj_cfg, uint8_t x) { if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (obj_idx >= CAN_TOT_OBJ_NUM) { return ARM_DRIVER_ERROR_PARAMETER; } if (can_driver_powered[x] == 0U) { return ARM_DRIVER_ERROR; } switch (obj_cfg) { case ARM_CAN_OBJ_INACTIVE: can_obj_cfg[x][obj_idx] = ARM_CAN_OBJ_INACTIVE; break; case ARM_CAN_OBJ_RX_RTR_TX_DATA: case ARM_CAN_OBJ_TX_RTR_RX_DATA: can_obj_cfg[x][obj_idx] = ARM_CAN_OBJ_INACTIVE; return ARM_DRIVER_ERROR_UNSUPPORTED; case ARM_CAN_OBJ_TX: if (obj_idx < CAN_RX_OBJ_NUM) { return ARM_DRIVER_ERROR_PARAMETER; } can_obj_cfg[x][obj_idx] = ARM_CAN_OBJ_TX; break; case ARM_CAN_OBJ_RX: if (obj_idx >= CAN_RX_OBJ_NUM) { return ARM_DRIVER_ERROR_PARAMETER; } can_obj_cfg[x][obj_idx] = ARM_CAN_OBJ_RX; break; default: return ARM_DRIVER_ERROR; } return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) static int32_t CAN1_ObjectConfigure (uint32_t obj_idx, ARM_CAN_OBJ_CONFIG obj_cfg) { return CANx_ObjectConfigure (obj_idx, obj_cfg, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_ObjectConfigure (uint32_t obj_idx, ARM_CAN_OBJ_CONFIG obj_cfg) { return CANx_ObjectConfigure (obj_idx, obj_cfg, 1U); } #endif /** \fn int32_t CANx_MessageSend (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, const uint8_t *data, uint8_t size, uint8_t x) \brief Send message on CAN bus. \param[in] obj_idx Object index \param[in] msg_info Pointer to CAN message information \param[in] data Pointer to data buffer \param[in] size Number of data bytes to send \param[in] x Controller number (0..1) \return value >= 0 number of data bytes accepted to send \return value < 0 execution status */ static int32_t CANx_MessageSend (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, const uint8_t *data, uint8_t size, uint8_t x) { CAN_TypeDef *ptr_CAN; uint32_t data_tx[2]; uint32_t tir; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if ((obj_idx < CAN_RX_OBJ_NUM) || (obj_idx >= CAN_TOT_OBJ_NUM)) { return ARM_DRIVER_ERROR_PARAMETER; } if (can_driver_powered[x] == 0U) { return ARM_DRIVER_ERROR; } if (can_obj_cfg[x][obj_idx] != ARM_CAN_OBJ_TX) { return ARM_DRIVER_ERROR; } obj_idx -= CAN_RX_OBJ_NUM; // obj_idx origin to 0 ptr_CAN = ptr_CANx[x]; if ((ptr_CAN->sTxMailBox[obj_idx].TIR & CAN_TI0R_TXRQ) != 0U) { return ARM_DRIVER_ERROR_BUSY; } if ((msg_info->id & ARM_CAN_ID_IDE_Msk) != 0U) { // Extended Identifier tir = (msg_info->id << 3) | CAN_TI0R_IDE; } else { // Standard Identifier tir = (msg_info->id << 21); } if (size > 8U) { size = 8U; } if (msg_info->rtr != 0U) { // If send RTR requested size = 0U; tir |= CAN_TI0R_RTR; ptr_CAN->sTxMailBox[obj_idx].TDTR &= ~CAN_TDT0R_DLC; ptr_CAN->sTxMailBox[obj_idx].TDTR |= msg_info->dlc & CAN_TDT0R_DLC; } else { if (size != 8U) { data_tx[0] = 0U; data_tx[1] = 0U; } memcpy((uint8_t *)(&data_tx[0]), data, size); ptr_CAN->sTxMailBox[obj_idx].TDLR = data_tx[0]; ptr_CAN->sTxMailBox[obj_idx].TDHR = data_tx[1]; ptr_CAN->sTxMailBox[obj_idx].TDTR &= ~CAN_TDT0R_DLC; ptr_CAN->sTxMailBox[obj_idx].TDTR |= size & CAN_TDT0R_DLC; } ptr_CAN->sTxMailBox[obj_idx].TIR = tir | CAN_TI0R_TXRQ; // Activate transmit return ((int32_t)size); } #if (MX_CAN1 == 1U) static int32_t CAN1_MessageSend (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, const uint8_t *data, uint8_t size) { return CANx_MessageSend (obj_idx, msg_info, data, size, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_MessageSend (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, const uint8_t *data, uint8_t size) { return CANx_MessageSend (obj_idx, msg_info, data, size, 1U); } #endif /** \fn int32_t CANx_MessageRead (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, uint8_t *data, uint8_t size, uint8_t x) \brief Read message received on CAN bus. \param[in] obj_idx Object index \param[out] msg_info Pointer to read CAN message information \param[out] data Pointer to data buffer for read data \param[in] size Maximum number of data bytes to read \param[in] x Controller number (0..1) \return value >= 0 number of data bytes read \return value < 0 execution status */ static int32_t CANx_MessageRead (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, uint8_t *data, uint8_t size, uint8_t x) { CAN_TypeDef *ptr_CAN; uint32_t data_rx[2][2]; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (obj_idx >= CAN_RX_OBJ_NUM) { return ARM_DRIVER_ERROR_PARAMETER; } if (can_driver_powered[x] == 0U) { return ARM_DRIVER_ERROR; } if (can_obj_cfg[x][obj_idx] != ARM_CAN_OBJ_RX) { return ARM_DRIVER_ERROR; } ptr_CAN = ptr_CANx[x]; if (size > 8U) { size = 8U; } if ((ptr_CAN->sFIFOMailBox[obj_idx].RIR & CAN_RI0R_IDE) != 0U) { // Extended Identifier msg_info->id = (0x1FFFFFFFUL & (ptr_CAN->sFIFOMailBox[obj_idx].RIR >> 3)) | ARM_CAN_ID_IDE_Msk; } else { // Standard Identifier msg_info->id = ( 0x07FFUL & (ptr_CAN->sFIFOMailBox[obj_idx].RIR >> 21)); } if ((ptr_CAN->sFIFOMailBox[obj_idx].RIR & CAN_RI0R_RTR) != 0U) { msg_info->rtr = 1U; size = 0U; } else { msg_info->rtr = 0U; } msg_info->dlc = ptr_CAN->sFIFOMailBox[obj_idx].RDTR & CAN_RDT0R_DLC; if (size > 0U) { data_rx[x][0] = ptr_CAN->sFIFOMailBox[obj_idx].RDLR; data_rx[x][1] = ptr_CAN->sFIFOMailBox[obj_idx].RDHR; memcpy(data, (uint8_t *)(&data_rx[x][0]), size); } if (obj_idx == 1U) { ptr_CAN->RF1R = CAN_RF1R_RFOM1; // Release FIFO 1 output mailbox } else { ptr_CAN->RF0R = CAN_RF0R_RFOM0; // Release FIFO 0 output mailbox } return ((int32_t)size); } #if (MX_CAN1 == 1U) static int32_t CAN1_MessageRead (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, uint8_t *data, uint8_t size) { return CANx_MessageRead (obj_idx, msg_info, data, size, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_MessageRead (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, uint8_t *data, uint8_t size) { return CANx_MessageRead (obj_idx, msg_info, data, size, 1U); } #endif /** \fn int32_t CANx_Control (uint32_t control, uint32_t arg, uint8_t x) \brief Control CAN interface. \param[in] control Operation - ARM_CAN_SET_FD_MODE : set FD operation mode - ARM_CAN_ABORT_MESSAGE_SEND : abort sending of CAN message - ARM_CAN_CONTROL_RETRANSMISSION : enable/disable automatic retransmission - ARM_CAN_SET_TRANSCEIVER_DELAY : set transceiver delay \param[in] arg Argument of operation \param[in] x Controller number (0..1) \return execution status */ static int32_t CANx_Control (uint32_t control, uint32_t arg, uint8_t x) { CAN_TypeDef *ptr_CAN; if (x >= CAN_CTRL_NUM) { return ARM_DRIVER_ERROR; } if (can_driver_powered[x] == 0U) { return ARM_DRIVER_ERROR; } ptr_CAN = ptr_CANx[x]; switch (control & ARM_CAN_CONTROL_Msk) { case ARM_CAN_ABORT_MESSAGE_SEND: if ((arg < CAN_RX_OBJ_NUM) || (arg >= CAN_TOT_OBJ_NUM)) { return ARM_DRIVER_ERROR_PARAMETER; } arg -= CAN_RX_OBJ_NUM; switch (arg) { case 0: ptr_CAN->TSR = CAN_TSR_ABRQ0; break; case 1: ptr_CAN->TSR = CAN_TSR_ABRQ1; break; case 2: ptr_CAN->TSR = CAN_TSR_ABRQ2; break; default: return ARM_DRIVER_ERROR_PARAMETER; } break; case ARM_CAN_CONTROL_RETRANSMISSION: switch (arg) { case 0: ptr_CAN->MCR |= CAN_MCR_NART; break; case 1: ptr_CAN->MCR &= ~CAN_MCR_NART; break; default: return ARM_DRIVER_ERROR_PARAMETER; } break; case ARM_CAN_SET_FD_MODE: case ARM_CAN_SET_TRANSCEIVER_DELAY: default: return ARM_DRIVER_ERROR_UNSUPPORTED; } return ARM_DRIVER_OK; } #if (MX_CAN1 == 1U) static int32_t CAN1_Control (uint32_t control, uint32_t arg) { return CANx_Control (control, arg, 0U); } #endif #if (MX_CAN2 == 1U) static int32_t CAN2_Control (uint32_t control, uint32_t arg) { return CANx_Control (control, arg, 1U); } #endif /** \fn ARM_CAN_STATUS CANx_GetStatus (uint8_t x) \brief Get CAN status. \param[in] x Controller number (0..1) \return CAN status ARM_CAN_STATUS */ static ARM_CAN_STATUS CANx_GetStatus (uint8_t x) { CAN_TypeDef *ptr_CAN; ARM_CAN_STATUS can_status; uint32_t esr; ptr_CAN = ptr_CANx[x]; esr = ptr_CAN->ESR; ptr_CAN->ESR = CAN_ESR_LEC; // Software set last error code to unused value if ((ptr_CAN->MSR & CAN_MSR_INAK) != 0U) { can_status.unit_state = ARM_CAN_UNIT_STATE_INACTIVE; } else if (((ptr_CAN->BTR & CAN_BTR_LBKM) != 0U) || ((ptr_CAN->BTR & CAN_BTR_SILM) != 0U)) { can_status.unit_state = ARM_CAN_UNIT_STATE_PASSIVE; } else if ((esr & CAN_ESR_BOFF) != 0U) { can_status.unit_state = ARM_CAN_UNIT_STATE_INACTIVE; } else if ((esr & CAN_ESR_EPVF) != 0U) { can_status.unit_state = ARM_CAN_UNIT_STATE_PASSIVE; } else { can_status.unit_state = ARM_CAN_UNIT_STATE_ACTIVE; } switch ((esr & CAN_ESR_LEC) >> 4) { case 0: can_status.last_error_code = ARM_CAN_LEC_NO_ERROR; break; case 1: can_status.last_error_code = ARM_CAN_LEC_STUFF_ERROR; break; case 2: can_status.last_error_code = ARM_CAN_LEC_FORM_ERROR; break; case 3: can_status.last_error_code = ARM_CAN_LEC_ACK_ERROR; break; case 4: case 5: can_status.last_error_code = ARM_CAN_LEC_BIT_ERROR; break; case 6: can_status.last_error_code = ARM_CAN_LEC_CRC_ERROR; break; case 7: can_status.last_error_code = ARM_CAN_LEC_NO_ERROR; break; } can_status.tx_error_count = (uint8_t)((esr & CAN_ESR_TEC) >> 16); can_status.rx_error_count = (uint8_t)((esr & CAN_ESR_REC) >> 24); return can_status; } #if (MX_CAN1 == 1U) static ARM_CAN_STATUS CAN1_GetStatus (void) { return CANx_GetStatus (0); } #endif #if (MX_CAN2 == 1U) static ARM_CAN_STATUS CAN2_GetStatus (void) { return CANx_GetStatus (1); } #endif #if (MX_CAN1 == 1U) /** \fn void CAN1_TX_IRQHandler (void) \brief CAN1 Transmit Interrupt Routine (IRQ). */ #ifdef STM32F10X_CL void CAN1_TX_IRQHandler (void) { #else void USB_HP_CAN1_TX_IRQHandler (void) { #endif uint32_t esr, ier; if ((CAN1->TSR & CAN_TSR_RQCP0) != 0U) { if ((CAN1->TSR & CAN_TSR_TXOK0) != 0U) { if (can_obj_cfg[0][CAN_RX_OBJ_NUM] == ARM_CAN_OBJ_TX) { if (CAN_SignalObjectEvent[0] != NULL) { CAN_SignalObjectEvent[0](CAN_RX_OBJ_NUM, ARM_CAN_EVENT_SEND_COMPLETE); } } } CAN1->TSR = CAN_TSR_RQCP0; // Request completed on transmit mailbox 0 } if ((CAN1->TSR & CAN_TSR_RQCP1) != 0U) { if ((CAN1->TSR & CAN_TSR_TXOK1) != 0U) { if (can_obj_cfg[0][CAN_RX_OBJ_NUM+1U] == ARM_CAN_OBJ_TX) { if (CAN_SignalObjectEvent[0] != NULL) { CAN_SignalObjectEvent[0](CAN_RX_OBJ_NUM+1U, ARM_CAN_EVENT_SEND_COMPLETE); } } } CAN1->TSR = CAN_TSR_RQCP1; // Request completed on transmit mailbox 1 } if ((CAN1->TSR & CAN_TSR_RQCP2) != 0U) { if ((CAN1->TSR & CAN_TSR_TXOK2) != 0U) { if (can_obj_cfg[0][CAN_RX_OBJ_NUM+2U] == ARM_CAN_OBJ_TX) { if (CAN_SignalObjectEvent[0] != NULL) { CAN_SignalObjectEvent[0](CAN_RX_OBJ_NUM+2U, ARM_CAN_EVENT_SEND_COMPLETE); } } } CAN1->TSR = CAN_TSR_RQCP2; // Request completed on transmit mailbox 2 } // Handle transition from from 'bus off', ' error active' state, or re-enable warning interrupt esr = CAN1->ESR; ier = CAN1->IER; if (((esr & CAN_ESR_BOFF) == 0U) && ((ier & CAN_IER_BOFIE) == 0U)) { CAN1->IER |= CAN_IER_BOFIE; if (CAN_SignalUnitEvent[0] != NULL) { CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_PASSIVE); } } if (((esr & CAN_ESR_EPVF) == 0U) && ((ier & CAN_IER_EPVIE) == 0U)) { CAN1->IER |= CAN_IER_EPVIE; if (CAN_SignalUnitEvent[0] != NULL) { CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_ACTIVE); } } if (((esr & CAN_ESR_EWGF) == 0U) && ((ier & CAN_IER_EWGIE) == 0U) && (((esr & CAN_ESR_TEC) >> 16) == 95U) && (((esr & CAN_ESR_REC) >> 24) < 95U)) { CAN1->IER |= CAN_IER_EWGIE; } } /** \fn void CAN1_RX0_IRQHandler (void) \brief CAN1 Receive on FIFO0 Interrupt Routine (IRQ). */ #ifdef STM32F10X_CL void CAN1_RX0_IRQHandler (void) { #else void USB_LP_CAN1_RX0_IRQHandler (void) { #endif uint32_t esr, ier; if (can_obj_cfg[0][0] == ARM_CAN_OBJ_RX) { if ((CAN1->RF0R & CAN_RF0R_FOVR0) != 0U) { CAN1->RF0R = CAN_RF0R_FOVR0; // Clear overrun flag if (CAN_SignalObjectEvent[0] != NULL) { CAN_SignalObjectEvent[0](0U, ARM_CAN_EVENT_RECEIVE | ARM_CAN_EVENT_RECEIVE_OVERRUN); } } else if ((CAN1->RF0R & CAN_RF0R_FMP0) != 0U) { if (CAN_SignalObjectEvent[0] != NULL) { CAN_SignalObjectEvent[0](0U, ARM_CAN_EVENT_RECEIVE); } } } else { CAN1->RF0R = CAN_RF0R_RFOM0; // Release FIFO 0 output mailbox if object not enabled for reception } // Handle transition from from 'bus off', ' error active' state, or re-enable warning interrupt esr = CAN1->ESR; ier = CAN1->IER; if (((esr & CAN_ESR_BOFF) == 0U) && ((ier & CAN_IER_BOFIE) == 0U)) { CAN1->IER |= CAN_IER_BOFIE; if (CAN_SignalUnitEvent[0] != NULL) { CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_PASSIVE); } } if (((esr & CAN_ESR_EPVF) == 0U) && ((ier & CAN_IER_EPVIE) == 0U)) { CAN1->IER |= CAN_IER_EPVIE; if (CAN_SignalUnitEvent[0] != NULL) { CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_ACTIVE); } } if (((esr & CAN_ESR_EWGF) == 0U) && ((ier & CAN_IER_EWGIE) == 0U) && (((esr & CAN_ESR_TEC) >> 16) < 95U) && (((esr & CAN_ESR_REC) >> 24) == 95U)) { CAN1->IER |= CAN_IER_EWGIE; } } /** \fn void CAN1_RX1_IRQHandler (void) \brief CAN1 Receive on FIFO1 Interrupt Routine (IRQ). */ void CAN1_RX1_IRQHandler (void) { uint32_t esr, ier; if (can_obj_cfg[0][1] == ARM_CAN_OBJ_RX) { if ((CAN1->RF1R & CAN_RF1R_FOVR1) != 0U) { CAN1->RF1R = CAN_RF1R_FOVR1; // Clear overrun flag if (CAN_SignalObjectEvent[0] != NULL) { CAN_SignalObjectEvent[0](1U, ARM_CAN_EVENT_RECEIVE | ARM_CAN_EVENT_RECEIVE_OVERRUN); } } else if ((CAN1->RF1R & CAN_RF1R_FMP1) != 0U) { if (CAN_SignalObjectEvent[0] != NULL) { CAN_SignalObjectEvent[0](1U, ARM_CAN_EVENT_RECEIVE); } } } else { CAN1->RF1R = CAN_RF1R_RFOM1; // Release FIFO 1 output mailbox if object not enabled for reception } // Handle transition from from 'bus off', ' error active' state, or re-enable warning interrupt esr = CAN1->ESR; ier = CAN1->IER; if (((esr & CAN_ESR_BOFF) == 0U) && ((ier & CAN_IER_BOFIE) == 0U)) { CAN1->IER |= CAN_IER_BOFIE; if (CAN_SignalUnitEvent[0] != NULL) { CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_PASSIVE); } } if (((esr & CAN_ESR_EPVF) == 0U) && ((ier & CAN_IER_EPVIE) == 0U)) { CAN1->IER |= CAN_IER_EPVIE; if (CAN_SignalUnitEvent[0] != NULL) { CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_ACTIVE); } } if (((esr & CAN_ESR_EWGF) == 0U) && ((ier & CAN_IER_EWGIE) == 0U) && (((esr & CAN_ESR_TEC) >> 16) < 95U) && (((esr & CAN_ESR_REC) >> 24) == 95U)) { CAN1->IER |= CAN_IER_EWGIE; } } /** \fn void CAN1_SCE_IRQHandler (void) \brief CAN1 Error and Status Change Interrupt Routine (IRQ). */ void CAN1_SCE_IRQHandler (void) { uint32_t esr, ier; if (CAN_SignalUnitEvent[0] != NULL) { esr = CAN1->ESR; ier = CAN1->IER; CAN1->MSR = CAN_MSR_ERRI; // Clear error interrupt if (((esr & CAN_ESR_BOFF) != 0U) && ((ier & CAN_IER_BOFIE) != 0U)) { CAN1->IER &= ~CAN_IER_BOFIE; CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_BUS_OFF); } else if (((esr & CAN_ESR_EPVF) != 0U) && ((ier & CAN_IER_EPVIE) != 0U)) { CAN1->IER &= ~CAN_IER_EPVIE; CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_PASSIVE); } else if (((esr & CAN_ESR_EWGF) != 0U) && ((ier & CAN_IER_EWGIE) != 0U)) { CAN1->IER &= ~CAN_IER_EWGIE; CAN_SignalUnitEvent[0](ARM_CAN_EVENT_UNIT_WARNING); } } } #endif #if (MX_CAN2 == 1U) /** \fn void CAN2_TX_IRQHandler (void) \brief CAN2 Transmit Interrupt Routine (IRQ). */ void CAN2_TX_IRQHandler (void) { uint32_t esr, ier; if ((CAN2->TSR & CAN_TSR_TXOK0) != 0U) { if (can_obj_cfg[1][CAN_RX_OBJ_NUM] == ARM_CAN_OBJ_TX) { if (CAN_SignalObjectEvent[1] != NULL) { CAN_SignalObjectEvent[1](CAN_RX_OBJ_NUM, ARM_CAN_EVENT_SEND_COMPLETE); } } CAN2->TSR = CAN_TSR_RQCP0; // Request completed on transmit mailbox 0 } if ((CAN2->TSR & CAN_TSR_TXOK1) != 0U) { if (can_obj_cfg[1][CAN_RX_OBJ_NUM+1U] == ARM_CAN_OBJ_TX) { if (CAN_SignalObjectEvent[1] != NULL) { CAN_SignalObjectEvent[1](CAN_RX_OBJ_NUM+1U, ARM_CAN_EVENT_SEND_COMPLETE); } } CAN2->TSR = CAN_TSR_RQCP1; // Request completed on transmit mailbox 1 } if ((CAN2->TSR & CAN_TSR_TXOK2) != 0U) { if (can_obj_cfg[1][CAN_RX_OBJ_NUM+2U] == ARM_CAN_OBJ_TX) { if (CAN_SignalObjectEvent[1] != NULL) { CAN_SignalObjectEvent[1](CAN_RX_OBJ_NUM+2U, ARM_CAN_EVENT_SEND_COMPLETE); } } CAN2->TSR = CAN_TSR_RQCP2; // Request completed on transmit mailbox 2 } // Handle transition from from 'bus off', ' error active' state, or re-enable warning interrupt esr = CAN2->ESR; ier = CAN2->IER; if (((esr & CAN_ESR_BOFF) == 0U) && ((ier & CAN_IER_BOFIE) == 0U)) { CAN2->IER |= CAN_IER_BOFIE; if (CAN_SignalUnitEvent[1] != NULL) { CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_PASSIVE); } } if (((esr & CAN_ESR_EPVF) == 0U) && ((ier & CAN_IER_EPVIE) == 0U)) { CAN2->IER |= CAN_IER_EPVIE; if (CAN_SignalUnitEvent[1] != NULL) { CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_ACTIVE); } } if (((esr & CAN_ESR_EWGF) == 0U) && ((ier & CAN_IER_EWGIE) == 0U) && (((esr & CAN_ESR_TEC) >> 16) == 95U) && (((esr & CAN_ESR_REC) >> 24) < 95U)) { CAN2->IER |= CAN_IER_EWGIE; } } /** \fn void CAN2_RX0_IRQHandler (void) \brief CAN2 Receive on FIFO0 Interrupt Routine (IRQ). */ void CAN2_RX0_IRQHandler (void) { uint32_t esr, ier; if (can_obj_cfg[1][0] == ARM_CAN_OBJ_RX) { if ((CAN2->RF0R & CAN_RF0R_FOVR0) != 0U) { CAN2->RF0R = CAN_RF0R_FOVR0; // Clear overrun flag if (CAN_SignalObjectEvent[1] != NULL) { CAN_SignalObjectEvent[1](0U, ARM_CAN_EVENT_RECEIVE | ARM_CAN_EVENT_RECEIVE_OVERRUN); } } else if ((CAN2->RF0R & CAN_RF0R_FMP0) != 0U) { if (CAN_SignalObjectEvent[1] != NULL) { CAN_SignalObjectEvent[1](0U, ARM_CAN_EVENT_RECEIVE); } } } else { CAN2->RF0R = CAN_RF0R_RFOM0; // Release FIFO 0 output mailbox if object not enabled for reception } // Handle transition from from 'bus off', ' error active' state, or re-enable warning interrupt esr = CAN2->ESR; ier = CAN2->IER; if (((esr & CAN_ESR_BOFF) == 0U) && ((ier & CAN_IER_BOFIE) == 0U)) { CAN2->IER |= CAN_IER_BOFIE; if (CAN_SignalUnitEvent[1] != NULL) { CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_PASSIVE); } } if (((esr & CAN_ESR_EPVF) == 0U) && ((ier & CAN_IER_EPVIE) == 0U)) { CAN2->IER |= CAN_IER_EPVIE; if (CAN_SignalUnitEvent[1] != NULL) { CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_ACTIVE); } } if (((esr & CAN_ESR_EWGF) == 0U) && ((ier & CAN_IER_EWGIE) == 0U) && (((esr & CAN_ESR_TEC) >> 16) < 95U) && (((esr & CAN_ESR_REC) >> 24) == 95U)) { CAN2->IER |= CAN_IER_EWGIE; } } /** \fn void CAN2_RX1_IRQHandler (void) \brief CAN2 Receive on FIFO1 Interrupt Routine (IRQ). */ void CAN2_RX1_IRQHandler (void) { uint32_t esr, ier; if (can_obj_cfg[1][1] == ARM_CAN_OBJ_RX) { if ((CAN2->RF1R & CAN_RF1R_FOVR1) != 0U) { CAN2->RF1R = CAN_RF1R_FOVR1; // Clear overrun flag if (CAN_SignalObjectEvent[1] != NULL) { CAN_SignalObjectEvent[1](1U, ARM_CAN_EVENT_RECEIVE | ARM_CAN_EVENT_RECEIVE_OVERRUN); } } else if ((CAN2->RF1R & CAN_RF1R_FMP1) != 0U) { if (CAN_SignalObjectEvent[1] != NULL) { CAN_SignalObjectEvent[1](1U, ARM_CAN_EVENT_RECEIVE); } } } else { CAN2->RF1R = CAN_RF1R_RFOM1; // Release FIFO 1 output mailbox if object not enabled for reception } // Handle transition from from 'bus off', ' error active' state, or re-enable warning interrupt esr = CAN2->ESR; ier = CAN2->IER; if (((esr & CAN_ESR_BOFF) == 0U) && ((ier & CAN_IER_BOFIE) == 0U)) { CAN2->IER |= CAN_IER_BOFIE; if (CAN_SignalUnitEvent[1] != NULL) { CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_PASSIVE); } } if (((esr & CAN_ESR_EPVF) == 0U) && ((ier & CAN_IER_EPVIE) == 0U)) { CAN2->IER |= CAN_IER_EPVIE; if (CAN_SignalUnitEvent[1] != NULL) { CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_ACTIVE); } } if (((esr & CAN_ESR_EWGF) == 0U) && ((ier & CAN_IER_EWGIE) == 0U) && (((esr & CAN_ESR_TEC) >> 16) < 95U) && (((esr & CAN_ESR_REC) >> 24) == 95U)) { CAN2->IER |= CAN_IER_EWGIE; } } /** \fn void CAN2_SCE_IRQHandler (void) \brief CAN2 Error and Status Change Interrupt Routine (IRQ). */ void CAN2_SCE_IRQHandler (void) { uint32_t esr, ier; if (CAN_SignalUnitEvent[1] != NULL) { esr = CAN2->ESR; ier = CAN2->IER; CAN2->MSR = CAN_MSR_ERRI; // Clear error interrupt if (((esr & CAN_ESR_BOFF) != 0U) && ((ier & CAN_IER_BOFIE) != 0U)) { CAN2->IER &= ~CAN_IER_BOFIE; CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_BUS_OFF); } else if (((esr & CAN_ESR_EPVF) != 0U) && ((ier & CAN_IER_EPVIE) != 0U)) { CAN2->IER &= ~CAN_IER_EPVIE; CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_PASSIVE); } else if (((esr & CAN_ESR_EWGF) != 0U) && ((ier & CAN_IER_EWGIE) != 0U)) { CAN2->IER &= ~CAN_IER_EWGIE; CAN_SignalUnitEvent[1](ARM_CAN_EVENT_UNIT_WARNING); } } } #endif #if (MX_CAN1 == 1U) ARM_DRIVER_CAN Driver_CAN1 = { CAN_GetVersion, CAN_GetCapabilities, CAN1_Initialize, CAN1_Uninitialize, CAN1_PowerControl, CAN_GetClock, CAN1_SetBitrate, CAN1_SetMode, CAN1_ObjectGetCapabilities, CAN1_ObjectSetFilter, CAN1_ObjectConfigure, CAN1_MessageSend, CAN1_MessageRead, CAN1_Control, CAN1_GetStatus }; #endif #if (MX_CAN2 == 1U) ARM_DRIVER_CAN Driver_CAN2 = { CAN_GetVersion, CAN_GetCapabilities, CAN2_Initialize, CAN2_Uninitialize, CAN2_PowerControl, CAN_GetClock, CAN2_SetBitrate, CAN2_SetMode, CAN2_ObjectGetCapabilities, CAN2_ObjectSetFilter, CAN2_ObjectConfigure, CAN2_MessageSend, CAN2_MessageRead, CAN2_Control, CAN2_GetStatus }; #endif /*! \endcond */