mirror of
https://github.com/Dev-KATECH/ADM.git
synced 2026-05-17 09:53:59 +09:00
2523 lines
100 KiB
C
2523 lines
100 KiB
C
/**
|
|
* @file FlexCAN_Ip_HwAccess.c
|
|
*
|
|
* @brief FlexCAN Functions to Hardware Acess
|
|
*
|
|
* @addtogroup FlexCAN
|
|
* @{
|
|
*/
|
|
/*==================================================================================================
|
|
* Project : RTD AUTOSAR 4.4
|
|
* Platform : CORTEXM
|
|
* Peripheral : FLEXCAN
|
|
* Dependencies :
|
|
*
|
|
* Autosar Version : 4.4.0
|
|
* Autosar Revision : ASR_REL_4_4_REV_0000
|
|
* Autosar Conf.Variant :
|
|
* SW Version : 0.9.0
|
|
* Build Version : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326
|
|
*
|
|
* (c) Copyright 2020 - 2021 NXP Semiconductors
|
|
* All Rights Reserved.
|
|
*
|
|
* NXP Confidential. This software is owned or controlled by NXP and may only be
|
|
* used strictly in accordance with the applicable license terms. By expressly
|
|
* accepting such terms or by downloading, installing, activating and/or otherwise
|
|
* using the software, you are agreeing that you have read, and that you agree to
|
|
* comply with and are bound by, such license terms. If you do not agree to be
|
|
* bound by the applicable license terms, then you may not retain, install,
|
|
* activate or otherwise use the software.
|
|
==================================================================================================*/
|
|
/*==================================================================================================
|
|
* INCLUDE FILES
|
|
* 1) system and project includes
|
|
* 2) needed interfaces from external units
|
|
* 3) internal and external interfaces from this unit
|
|
==================================================================================================*/
|
|
#include "FlexCAN_Ip_HwAccess.h"
|
|
#include "SchM_Can.h"
|
|
|
|
/*==================================================================================================
|
|
* SOURCE FILE VERSION INFORMATION
|
|
==================================================================================================*/
|
|
#define FLEXCAN_IP_HWACCESS_VENDOR_ID_C 43
|
|
#define FLEXCAN_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION_C 4
|
|
#define FLEXCAN_IP_HWACCESS_AR_RELEASE_MINOR_VERSION_C 4
|
|
#define FLEXCAN_IP_HWACCESS_AR_RELEASE_REVISION_VERSION_C 0
|
|
#define FLEXCAN_IP_HWACCESS_SW_MAJOR_VERSION_C 0
|
|
#define FLEXCAN_IP_HWACCESS_SW_MINOR_VERSION_C 9
|
|
#define FLEXCAN_IP_HWACCESS_SW_PATCH_VERSION_C 0
|
|
/*==================================================================================================
|
|
* FILE VERSION CHECKS
|
|
==================================================================================================*/
|
|
/* Check if current file and FlexCAN_Ip_HwAccess header file are of the same vendor */
|
|
#if (FLEXCAN_IP_HWACCESS_VENDOR_ID_C != FLEXCAN_IP_HWACCESS_VENDOR_ID_H)
|
|
#error "FlexCAN_Ip_HwAccess.c and FlexCAN_Ip_HwAccess.h have different vendor ids"
|
|
#endif
|
|
/* Check if current file and CAN header file are of the same Autosar version */
|
|
#if ((FLEXCAN_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION_C != FLEXCAN_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION_H) || \
|
|
(FLEXCAN_IP_HWACCESS_AR_RELEASE_MINOR_VERSION_C != FLEXCAN_IP_HWACCESS_AR_RELEASE_MINOR_VERSION_H) || \
|
|
(FLEXCAN_IP_HWACCESS_AR_RELEASE_REVISION_VERSION_C != FLEXCAN_IP_HWACCESS_AR_RELEASE_REVISION_VERSION_H))
|
|
#error "AutoSar Version Numbers of FlexCAN_Ip_HwAccess.c and FlexCAN_Ip_HwAccess.h are different"
|
|
#endif
|
|
/* Check if current file and CAN header file are of the same Software version */
|
|
#if ((FLEXCAN_IP_HWACCESS_SW_MAJOR_VERSION_C != FLEXCAN_IP_HWACCESS_SW_MAJOR_VERSION_H) || \
|
|
(FLEXCAN_IP_HWACCESS_SW_MINOR_VERSION_C != FLEXCAN_IP_HWACCESS_SW_MINOR_VERSION_H) || \
|
|
(FLEXCAN_IP_HWACCESS_SW_PATCH_VERSION_C != FLEXCAN_IP_HWACCESS_SW_PATCH_VERSION_H))
|
|
#error "Software Version Numbers of FlexCAN_Ip_HwAccess.c and FlexCAN_Ip_HwAccess.h are different"
|
|
#endif
|
|
|
|
#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
|
|
/* Check if current file and SchM_Can header file are of the same version */
|
|
#endif
|
|
/*==================================================================================================
|
|
* LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
|
|
==================================================================================================*/
|
|
|
|
/*==================================================================================================
|
|
* LOCAL MACROS
|
|
==================================================================================================*/
|
|
/* CAN FD extended data length DLC encoding */
|
|
#define CAN_DLC_VALUE_12_BYTES 9U
|
|
#define CAN_DLC_VALUE_16_BYTES 10U
|
|
#define CAN_DLC_VALUE_20_BYTES 11U
|
|
#define CAN_DLC_VALUE_24_BYTES 12U
|
|
#define CAN_DLC_VALUE_32_BYTES 13U
|
|
#define CAN_DLC_VALUE_48_BYTES 14U
|
|
#define CAN_DLC_VALUE_64_BYTES 15U
|
|
|
|
#define RxFifoFilterTableOffset 0x18U
|
|
#define FlexCanRxFifoAcceptRemoteFrame 1UL
|
|
#define FlexCanRxFifoAcceptExtFrame 1UL
|
|
|
|
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
|
|
#define FlexCanEnhancedRxFifoOneIDFilter 0UL
|
|
#define FlexCanEnhancedRxFifoRangerIDFilter 1UL
|
|
#define FlexCanEnhancedRxFifoTwoIDFilter 2UL
|
|
#define EnhancedRxFifoFilterTableBase 0x0U
|
|
#endif
|
|
|
|
/* Determines the RxFIFO Filter element number */
|
|
#define RXFIFO_FILTER_ELEM_NUM(x) (((x) + 1U) * 8U)
|
|
/*==================================================================================================
|
|
* LOCAL CONSTANTS
|
|
==================================================================================================*/
|
|
|
|
/*==================================================================================================
|
|
* GLOBAL CONSTANTS
|
|
==================================================================================================*/
|
|
|
|
/*==================================================================================================
|
|
* GLOBAL VARIABLES
|
|
==================================================================================================*/
|
|
#define CAN_START_SEC_VAR_NO_INIT_32_NO_CACHEABLE
|
|
#include "Can_MemMap.h"
|
|
|
|
static volatile uint32 g_FlexCAN_u32ImaskBuff[FLEXCAN_INSTANCE_COUNT][FEATURE_CAN_MBDSR_COUNT];
|
|
|
|
#define CAN_STOP_SEC_VAR_NO_INIT_32_NO_CACHEABLE
|
|
#include "Can_MemMap.h"
|
|
|
|
|
|
#define CAN_START_SEC_CODE
|
|
#include "Can_MemMap.h"
|
|
/*==================================================================================================
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
==================================================================================================*/
|
|
static uint8 FlexCAN_ComputeDLCValue(uint8 payloadSize);
|
|
|
|
static void FlexCAN_ClearRAM(FLEXCAN_Type * base);
|
|
|
|
#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
|
|
static boolean FlexCAN_IsExpandableMemoryAvailable(const FLEXCAN_Type * base);
|
|
#endif /* if FEATURE_CAN_HAS_EXPANDABLE_MEMORY */
|
|
|
|
/*==================================================================================================
|
|
* LOCAL FUNCTIONS
|
|
==================================================================================================*/
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name: FLEXCAN_ComputeDLCValue
|
|
* Description : Computes the DLC field value, given a payload size (in bytes).
|
|
*
|
|
*END**************************************************************************/
|
|
static uint8 FlexCAN_ComputeDLCValue(uint8 payloadSize)
|
|
{
|
|
uint32 ret = 0xFFU; /* 0, 1, 2, 3, 4, 5, 6, 7, 8, */
|
|
static const uint8 payload_code[65] = { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U,
|
|
/* 9 to 12 payload have DLC Code 12 Bytes */
|
|
CAN_DLC_VALUE_12_BYTES, CAN_DLC_VALUE_12_BYTES, CAN_DLC_VALUE_12_BYTES, CAN_DLC_VALUE_12_BYTES,
|
|
/* 13 to 16 payload have DLC Code 16 Bytes */
|
|
CAN_DLC_VALUE_16_BYTES, CAN_DLC_VALUE_16_BYTES, CAN_DLC_VALUE_16_BYTES, CAN_DLC_VALUE_16_BYTES,
|
|
/* 17 to 20 payload have DLC Code 20 Bytes */
|
|
CAN_DLC_VALUE_20_BYTES, CAN_DLC_VALUE_20_BYTES, CAN_DLC_VALUE_20_BYTES, CAN_DLC_VALUE_20_BYTES,
|
|
/* 21 to 24 payload have DLC Code 24 Bytes */
|
|
CAN_DLC_VALUE_24_BYTES, CAN_DLC_VALUE_24_BYTES, CAN_DLC_VALUE_24_BYTES, CAN_DLC_VALUE_24_BYTES,
|
|
/* 25 to 32 payload have DLC Code 32 Bytes */
|
|
CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES,
|
|
CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES,
|
|
/* 33 to 48 payload have DLC Code 48 Bytes */
|
|
CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
|
|
CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
|
|
CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
|
|
CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
|
|
/* 49 to 64 payload have DLC Code 64 Bytes */
|
|
CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES,
|
|
CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES,
|
|
CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES,
|
|
CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES };
|
|
|
|
if (payloadSize <= 64U)
|
|
{
|
|
ret = payload_code[payloadSize];
|
|
}
|
|
else
|
|
{
|
|
/* The argument is not a valid payload size will return 0xFF*/
|
|
}
|
|
|
|
return (uint8)ret;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_ClearRAM
|
|
* Description : Clears FlexCAN memory positions that require initialization.
|
|
*
|
|
*END**************************************************************************/
|
|
static void FlexCAN_ClearRAM(FLEXCAN_Type * base)
|
|
{
|
|
uint32 databyte;
|
|
uint32 ram_addr;
|
|
uint32 RAM_size = FlexCAN_GetMaxMbNum(base) * 4U;
|
|
uint32 RXIMR_size = FlexCAN_GetMaxMbNum(base);
|
|
/* Address of base + ram offset to point to MB start address */
|
|
volatile uint32 * RAM = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
|
|
/* Clear MB region */
|
|
for (databyte = 0U; databyte < RAM_size; databyte++)
|
|
{
|
|
RAM[databyte] = 0x0U;
|
|
}
|
|
RAM = base->RXIMR;
|
|
/* Clear RXIMR region */
|
|
for (databyte = 0U; databyte < RXIMR_size; databyte++)
|
|
{
|
|
RAM[databyte] = 0x0U;
|
|
}
|
|
#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
|
|
if (FlexCAN_IsExpandableMemoryAvailable(base))
|
|
{
|
|
RAM = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_EXP_RAM_OFFSET);
|
|
/* Clear Expanded Memory region */
|
|
for (databyte = 0U; databyte < CAN_RAM1n_COUNT; databyte++)
|
|
{
|
|
RAM[databyte] = 0x0U;
|
|
}
|
|
}
|
|
#endif /* if FEATURE_CAN_HAS_EXPANDABLE_MEMORY */
|
|
|
|
#if (FEATURE_CAN_HAS_MEM_ERR_DET == STD_ON)
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_01();
|
|
/* Set WRMFRZ bit in CTRL2 Register to grant write access to memory */
|
|
base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_WRMFRZ_MASK) | FLEXCAN_CTRL2_WRMFRZ(1U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_01();
|
|
ram_addr = (uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET;
|
|
RAM = (volatile uint32 *)ram_addr;
|
|
/* Clear RXMGMASK, RXFGMASK, RX14MASK, RX15MASK RAM mapping */
|
|
base->RXMGMASK = 0U;
|
|
base->RXFGMASK = 0U;
|
|
base->RX14MASK = 0U;
|
|
base->RX15MASK = 0U;
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
/* Clear SMB FD region */
|
|
for (databyte = 0U; databyte < (uint32)1U; databyte++)
|
|
{
|
|
RAM[databyte] = 0U;
|
|
}
|
|
#endif
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_01();
|
|
/* Clear WRMFRZ bit in CTRL2 Register to restrict write access to memory */
|
|
base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_WRMFRZ_MASK) | FLEXCAN_CTRL2_WRMFRZ(0U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_01();
|
|
#endif /* if FEATURE_CAN_HAS_MEM_ERR_DET */
|
|
}
|
|
|
|
#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_IsExpandableMemoryAvailable
|
|
* Description : Checks if FlexCAN has expandable memory.
|
|
* This function is private.
|
|
*
|
|
*END**************************************************************************/
|
|
static boolean FlexCAN_IsExpandableMemoryAvailable(const FLEXCAN_Type * base)
|
|
{
|
|
uint32 i;
|
|
static FLEXCAN_Type * const flexcanBase[] = CAN_BASE_PTRS_HAS_EXPANDABLE_MEMORY;
|
|
boolean returnValue = FALSE;
|
|
for (i = 0U; i < FEATURE_CAN_EXPANDABLE_MEMORY_NUM; i++)
|
|
{
|
|
if (base == flexcanBase[i])
|
|
{
|
|
returnValue = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
#endif /* if FEATURE_CAN_HAS_EXPANDABLE_MEMORY */
|
|
|
|
/*==================================================================================================
|
|
* GLOBAL FUNCTIONS
|
|
==================================================================================================*/
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_ComputePayloadSize
|
|
* Description : Computes the maximum payload size (in bytes), given a DLC
|
|
* field value.
|
|
*
|
|
*END**************************************************************************/
|
|
uint8 FlexCAN_ComputePayloadSize(uint8 dlcValue)
|
|
{
|
|
uint8 ret = 8U;
|
|
if (dlcValue <= 8U)
|
|
{
|
|
ret = dlcValue;
|
|
}
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
else
|
|
{
|
|
switch (dlcValue)
|
|
{
|
|
case CAN_DLC_VALUE_12_BYTES:
|
|
ret = 12U;
|
|
break;
|
|
case CAN_DLC_VALUE_16_BYTES:
|
|
ret = 16U;
|
|
break;
|
|
case CAN_DLC_VALUE_20_BYTES:
|
|
ret = 20U;
|
|
break;
|
|
case CAN_DLC_VALUE_24_BYTES:
|
|
ret = 24U;
|
|
break;
|
|
case CAN_DLC_VALUE_32_BYTES:
|
|
ret = 32U;
|
|
break;
|
|
case CAN_DLC_VALUE_48_BYTES:
|
|
ret = 48U;
|
|
break;
|
|
case CAN_DLC_VALUE_64_BYTES:
|
|
ret = 64U;
|
|
break;
|
|
default:
|
|
/* The argument is not a valid DLC size */
|
|
break;
|
|
}
|
|
}
|
|
#endif /* FEATURE_CAN_HAS_FD */
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_GetMsgBuffRegion
|
|
* Description : Returns the start of a MB area, based on its index.
|
|
*
|
|
*END**************************************************************************/
|
|
volatile uint32 * FlexCAN_GetMsgBuffRegion(const FLEXCAN_Type * base,
|
|
uint32 msgBuffIdx)
|
|
{
|
|
uint8 arbitration_field_size = 8U;
|
|
uint8 mb_size = 0U;
|
|
uint32 ramBlockSize = 512U;
|
|
uint32 ramBlockOffset = 0;
|
|
uint32 msgBuffIdxBackup = msgBuffIdx;
|
|
uint8 i=0U;
|
|
uint8 maxMbNum=0U;
|
|
uint32 mb_index=0U;
|
|
uint8 payload_size=0U;
|
|
volatile uint32 * RAM = (uint32*)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
|
|
volatile uint32 * pAddressRet = NULL_PTR;
|
|
#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
|
|
volatile uint32 * RAM_EXPANDED = (uint32*)((uint32)base + (uint32)FEATURE_CAN_EXP_RAM_OFFSET);
|
|
#endif
|
|
|
|
for (i=0; i< (uint8)FEATURE_CAN_MBDSR_COUNT; i++)
|
|
{
|
|
payload_size = FlexCAN_GetPayloadSize(base, i);
|
|
mb_size = (uint8)(payload_size + arbitration_field_size);
|
|
maxMbNum = (uint8)(ramBlockSize / mb_size);
|
|
if (maxMbNum > msgBuffIdxBackup)
|
|
{
|
|
break;
|
|
}
|
|
ramBlockOffset += 128U;
|
|
msgBuffIdxBackup -= maxMbNum;
|
|
}
|
|
|
|
#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
|
|
if (((uint8)FEATURE_CAN_MBDSR_COUNT == i) && ((boolean)TRUE == FlexCAN_IsExpandableMemoryAvailable(base)))
|
|
{
|
|
/* Multiply the MB index by the MB size (in words) */
|
|
/* for expanded ramblock:
|
|
* maxMbNum per one block: 7
|
|
* mb_size per one Mb: 72
|
|
*/
|
|
mb_index = ((msgBuffIdxBackup / 7U) * 128U) + ((msgBuffIdxBackup % 7U) * (72U >> 2U));
|
|
pAddressRet = &(RAM_EXPANDED[mb_index]);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/* Multiply the MB index by the MB size (in words) */
|
|
mb_index = ramBlockOffset + ((msgBuffIdxBackup % (uint32)maxMbNum) * ((uint32)mb_size >> 2U));
|
|
pAddressRet = &(RAM[mb_index]);
|
|
}
|
|
|
|
return pAddressRet;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_GetMaxMbNum
|
|
* Description : Computes the maximum RAM size occupied by MBs.
|
|
*
|
|
*END**************************************************************************/
|
|
uint32 FlexCAN_GetMaxMbNum(const FLEXCAN_Type * base)
|
|
{
|
|
uint32 i, ret = 0u;
|
|
static FLEXCAN_Type * const flexcanBase[] = FLEXCAN_BASE_PTRS;
|
|
static const uint32 maxMbNum[] = FEATURE_CAN_MAX_MB_NUM_ARRAY;
|
|
|
|
for (i = 0u; i < FLEXCAN_INSTANCE_COUNT; i++)
|
|
{
|
|
if (base == flexcanBase[i])
|
|
{
|
|
ret = maxMbNum[i];
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_EnterFreezeMode
|
|
* Description : Enter the freeze mode.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_EnterFreezeMode(FLEXCAN_Type * base)
|
|
{
|
|
uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
|
|
uint32 timeElapsed = 0U;
|
|
uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
|
|
Flexcan_Ip_StatusType returnResult = FLEXCAN_STATUS_SUCCESS;
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_02();
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_FRZ_MASK) | FLEXCAN_MCR_FRZ(1U);
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_HALT_MASK) | FLEXCAN_MCR_HALT(1U);
|
|
if (((base->MCR & FLEXCAN_MCR_MDIS_MASK) >> FLEXCAN_MCR_MDIS_SHIFT) != 0U)
|
|
{
|
|
base->MCR &= ~FLEXCAN_MCR_MDIS_MASK;
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_02();
|
|
/* Wait for entering the freeze mode */
|
|
timeStart = 0U;
|
|
while (((base->MCR & FLEXCAN_MCR_FRZACK_MASK) >> FLEXCAN_MCR_FRZACK_SHIFT) == 0U)
|
|
{
|
|
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
|
|
if (timeElapsed >= uS2Ticks)
|
|
{
|
|
returnResult = FLEXCAN_STATUS_TIMEOUT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return returnResult;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_Enable
|
|
* Description : Enable the clock for FlexCAN Module.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_Enable(FLEXCAN_Type * base)
|
|
{
|
|
uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
|
|
uint32 timeElapsed = 0U;
|
|
uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
|
|
Flexcan_Ip_StatusType returnValue = FLEXCAN_STATUS_SUCCESS;
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_03();
|
|
|
|
/* Enable Module */
|
|
base->MCR &= ~FLEXCAN_MCR_MDIS_MASK;
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_03();
|
|
/* Wait for entering the freeze mode */
|
|
timeStart = 0U;
|
|
while (((base->MCR & FLEXCAN_MCR_FRZACK_MASK) >> FLEXCAN_MCR_FRZACK_SHIFT) == 0U)
|
|
{
|
|
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
|
|
if (timeElapsed >= uS2Ticks)
|
|
{
|
|
returnValue = FLEXCAN_STATUS_TIMEOUT;
|
|
break;
|
|
}
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_ExitFreezeMode
|
|
* Description : Exit of freeze mode.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_ExitFreezeMode(FLEXCAN_Type * base)
|
|
{
|
|
uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
|
|
uint32 timeElapsed = 0U;
|
|
uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
|
|
Flexcan_Ip_StatusType returnValue = FLEXCAN_STATUS_SUCCESS;
|
|
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_04();
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_HALT_MASK) | FLEXCAN_MCR_HALT(0U);
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_FRZ_MASK) | FLEXCAN_MCR_FRZ(0U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_04();
|
|
/* Wait till exit freeze mode */
|
|
while (((base->MCR & FLEXCAN_MCR_FRZACK_MASK) >> FLEXCAN_MCR_FRZACK_SHIFT) != 0U)
|
|
{
|
|
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
|
|
if (timeElapsed >= uS2Ticks)
|
|
{
|
|
returnValue = FLEXCAN_STATUS_TIMEOUT;
|
|
break;
|
|
}
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_Disable
|
|
* Description : Disable FlexCAN module.
|
|
* This function will disable FlexCAN module.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_Disable(FLEXCAN_Type * base)
|
|
{
|
|
uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
|
|
uint32 timeElapsed = 0U;
|
|
uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
|
|
Flexcan_Ip_StatusType returnResult = FLEXCAN_STATUS_SUCCESS;
|
|
/* To access the memory mapped registers */
|
|
/* Enter disable mode (hard reset). */
|
|
if (((base->MCR & FLEXCAN_MCR_MDIS_MASK) >> FLEXCAN_MCR_MDIS_SHIFT) == 0U)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_05();
|
|
/* Clock disable (module) */
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_MDIS_MASK) | FLEXCAN_MCR_MDIS(1U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_05();
|
|
/* Wait until disable mode acknowledged */
|
|
while (((base->MCR & FLEXCAN_MCR_LPMACK_MASK) >> FLEXCAN_MCR_LPMACK_SHIFT) == 0U)
|
|
{
|
|
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
|
|
if (timeElapsed >= uS2Ticks)
|
|
{
|
|
returnResult = FLEXCAN_STATUS_TIMEOUT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return returnResult;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_SetErrIntCmd
|
|
* Description : Enable the error interrupts.
|
|
* This function will enable Error interrupt.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_SetErrIntCmd(FLEXCAN_Type * base,
|
|
flexcan_int_type_t errType,
|
|
boolean enable)
|
|
{
|
|
uint32 temp = (uint32)errType;
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_06();
|
|
if (enable)
|
|
{
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
if (errType == FLEXCAN_INT_ERR_FAST)
|
|
{
|
|
base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_ERRMSK_FAST_MASK) | FLEXCAN_CTRL2_ERRMSK_FAST(1U);
|
|
(void)temp;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if ((errType == FLEXCAN_INT_RX_WARNING) || (errType == FLEXCAN_INT_TX_WARNING))
|
|
{
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_WRNEN_MASK) | FLEXCAN_MCR_WRNEN(1U);
|
|
}
|
|
(base->CTRL1) = ((base->CTRL1) | (temp));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
if (errType == FLEXCAN_INT_ERR_FAST)
|
|
{
|
|
base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_ERRMSK_FAST_MASK) | FLEXCAN_CTRL2_ERRMSK_FAST(0U);
|
|
(void)temp;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
(base->CTRL1) = ((base->CTRL1) & ~(temp));
|
|
temp = base->CTRL1;
|
|
if (((temp & (uint32)FLEXCAN_INT_RX_WARNING) == 0U) && ((temp & (uint32)FLEXCAN_INT_TX_WARNING) == 0U))
|
|
{
|
|
/* If WRNEN disabled then both FLEXCAN_INT_RX_WARNING and FLEXCAN_INT_TX_WARNING will be disabled */
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_WRNEN_MASK) | FLEXCAN_MCR_WRNEN(0U);
|
|
}
|
|
}
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_06();
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_Init
|
|
* Description : Initialize FlexCAN module.
|
|
* This function will reset FlexCAN module, set maximum number of message
|
|
* buffers, initialize all message buffers as inactive, enable RX FIFO
|
|
* if needed, mask all mask bits, and disable all MB interrupts.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_Init(FLEXCAN_Type * base)
|
|
{
|
|
uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
|
|
uint32 timeElapsed = 0U;
|
|
uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
|
|
Flexcan_Ip_StatusType returnResult = FLEXCAN_STATUS_SUCCESS;
|
|
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_07();
|
|
/* Reset the FLEXCAN */
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_SOFTRST_MASK) | FLEXCAN_MCR_SOFTRST(1U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_07();
|
|
/* Wait for reset cycle to complete */
|
|
while (((base->MCR & FLEXCAN_MCR_SOFTRST_MASK) >> FLEXCAN_MCR_SOFTRST_SHIFT) != 0U)
|
|
{
|
|
timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
|
|
if (timeElapsed >= uS2Ticks)
|
|
{
|
|
returnResult = FLEXCAN_STATUS_TIMEOUT;
|
|
break;
|
|
}
|
|
}
|
|
if(returnResult == FLEXCAN_STATUS_SUCCESS)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_07();
|
|
/* Avoid Abort Transmission, use Inactive MB */
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_AEN_MASK) | FLEXCAN_MCR_AEN(1U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_07();
|
|
/* Clear FlexCAN memory */
|
|
FlexCAN_ClearRAM(base);
|
|
/* Rx global mask*/
|
|
(base->RXMGMASK) = (uint32)(FLEXCAN_RXMGMASK_MG_MASK);
|
|
/* Rx reg 14 mask*/
|
|
(base->RX14MASK) = (uint32)(FLEXCAN_RX14MASK_RX14M_MASK);
|
|
/* Rx reg 15 mask*/
|
|
(base->RX15MASK) = (uint32)(FLEXCAN_RX15MASK_RX15M_MASK);
|
|
/* Disable all MB interrupts */
|
|
(base->IMASK1) = 0x0;
|
|
/* Clear all MB interrupt flags */
|
|
(base->IFLAG1) = FLEXCAN_IMASK1_BUF31TO0M_MASK;
|
|
#if FEATURE_CAN_MAX_MB_NUM > 32U
|
|
if (FlexCAN_GetMaxMbNum(base) > 32U)
|
|
{
|
|
(base->IMASK2) = 0x0;
|
|
(base->IFLAG2) = FLEXCAN_IMASK2_BUF63TO32M_MASK;
|
|
}
|
|
#endif
|
|
#if FEATURE_CAN_MAX_MB_NUM > 64U
|
|
if (FlexCAN_GetMaxMbNum(base) > 64U)
|
|
{
|
|
(base->IMASK3) = 0x0;
|
|
(base->IFLAG3) = FLEXCAN_IMASK3_BUF95TO64M_MASK;
|
|
}
|
|
#endif
|
|
#if FEATURE_CAN_MAX_MB_NUM > 96U
|
|
if (FlexCAN_GetMaxMbNum(base) > 96U)
|
|
{
|
|
(base->IMASK4) = 0x0;
|
|
(base->IFLAG4) = FLEXCAN_IMASK4_BUF127TO96M_MASK;
|
|
}
|
|
#endif
|
|
/* Clear all error interrupt flags */
|
|
(base->ESR1) = FLEXCAN_ALL_INT;
|
|
/* clear registers which are not effected by soft reset */
|
|
base->CTRL1 = FLEXCAN_CTRL1_DEFAULT_VALUE_U32;
|
|
base->CTRL2 = FLEXCAN_CTRL2_DEFAULT_VALUE_U32;
|
|
base->CBT = FLEXCAN_CBT_DEFAULT_VALUE_U32;
|
|
/* TBC: add define to guard all parts relates to enhanced cbt */
|
|
base->EPRS = FLEXCAN_EPRS_DEFAULT_VALUE_U32;
|
|
base->ENCBT = FLEXCAN_ENCBT_DEFAULT_VALUE_U32;
|
|
base->EDCBT = FLEXCAN_EDCBT_DEFAULT_VALUE_U32;
|
|
base->ETDC = FLEXCAN_ETDC_DEFAULT_VALUE_U32;
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
base->FDCBT = FLEXCAN_FDCBT_DEFAULT_VALUE_U32;
|
|
base->FDCTRL = FLEXCAN_FDCTRL_DEFAULT_VALUE_U32;
|
|
#endif /* (FEATURE_CAN_HAS_FD == STD_ON) */
|
|
}
|
|
return returnResult;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_EnableRxFifo
|
|
* Description : Enable Rx FIFO feature.
|
|
* This function will enable the Rx FIFO feature.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_EnableRxFifo(FLEXCAN_Type * base,
|
|
uint32 numOfFilters)
|
|
{
|
|
uint32 i;
|
|
uint16 noOfMbx = (uint16)FlexCAN_GetMaxMbNum(base);
|
|
Flexcan_Ip_StatusType stat = FLEXCAN_STATUS_SUCCESS;
|
|
/* RxFIFO cannot be enabled if FD is enabled */
|
|
if (((base->MCR & FLEXCAN_MCR_FDEN_MASK) >> FLEXCAN_MCR_FDEN_SHIFT) != 0U)
|
|
{
|
|
stat = FLEXCAN_STATUS_ERROR;
|
|
}
|
|
if (stat == FLEXCAN_STATUS_SUCCESS)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_08();
|
|
/* Enable RX FIFO */
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_RFEN_MASK) | FLEXCAN_MCR_RFEN(1U);
|
|
/* Set the number of the RX FIFO filters needed */
|
|
base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_RFFN_MASK) | ((numOfFilters << FLEXCAN_CTRL2_RFFN_SHIFT) & FLEXCAN_CTRL2_RFFN_MASK);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_08();
|
|
/* RX FIFO global mask, take in consideration all filter fields*/
|
|
(base->RXFGMASK) = FLEXCAN_RXFGMASK_FGM_MASK;
|
|
|
|
for (i = 0U; i < noOfMbx; i++)
|
|
{
|
|
/* RX individual mask */
|
|
base->RXIMR[i] = (FLEXCAN_RXIMR_MI_MASK << CAN_ID_EXT_SHIFT) & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK);
|
|
}
|
|
}
|
|
return stat;
|
|
}
|
|
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_SetPayloadSize
|
|
* Description : Sets the payload size of the MBs.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_SetPayloadSize(FLEXCAN_Type * base,
|
|
const Flexcan_Ip_PayloadSizeType * payloadSize)
|
|
{
|
|
uint32 tmp;
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock0 == FLEXCAN_PAYLOAD_SIZE_8));
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 1U)
|
|
DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock1 == FLEXCAN_PAYLOAD_SIZE_8));
|
|
#endif
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 2U)
|
|
DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock2 == FLEXCAN_PAYLOAD_SIZE_8));
|
|
#endif
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 3U)
|
|
DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock3 == FLEXCAN_PAYLOAD_SIZE_8));
|
|
#endif
|
|
#endif
|
|
/* If FD is not enabled, only 8 bytes payload is supported */
|
|
if (FlexCAN_IsFDEnabled(base))
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_09();
|
|
tmp = base->FDCTRL;
|
|
tmp &= ~(FLEXCAN_FDCTRL_MBDSR0_MASK);
|
|
tmp |= ((uint32)payloadSize->payloadBlock0) << FLEXCAN_FDCTRL_MBDSR0_SHIFT;
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 1U)
|
|
tmp &= ~(FLEXCAN_FDCTRL_MBDSR1_MASK);
|
|
tmp |= ((uint32)payloadSize->payloadBlock1) << FLEXCAN_FDCTRL_MBDSR1_SHIFT;
|
|
#endif
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 2U)
|
|
tmp &= ~(FLEXCAN_FDCTRL_MBDSR2_MASK);
|
|
tmp |= ((uint32)payloadSize->payloadBlock2) << FLEXCAN_FDCTRL_MBDSR2_SHIFT;
|
|
#endif
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 3U)
|
|
tmp &= ~(FLEXCAN_FDCTRL_MBDSR3_MASK);
|
|
tmp |= ((uint32)payloadSize->payloadBlock3) << FLEXCAN_FDCTRL_MBDSR3_SHIFT;
|
|
#endif
|
|
base->FDCTRL = tmp;
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_09();
|
|
}
|
|
}
|
|
|
|
#endif /* End FEATURE_CAN_HAS_FD */
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_GetPayloadSize
|
|
* Description : Returns the payload size of the MBs (in bytes).
|
|
*
|
|
*END**************************************************************************/
|
|
uint8 FlexCAN_GetPayloadSize(const FLEXCAN_Type * base, uint8 mbdsrIdx)
|
|
{
|
|
uint32 payloadSize;
|
|
switch (mbdsrIdx)
|
|
{
|
|
case 0 : { payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR0_MASK) >> FLEXCAN_FDCTRL_MBDSR0_SHIFT); } break;
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 1U)
|
|
case 1 : { payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR1_MASK) >> FLEXCAN_FDCTRL_MBDSR1_SHIFT); } break;
|
|
#endif
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 2U)
|
|
case 2 : { payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR2_MASK) >> FLEXCAN_FDCTRL_MBDSR2_SHIFT); } break;
|
|
#endif
|
|
#if (FEATURE_CAN_MBDSR_COUNT > 3U)
|
|
case 3 : { payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR3_MASK) >> FLEXCAN_FDCTRL_MBDSR3_SHIFT); } break;
|
|
#endif
|
|
default :{ payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR0_MASK) >> FLEXCAN_FDCTRL_MBDSR0_SHIFT); } break;
|
|
}
|
|
|
|
return (uint8)payloadSize;
|
|
}
|
|
|
|
|
|
|
|
uint8 FlexCAN_GetMbPayloadSize(const FLEXCAN_Type * base, uint32 maxMsgBuffNum)
|
|
{
|
|
uint8 arbitration_field_size = 8U;
|
|
uint32 ramBlockSize = 512U;
|
|
uint8 can_real_payload = 8U;
|
|
uint8 maxMbBlockNum = 0U;
|
|
uint8 i=0U;
|
|
uint8 mb_size = 0U;
|
|
for(i=0; i< (uint8)FEATURE_CAN_MBDSR_COUNT; i++)
|
|
{
|
|
/* Check that the number of MBs is supported based on the payload size*/
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
can_real_payload = FlexCAN_GetPayloadSize(base, i);
|
|
#endif /* Else can_real_payload will remain as 8 payload size */
|
|
mb_size = (uint8)(can_real_payload + arbitration_field_size);
|
|
maxMbBlockNum += (uint8)(ramBlockSize / mb_size);
|
|
if (maxMbBlockNum > maxMsgBuffNum)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
#if (STD_ON == FEATURE_CAN_HAS_EXPANDABLE_MEMORY)
|
|
/* exceeded normal ram block */
|
|
if ((uint8)FEATURE_CAN_MBDSR_COUNT == i)
|
|
{
|
|
can_real_payload = 64U;
|
|
}
|
|
#endif
|
|
|
|
return can_real_payload;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_LockRxMsgBuff
|
|
* Description : Lock the RX message buffer.
|
|
* This function will lock the RX message buffer.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_LockRxMsgBuff(const FLEXCAN_Type * base,
|
|
uint32 msgBuffIdx)
|
|
{
|
|
volatile const uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
|
|
|
|
/* Lock the mailbox by reading it */
|
|
(void)*flexcan_mb;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_SetMsgBuffIntCmd
|
|
* Description : Enable/Disable the corresponding Message Buffer interrupt.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_SetMsgBuffIntCmd(FLEXCAN_Type * base,
|
|
uint8 u8Instance,
|
|
uint32 msgBuffIdx,
|
|
boolean enable,
|
|
boolean bIsIntActive)
|
|
{
|
|
uint32 temp;
|
|
Flexcan_Ip_StatusType stat = FLEXCAN_STATUS_SUCCESS;
|
|
|
|
/* Enable the corresponding message buffer Interrupt */
|
|
temp = 1UL << (msgBuffIdx % 32U);
|
|
if (msgBuffIdx < 32U)
|
|
{
|
|
if (enable)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][0U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][0U]) | (temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
base->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
else
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][0U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][0U]) & ~(temp));
|
|
base->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
}
|
|
#if FEATURE_CAN_MAX_MB_NUM > 32U
|
|
if ((msgBuffIdx >= 32U) && (msgBuffIdx < 64U))
|
|
{
|
|
if (enable)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][1U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][1U]) | (temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
base->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
else
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][1U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][1U]) & ~(temp));
|
|
base->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
}
|
|
#endif /* if FEATURE_CAN_MAX_MB_NUM > 32U */
|
|
#if FEATURE_CAN_MAX_MB_NUM > 64U
|
|
if ((msgBuffIdx >= 64U) && (msgBuffIdx < 96U))
|
|
{
|
|
if (enable)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][2U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][2U]) | (temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
base->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
else
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][2U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][2U]) & ~(temp));
|
|
base->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
}
|
|
#endif /* if FEATURE_CAN_MAX_MB_NUM > 64U */
|
|
#if FEATURE_CAN_MAX_MB_NUM > 96U
|
|
if (msgBuffIdx >= 96U)
|
|
{
|
|
if (enable)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][3U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][3U]) | (temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
base->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
else
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][3U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][3U]) & ~(temp));
|
|
base->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
}
|
|
#endif /* if FEATURE_CAN_MAX_MB_NUM > 96U */
|
|
|
|
return stat;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_ClearMsgBuffIntCmd
|
|
* Description : Disable the corresponding Message Buffer interrupt only if interrupts are active
|
|
*
|
|
*END**************************************************************************/
|
|
void FLEXCAN_ClearMsgBuffIntCmd(FLEXCAN_Type * pBase,
|
|
uint8 u8Instance,
|
|
uint32 mb_idx,
|
|
boolean bIsIntActive)
|
|
{
|
|
uint32 temp = (1UL << (mb_idx % 32U));
|
|
/* Stop the running transfer. */
|
|
if (mb_idx < 32U)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][0U] = (pBase->IMASK1 & (~temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
pBase->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
#if FEATURE_CAN_MAX_MB_NUM > 32U
|
|
if ((mb_idx >= 32U) && (mb_idx < 64U))
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][1U] = (pBase->IMASK2 & (~temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
pBase->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
#endif
|
|
#if FEATURE_CAN_MAX_MB_NUM > 64U
|
|
if ((mb_idx >= 64U) && (mb_idx < 96U))
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][2U] = (pBase->IMASK3 & (~temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
pBase->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
#endif /* FEATURE_CAN_MAX_MB_NUM > 64U */
|
|
#if FEATURE_CAN_MAX_MB_NUM > 96U
|
|
if (mb_idx >= 96U)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
|
|
g_FlexCAN_u32ImaskBuff[u8Instance][3U] = (pBase->IMASK4 & (~temp));
|
|
if (bIsIntActive == TRUE)
|
|
{
|
|
pBase->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
|
|
}
|
|
#endif /* #if FEATURE_CAN_MAX_MB_NUM > 96U */
|
|
}
|
|
|
|
|
|
void FlexCAN_DisableInterrupts(FLEXCAN_Type * pBase)
|
|
{
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
|
|
uint32 u32MaxMbCrtlNum = FlexCAN_GetMaxMbNum(pBase);
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */
|
|
|
|
pBase->IMASK1 = 0U;
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
|
|
if (u32MaxMbCrtlNum > 32U)
|
|
{
|
|
pBase->IMASK2 = 0U;
|
|
}
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 64U)
|
|
if (u32MaxMbCrtlNum > 64U)
|
|
{
|
|
pBase->IMASK3 = 0U;
|
|
}
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 64U) */
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 96U)
|
|
if (u32MaxMbCrtlNum > 96U)
|
|
{
|
|
pBase->IMASK4 = 0U;
|
|
}
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 96U) */
|
|
}
|
|
|
|
void FlexCAN_EnableInterrupts(FLEXCAN_Type * pBase, uint8 u8Instance)
|
|
{
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
|
|
uint32 u32MaxMbCrtlNum = FlexCAN_GetMaxMbNum(pBase);
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */
|
|
|
|
pBase->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
|
|
if (u32MaxMbCrtlNum > 32U)
|
|
{
|
|
pBase->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
|
|
}
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 64U)
|
|
if (u32MaxMbCrtlNum > 64U)
|
|
{
|
|
pBase->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
|
|
}
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 64U) */
|
|
#if (FEATURE_CAN_MAX_MB_NUM > 96U)
|
|
if (u32MaxMbCrtlNum > 96U)
|
|
{
|
|
pBase->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
|
|
}
|
|
#endif /* (FEATURE_CAN_MAX_MB_NUM > 96U) */
|
|
}
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_SetRxMsgBuff
|
|
* Description : Configure a message buffer for receiving.
|
|
* This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
|
|
* the function will make sure if the MB requested is not occupied by RX FIFO
|
|
* and ID filter table. Then this function will configure the message buffer as
|
|
* required for receiving.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_SetRxMsgBuff(const FLEXCAN_Type * base,
|
|
uint32 msgBuffIdx,
|
|
const Flexcan_Ip_MsbuffCodeStatusType * cs,
|
|
uint32 msgId)
|
|
{
|
|
volatile uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
|
|
volatile uint32 * flexcan_mb_id = &flexcan_mb[1];
|
|
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert(cs != NULL_PTR);
|
|
#endif
|
|
|
|
|
|
/* Clean up the arbitration field area */
|
|
*flexcan_mb = 0;
|
|
*flexcan_mb_id = 0;
|
|
|
|
/* Set the ID according the format structure */
|
|
if (cs->msgIdType == FLEXCAN_MSG_ID_EXT)
|
|
{
|
|
/* Set IDE */
|
|
*flexcan_mb |= CAN_CS_IDE_MASK;
|
|
|
|
/* Clear SRR bit */
|
|
*flexcan_mb &= ~CAN_CS_SRR_MASK;
|
|
|
|
/* ID [28-0] */
|
|
*flexcan_mb_id &= ~(CAN_ID_STD_MASK | CAN_ID_EXT_MASK);
|
|
*flexcan_mb_id |= (msgId & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK));
|
|
}
|
|
|
|
if (cs->msgIdType == FLEXCAN_MSG_ID_STD)
|
|
{
|
|
/* Make sure IDE and SRR are not set */
|
|
*flexcan_mb &= ~(CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);
|
|
|
|
/* ID[28-18] */
|
|
*flexcan_mb_id &= ~CAN_ID_STD_MASK;
|
|
*flexcan_mb_id |= (msgId << CAN_ID_STD_SHIFT) & CAN_ID_STD_MASK;
|
|
}
|
|
|
|
/* Set MB CODE */
|
|
if (cs->code != (uint32)FLEXCAN_RX_NOT_USED)
|
|
{
|
|
*flexcan_mb &= ~CAN_CS_CODE_MASK;
|
|
*flexcan_mb |= (cs->code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK;
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_GetMsgBuffTimestamp
|
|
* Description : Get a message buffer timestamp value.
|
|
*
|
|
*END**************************************************************************/
|
|
uint32 FlexCAN_GetMsgBuffTimestamp(const FLEXCAN_Type * base, uint32 msgBuffIdx)
|
|
{
|
|
uint32 timestamp = 0U;
|
|
volatile const uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
|
|
|
|
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
|
|
if (FLEXCAN_IsHRTimeStampEnabled(base))
|
|
{
|
|
/* Extract the Time Stamp */
|
|
timestamp = (uint32)base->HR_TIME_STAMP[msgBuffIdx];
|
|
}
|
|
else
|
|
#endif /* EATURE_CAN_HAS_HR_TIMER */
|
|
{
|
|
timestamp = (uint32)((*flexcan_mb & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
|
|
}
|
|
return timestamp;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_GetMsgBuff
|
|
* Description : Get a message buffer field values.
|
|
* This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
|
|
* the function will make sure if the MB requested is not occupied by RX FIFO
|
|
* and ID filter table. Then this function will get the message buffer field
|
|
* values and copy the MB data field into user's buffer.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_GetMsgBuff(const FLEXCAN_Type * base,
|
|
uint32 msgBuffIdx,
|
|
Flexcan_Ip_MsgBuffType * msgBuff)
|
|
{
|
|
|
|
uint8 i;
|
|
volatile const uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
|
|
volatile const uint32 * flexcan_mb_id = &flexcan_mb[1];
|
|
volatile const uint8 * flexcan_mb_data = (volatile const uint8 *)(&flexcan_mb[2]);
|
|
volatile const uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
|
|
uint32 * msgBuff_data_32 = (uint32 *)(msgBuff->data);
|
|
uint32 mbWord;
|
|
|
|
uint8 flexcan_mb_dlc_value = (uint8)(((*flexcan_mb) & CAN_CS_DLC_MASK) >> 16);
|
|
uint8 payload_size = FlexCAN_ComputePayloadSize(flexcan_mb_dlc_value);
|
|
|
|
|
|
DevAssert(msgBuff != NULL_PTR);
|
|
|
|
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
/* Payload Size is based on MBDSR for 1 MBDSR corresponds 32 * 8Bytes MBs */
|
|
if (payload_size > FlexCAN_GetMbPayloadSize(base, msgBuffIdx))
|
|
{
|
|
payload_size = FlexCAN_GetMbPayloadSize(base, msgBuffIdx);
|
|
}
|
|
#endif /* FEATURE_CAN_HAS_FD */
|
|
|
|
msgBuff->dataLen = payload_size;
|
|
/* Get a MB field values */
|
|
msgBuff->cs = *flexcan_mb;
|
|
if ((msgBuff->cs & CAN_CS_IDE_MASK) != 0U)
|
|
{
|
|
msgBuff->msgId = (*flexcan_mb_id);
|
|
}
|
|
else
|
|
{
|
|
msgBuff->msgId = (*flexcan_mb_id) >> CAN_ID_STD_SHIFT;
|
|
}
|
|
|
|
|
|
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
|
|
if (FLEXCAN_IsHRTimeStampEnabled(base))
|
|
{
|
|
/* Extract the Time Stamp */
|
|
msgBuff->time_stamp = (uint32)base->HR_TIME_STAMP[msgBuffIdx];
|
|
}
|
|
else
|
|
#endif /* EATURE_CAN_HAS_HR_TIMER */
|
|
{
|
|
msgBuff->time_stamp = (uint32)((msgBuff->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
|
|
}
|
|
|
|
#if (defined (CPU_S32K116) || defined (CPU_S32K118))
|
|
/* Check if the buffer address is aligned */
|
|
if (((uint32)msgBuff_data_32 & 0x3U) != 0U)
|
|
{
|
|
/* Copy MB data field into user's buffer */
|
|
for (i = 0U; i < (payload_size & ~3U); i += 4U)
|
|
{
|
|
mbWord = flexcan_mb_data_32[i >> 2U];
|
|
uint8 index;
|
|
uint32 x;
|
|
const uint8 * p;
|
|
FlexcanSwapBytesInWord(mbWord, x);
|
|
p = (uint8 *)&x;
|
|
for (index = 0; index < 4U; index++)
|
|
{
|
|
msgBuff->data[i + index] = p[index];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0U; i < (payload_size & ~3U); i += 4U)
|
|
{
|
|
mbWord = flexcan_mb_data_32[i >> 2U];
|
|
FlexcanSwapBytesInWord(mbWord, msgBuff_data_32[i >> 2U]);
|
|
}
|
|
}
|
|
|
|
#else /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
|
|
for (i = 0U; i < (payload_size & ~3U); i += 4U)
|
|
{
|
|
mbWord = flexcan_mb_data_32[i >> 2U];
|
|
FlexcanSwapBytesInWord((mbWord), (msgBuff_data_32[i >> 2U]));
|
|
}
|
|
|
|
#endif /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
|
|
for ( ; i < payload_size; i++)
|
|
{ /* Max allowed value for index is 63 */
|
|
msgBuff->data[i] = flexcan_mb_data[FlexcanSwapBytesInWordIndex(i)];
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_SetTxMsgBuff
|
|
* Description : Configure a message buffer for transmission.
|
|
* This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
|
|
* the function will make sure if the MB requested is not occupied by RX FIFO
|
|
* and ID filter table. Then this function will copy user's buffer into the
|
|
* message buffer data area and configure the message buffer as required for
|
|
* transmission.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_SetTxMsgBuff(const FLEXCAN_Type * base,
|
|
uint32 msgBuffIdx,
|
|
const Flexcan_Ip_MsbuffCodeStatusType * cs,
|
|
uint32 msgId,
|
|
const uint8 * msgData,
|
|
const boolean isRemote)
|
|
{
|
|
uint32 flexcan_mb_config = 0;
|
|
uint32 databyte;
|
|
uint8 dlc_value;
|
|
uint8 payload_size;
|
|
volatile uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
|
|
volatile uint32 * flexcan_mb_id = &flexcan_mb[1];
|
|
volatile uint8 * flexcan_mb_data = (volatile uint8*)(&flexcan_mb[2]);
|
|
volatile uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
|
|
const uint32 * msgData_32 = (const uint32*)msgData;
|
|
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert(cs != NULL_PTR);
|
|
#endif
|
|
|
|
/* Clean up the arbitration field area and set TxMB Inactive */
|
|
*flexcan_mb = (uint32)((((uint32)FLEXCAN_TX_INACTIVE & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK);
|
|
*flexcan_mb_id = 0;
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
/* Check if the Payload Size is smaller than the payload configured */
|
|
DevAssert((uint8)cs->dataLen <= FlexCAN_GetMbPayloadSize(base, msgBuffIdx));
|
|
#endif
|
|
#else
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert((uint8)cs->dataLen <= 8U);
|
|
#endif
|
|
#endif
|
|
/* Compute the value of the DLC field */
|
|
dlc_value = FlexCAN_ComputeDLCValue((uint8)cs->dataLen);
|
|
/* Copy user's buffer into the message buffer data area */
|
|
if (msgData != NULL_PTR)
|
|
{
|
|
for (databyte = 0; databyte < (cs->dataLen & ~3U); databyte += 4U)
|
|
{
|
|
FlexcanSwapBytesInWord((msgData_32[databyte >> 2U]), (flexcan_mb_data_32[databyte >> 2U]));
|
|
}
|
|
for ( ; databyte < cs->dataLen; databyte++)
|
|
{
|
|
flexcan_mb_data[FlexcanSwapBytesInWordIndex(databyte)] = msgData[databyte];
|
|
}
|
|
#if (FEATURE_CAN_HAS_FD == STD_ON)
|
|
payload_size = FlexCAN_ComputePayloadSize(dlc_value);
|
|
/* Add padding, if needed */
|
|
for (databyte = cs->dataLen; databyte < payload_size; databyte++)
|
|
{
|
|
flexcan_mb_data[FlexcanSwapBytesInWordIndex(databyte)] = cs->fd_padding;
|
|
}
|
|
#endif /* FEATURE_CAN_HAS_FD */
|
|
}
|
|
/* Set the ID according the format structure */
|
|
if (cs->msgIdType == FLEXCAN_MSG_ID_EXT)
|
|
{
|
|
/* ID [28-0] */
|
|
*flexcan_mb_id &= ~(CAN_ID_STD_MASK | CAN_ID_EXT_MASK);
|
|
*flexcan_mb_id |= (msgId & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK));
|
|
/* Set IDE and SRR bit*/
|
|
flexcan_mb_config |= (CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);
|
|
}
|
|
if (cs->msgIdType == FLEXCAN_MSG_ID_STD)
|
|
{
|
|
/* ID[28-18] */
|
|
*flexcan_mb_id &= ~CAN_ID_STD_MASK;
|
|
*flexcan_mb_id |= (msgId << CAN_ID_STD_SHIFT) & CAN_ID_STD_MASK;
|
|
/* make sure IDE and SRR are not set */
|
|
flexcan_mb_config &= ~(CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);
|
|
}
|
|
/* Set the length of data in bytes */
|
|
flexcan_mb_config &= ~CAN_CS_DLC_MASK;
|
|
flexcan_mb_config |= ((uint32)dlc_value << CAN_CS_DLC_SHIFT) & CAN_CS_DLC_MASK;
|
|
/* Set MB CODE */
|
|
if (cs->code != (uint32)FLEXCAN_TX_NOT_USED)
|
|
{
|
|
if (cs->code == (uint32)FLEXCAN_TX_REMOTE)
|
|
{
|
|
/* Set RTR bit */
|
|
flexcan_mb_config |= CAN_CS_RTR_MASK;
|
|
}
|
|
else
|
|
{
|
|
if (isRemote == TRUE)
|
|
{
|
|
/* Set RTR bit */
|
|
flexcan_mb_config |= CAN_CS_RTR_MASK;
|
|
}
|
|
}
|
|
/* Reset the code */
|
|
flexcan_mb_config &= ~CAN_CS_CODE_MASK;
|
|
/* Set the code */
|
|
if (cs->fd_enable)
|
|
{
|
|
flexcan_mb_config |= ((cs->code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK) | CAN_MB_EDL_MASK;
|
|
/* In case of FD frame not supported RTR */
|
|
flexcan_mb_config &= ~CAN_CS_RTR_MASK;
|
|
}
|
|
else
|
|
{
|
|
flexcan_mb_config |= (cs->code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK;
|
|
}
|
|
|
|
if (cs->enable_brs)
|
|
{
|
|
flexcan_mb_config |= CAN_MB_BRS_MASK;
|
|
}
|
|
*flexcan_mb |= flexcan_mb_config;
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_SetMaxMsgBuffNum
|
|
* Description : Set the number of the last Message Buffers.
|
|
* This function will define the number of the last Message Buffers
|
|
*
|
|
*END***************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_SetMaxMsgBuffNum(
|
|
FLEXCAN_Type * base,
|
|
uint32 maxMsgBuffNum)
|
|
{
|
|
uint8 msgBuffIdx;
|
|
uint32 databyte;
|
|
const volatile uint32 * RAM = (uint32*)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
|
|
#if (STD_ON == FEATURE_CAN_HAS_EXPANDABLE_MEMORY)
|
|
const volatile uint32 * RAM_EXPANDED = (uint32*)((uint32)base + (uint32)FEATURE_CAN_EXP_RAM_OFFSET);
|
|
#endif /* FEATURE_CAN_HAS_EXPANDABLE_MEMORY */
|
|
const volatile uint32 * valEndMbPointer = NULL_PTR;
|
|
volatile uint32 *flexcan_mb = NULL_PTR;
|
|
volatile uint32 *flexcan_mb_id = NULL_PTR ;
|
|
volatile uint8 *flexcan_mb_data = NULL_PTR;
|
|
uint8 arbitration_field_size = 8U;
|
|
uint8 can_real_payload = FlexCAN_GetMbPayloadSize(base, maxMsgBuffNum - (uint32)1U);
|
|
uint32 valEndMb = 0U;
|
|
uint32 valEndRam = 0U;
|
|
Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert(maxMsgBuffNum>0U);
|
|
#endif
|
|
|
|
valEndMbPointer = FlexCAN_GetMsgBuffRegion(base, (maxMsgBuffNum - (uint32)1U));
|
|
|
|
valEndMb = (uint32)valEndMbPointer + can_real_payload + arbitration_field_size;
|
|
|
|
#if (STD_ON == FEATURE_CAN_HAS_EXPANDABLE_MEMORY)
|
|
if (FlexCAN_IsExpandableMemoryAvailable(base))
|
|
{
|
|
valEndRam = (uint32)&RAM_EXPANDED[CAN_RAM1n_COUNT];
|
|
}
|
|
else
|
|
{
|
|
valEndRam = (uint32)&RAM[CAN_RAMn_COUNT];
|
|
}
|
|
#else
|
|
valEndRam = (uint32)&RAM[CAN_RAMn_COUNT];
|
|
#endif /* FEATURE_CAN_HAS_EXPANDABLE_MEMORY */
|
|
|
|
if ((valEndMb > valEndRam) || (maxMsgBuffNum > FlexCAN_GetMaxMbNum(base)))
|
|
{
|
|
status = FLEXCAN_STATUS_BUFF_OUT_OF_RANGE;
|
|
}
|
|
|
|
|
|
if (status == FLEXCAN_STATUS_SUCCESS)
|
|
{
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_11();
|
|
/* Set the maximum number of MBs*/
|
|
base->MCR = (base->MCR & ~FLEXCAN_MCR_MAXMB_MASK) | (((maxMsgBuffNum-1U) << FLEXCAN_MCR_MAXMB_SHIFT) & FLEXCAN_MCR_MAXMB_MASK);
|
|
if (!(((base->MCR & FLEXCAN_MCR_RFEN_MASK) >> FLEXCAN_MCR_RFEN_SHIFT) != 0U))
|
|
{
|
|
/* Initialize all message buffers as inactive */
|
|
for (msgBuffIdx = 0; msgBuffIdx < maxMsgBuffNum; msgBuffIdx++)
|
|
{
|
|
flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
|
|
flexcan_mb_id = &flexcan_mb[1];
|
|
flexcan_mb_data = (volatile uint8*)(&flexcan_mb[2]);
|
|
*flexcan_mb = 0x0U;
|
|
*flexcan_mb_id = 0x0U;
|
|
can_real_payload = FlexCAN_GetMbPayloadSize(base, msgBuffIdx);
|
|
for (databyte = 0; databyte < can_real_payload; databyte++)
|
|
{
|
|
flexcan_mb_data[databyte] = 0x0U;
|
|
}
|
|
}
|
|
}
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_11();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_SetOperationMode
|
|
* Description : Enable a FlexCAN operation mode.
|
|
* This function will enable one of the modes listed in flexcan_operation_modes_t.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_SetOperationMode(FLEXCAN_Type * base,
|
|
Flexcan_Ip_ModesType mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case FLEXCAN_NORMAL_MODE:
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_12();
|
|
base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LOM_MASK) | FLEXCAN_CTRL1_LOM(0U);
|
|
base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LPB_MASK) | FLEXCAN_CTRL1_LPB(0U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_12();
|
|
break;
|
|
case FLEXCAN_LISTEN_ONLY_MODE:
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_12();
|
|
base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LOM_MASK) | FLEXCAN_CTRL1_LOM(1U);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_12();
|
|
break;
|
|
case FLEXCAN_LOOPBACK_MODE:
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_12();
|
|
base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LPB_MASK) | FLEXCAN_CTRL1_LPB(1U);
|
|
base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LOM_MASK) | FLEXCAN_CTRL1_LOM(0U);
|
|
/* Enable Self Reception */
|
|
FlexCAN_SetSelfReception(base, TRUE);
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_12();
|
|
break;
|
|
default:
|
|
/* Should not get here */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_SetRxFifoFilter
|
|
* Description : Configure RX FIFO ID filter table elements.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_SetRxFifoFilter(FLEXCAN_Type * base,
|
|
Flexcan_Ip_RxFifoIdElementFormatType idFormat,
|
|
const Flexcan_Ip_IdTableType * idFilterTable)
|
|
{
|
|
|
|
/* Set RX FIFO ID filter table elements*/
|
|
uint32 i, j, numOfFilters;
|
|
uint32 val1 = 0UL, val2 = 0UL, val = 0UL;
|
|
volatile uint32 * filterTable = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET + ((uint32)RxFifoFilterTableOffset * 4U));
|
|
|
|
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert((idFilterTable != NULL_PTR) || (FLEXCAN_RX_FIFO_ID_FORMAT_D == idFormat));
|
|
#endif
|
|
|
|
numOfFilters = (((base->CTRL2) & FLEXCAN_CTRL2_RFFN_MASK) >> FLEXCAN_CTRL2_RFFN_SHIFT);
|
|
switch (idFormat)
|
|
{
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_A):
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
|
|
/* One full ID (standard and extended) per ID Filter Table element.*/
|
|
(base->MCR) =
|
|
(((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
|
|
((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_A)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
|
|
for (i = 0U; i < RXFIFO_FILTER_ELEM_NUM(numOfFilters); i++)
|
|
{
|
|
val = 0UL;
|
|
|
|
if (idFilterTable[i].isRemoteFrame)
|
|
{
|
|
val = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT;
|
|
}
|
|
|
|
if (idFilterTable[i].isExtendedFrame)
|
|
{
|
|
val |= FlexCanRxFifoAcceptExtFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT;
|
|
filterTable[i] = val + ((idFilterTable[i].id <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_SHIFT) &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_MASK);
|
|
}
|
|
else
|
|
{
|
|
filterTable[i] = val + ((idFilterTable[i].id <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_SHIFT) &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_MASK);
|
|
}
|
|
}
|
|
break;
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_B):
|
|
/* Two full standard IDs or two partial 14-bit (standard and extended) IDs*/
|
|
/* per ID Filter Table element.*/
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
|
|
(base->MCR) =
|
|
(((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
|
|
((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_B)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
|
|
j = 0U;
|
|
for (i = 0U; i < RXFIFO_FILTER_ELEM_NUM(numOfFilters); i++)
|
|
{
|
|
val1 = 0U;
|
|
val2 = 0U;
|
|
|
|
if (idFilterTable[j].isRemoteFrame)
|
|
{
|
|
val1 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT;
|
|
}
|
|
|
|
if (idFilterTable[j + 1U].isRemoteFrame)
|
|
{
|
|
val2 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_RTR_SHIFT;
|
|
}
|
|
|
|
if (idFilterTable[j].isExtendedFrame)
|
|
{
|
|
val1 |= FlexCanRxFifoAcceptExtFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT;
|
|
|
|
filterTable[i] = val1 + (((idFilterTable[j].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT1);
|
|
}
|
|
else
|
|
{
|
|
filterTable[i] = val1 + ((idFilterTable[j].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT1);
|
|
}
|
|
|
|
if (idFilterTable[j + 1U].isExtendedFrame)
|
|
{
|
|
val2 |= FlexCanRxFifoAcceptExtFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_IDE_SHIFT;
|
|
|
|
filterTable[i] |= val2 + (((idFilterTable[j + 1U].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT2);
|
|
}
|
|
else
|
|
{
|
|
filterTable[i] |= val2 + ((idFilterTable[j + 1U].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT2);
|
|
}
|
|
|
|
j = j + 2U;
|
|
}
|
|
break;
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_C):
|
|
/* Four partial 8-bit Standard IDs per ID Filter Table element.*/
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
|
|
(base->MCR) =
|
|
(((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
|
|
((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_C)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
|
|
j = 0U;
|
|
for (i = 0U; i < RXFIFO_FILTER_ELEM_NUM(numOfFilters); i++)
|
|
{
|
|
if (idFilterTable[j].isExtendedFrame)
|
|
{
|
|
filterTable[i] = val1 + (((idFilterTable[j].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1);
|
|
}
|
|
else
|
|
{
|
|
filterTable[i] = val1 + (((idFilterTable[j].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1);
|
|
}
|
|
|
|
if (idFilterTable[j + 1U].isExtendedFrame)
|
|
{
|
|
filterTable[i] |= val1 + (((idFilterTable[j + 1U].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT2);
|
|
}
|
|
else
|
|
{
|
|
filterTable[i] |= val1 + (((idFilterTable[j + 1U].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT2);
|
|
}
|
|
|
|
if (idFilterTable[j + 2U].isExtendedFrame)
|
|
{
|
|
filterTable[i] |= val1 + (((idFilterTable[j + 2U].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT3);
|
|
}
|
|
else
|
|
{
|
|
filterTable[i] |= val1 + (((idFilterTable[j + 2U].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT3);
|
|
}
|
|
|
|
if (idFilterTable[j + 3U].isExtendedFrame)
|
|
{
|
|
filterTable[i] |= val1 + (((idFilterTable[j + 3U].id &
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT4);
|
|
}
|
|
else
|
|
{
|
|
filterTable[i] |= val1 +
|
|
(((idFilterTable[j + 3U].id & FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
|
|
FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT4);
|
|
}
|
|
|
|
j = j + 4U;
|
|
}
|
|
break;
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_D):
|
|
/* All frames rejected.*/
|
|
/* Start critical section: implementation depends on integrator */
|
|
SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
|
|
(base->MCR) =
|
|
(((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
|
|
((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_D)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
|
|
/* End critical section: implementation depends on integrator */
|
|
SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
|
|
break;
|
|
default:
|
|
/* Should not get here */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_ReadRxFifo
|
|
* Description : Read Rx FIFO data.
|
|
* This function will copy MB[0] data field into user's buffer.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_ReadRxFifo(const FLEXCAN_Type * base,
|
|
Flexcan_Ip_MsgBuffType * rxFifo)
|
|
{
|
|
|
|
uint32 databyte;
|
|
uint32 mbWord;
|
|
#if (defined (CPU_S32K116) || defined (CPU_S32K118))
|
|
uint32 x;
|
|
uint8 index;
|
|
const uint8 * p;
|
|
#endif
|
|
|
|
volatile const uint32 * flexcan_mb = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
|
|
volatile const uint32 * flexcan_mb_id = &flexcan_mb[1];
|
|
volatile const uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
|
|
uint32 * msgData_32 = (uint32 *)(rxFifo->data);
|
|
uint8 flexcan_mb_dlc_value = (uint8)(((*flexcan_mb) & CAN_CS_DLC_MASK) >> 16);
|
|
uint8 can_real_payload = FlexCAN_ComputePayloadSize(flexcan_mb_dlc_value);
|
|
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert(rxFifo != NULL_PTR);
|
|
#endif
|
|
/*
|
|
Check if the length of received data packet bigger than the maximum length accepted,
|
|
then processing flow shall continue with the maximum length defined by configuration.
|
|
Legacy FIFO just support in normal mode.
|
|
*/
|
|
/* no need to check if FD enabled or not because this function just is invoked when legacy fifo enabled only ! */
|
|
if(can_real_payload > 8U)
|
|
{
|
|
can_real_payload = 8U;
|
|
}
|
|
|
|
rxFifo->dataLen = can_real_payload;
|
|
rxFifo->cs = *flexcan_mb;
|
|
if ((rxFifo->cs & CAN_CS_IDE_MASK) != 0U)
|
|
{
|
|
rxFifo->msgId = *flexcan_mb_id;
|
|
}
|
|
else
|
|
{
|
|
rxFifo->msgId = (*flexcan_mb_id) >> CAN_ID_STD_SHIFT;
|
|
}
|
|
/* Extract the IDHIT */
|
|
rxFifo->id_hit = (uint8)base->RXFIR;
|
|
/* Extract the Time Stamp */
|
|
rxFifo->time_stamp = (uint32)((rxFifo->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
|
|
#if (defined (CPU_S32K116) || defined (CPU_S32K118))
|
|
/* Check if the buffer address is aligned */
|
|
if (((uint32)msgData_32 & 0x3U) != 0U)
|
|
{
|
|
/* Copy MB[0] data field into user's buffer */
|
|
for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
|
|
{
|
|
|
|
mbWord = flexcan_mb_data_32[databyte >> 2U];
|
|
|
|
FlexcanSwapBytesInWord(mbWord, x);
|
|
p = (uint8 *)&x;
|
|
for (index = 0U; index < 4U; index++)
|
|
{
|
|
rxFifo->data[databyte + index] = p[index];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Copy MB[0] data field into user's buffer */
|
|
for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
|
|
{
|
|
mbWord = flexcan_mb_data_32[databyte >> 2U];
|
|
FlexcanSwapBytesInWord(mbWord, msgData_32[databyte >> 2U]);
|
|
}
|
|
}
|
|
#else /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
|
|
/* Copy MB[0] data field into user's buffer */
|
|
for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
|
|
{
|
|
mbWord = flexcan_mb_data_32[databyte >> 2U];
|
|
FlexcanSwapBytesInWord((mbWord), (msgData_32[databyte >> 2U]));
|
|
}
|
|
#endif /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
|
|
}
|
|
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_ReadEnhancedRxFifo
|
|
* Description : Read Enhanced Rx FIFO data.
|
|
* This function will copy Enhanced Rx FIFO data output into user's buffer.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_ReadEnhancedRxFifo(const FLEXCAN_Type * base,
|
|
Flexcan_Ip_MsgBuffType * rxFifo)
|
|
{
|
|
uint32 databyte;
|
|
uint32 mbWord;
|
|
uint8 idhit_offset;
|
|
volatile const uint32 * flexcan_mb = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_ENHANCED_FIFO_RAM_OFFSET);
|
|
volatile const uint32 * flexcan_mb_id = &flexcan_mb[1];
|
|
volatile const uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
|
|
uint32 * msgData_32 = NULL_PTR;
|
|
|
|
/* Check if the buffer address is aligned */
|
|
|
|
/* Compute payload size */
|
|
uint8 flexcan_mb_dlc_value = (uint8)(((*flexcan_mb) & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
|
|
uint8 can_real_payload = FlexCAN_ComputePayloadSize(flexcan_mb_dlc_value);
|
|
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert(rxFifo != NULL_PTR);
|
|
#endif
|
|
|
|
msgData_32 = (uint32 *)(rxFifo->data);
|
|
rxFifo->dataLen = can_real_payload;
|
|
rxFifo->cs = *flexcan_mb;
|
|
|
|
if ((rxFifo->cs & CAN_CS_IDE_MASK) != 0U)
|
|
{
|
|
rxFifo->msgId = *flexcan_mb_id;
|
|
}
|
|
else
|
|
{
|
|
rxFifo->msgId = (*flexcan_mb_id) >> CAN_ID_STD_SHIFT;
|
|
}
|
|
|
|
if ((rxFifo->cs & CAN_CS_RTR_MASK) != 0U)
|
|
{
|
|
can_real_payload = 0U;
|
|
}
|
|
|
|
idhit_offset = (can_real_payload >> 2U) + (((can_real_payload % 4U) != 0U) ? 1U : 0U);
|
|
|
|
/* Extract the IDHIT */
|
|
rxFifo->id_hit = (uint8)(((flexcan_mb_data_32[idhit_offset]) & CAN_ENHANCED_IDHIT_MASK) >> CAN_ENHANCED_IDHIT_SHIFT);
|
|
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
|
|
/* Extract the Time Stamp */
|
|
if (FLEXCAN_IsHRTimeStampEnabled(base))
|
|
{
|
|
rxFifo->time_stamp = (uint32)(flexcan_mb_data_32[idhit_offset + 1U]);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
rxFifo->time_stamp = (uint32)((rxFifo->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
|
|
}
|
|
|
|
/* Copy EnhancedRxFIFO data field into user's buffer */
|
|
for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
|
|
{
|
|
mbWord = flexcan_mb_data_32[databyte >> 2U];
|
|
FlexcanSwapBytesInWord((mbWord), (msgData_32[databyte >> 2U]));
|
|
}
|
|
}
|
|
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */
|
|
|
|
#if (FEATURE_CAN_BUSOFF_ERROR_INTERRUPT_UNIFIED == STD_OFF)
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_ClearErrIntStatusFlag
|
|
* Description : Clear all error interrupt status.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_ClearErrIntStatusFlag(FLEXCAN_Type * base)
|
|
{
|
|
if ((base->ESR1 & FLEXCAN_ALL_INT) != 0U)
|
|
{
|
|
(base->ESR1) = ERROR_INT;
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_ClearBusOffIntStatusFlag
|
|
* Description : Clear all busOff and Tx/Rx Warning interrupt status.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_ClearBusOffIntStatusFlag(FLEXCAN_Type * base)
|
|
{
|
|
if ((base->ESR1 & BUS_OFF_INT) != 0U)
|
|
{
|
|
base->ESR1 = BUS_OFF_INT;
|
|
}
|
|
}
|
|
#endif /* (FEATURE_CAN_BUSOFF_ERROR_INTERRUPT_UNIFIED == STD_OFF) */
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_GetErrStatusFlag.
|
|
* Description : Get error interrupt status.
|
|
*
|
|
*END**************************************************************************/
|
|
boolean FlexCAN_GetErrStatusFlag(uint8 u8Instance)
|
|
{
|
|
static FLEXCAN_Type * const flexcanBase[] = FLEXCAN_BASE_PTRS;
|
|
boolean bErrStatus = (boolean)FALSE;
|
|
|
|
if (((flexcanBase[u8Instance])->ESR1 & FLEXCAN_ESR1_ERRINT_MASK) != 0U)
|
|
{
|
|
bErrStatus = (boolean)TRUE;
|
|
}
|
|
return bErrStatus;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_GetBusOffStatusFlag.
|
|
* Description : Get busOff interrupt status.
|
|
*
|
|
*END**************************************************************************/
|
|
boolean FlexCAN_GetBusOffStatusFlag(uint8 u8Instance)
|
|
{
|
|
static FLEXCAN_Type * const flexcanBase[] = FLEXCAN_BASE_PTRS;
|
|
boolean bBOffStatus = (boolean)FALSE;
|
|
|
|
if ((flexcanBase[u8Instance]->ESR1 & FLEXCAN_ESR1_BOFFINT_MASK) != 0U)
|
|
{
|
|
bBOffStatus = (boolean)TRUE;
|
|
}
|
|
return bBOffStatus;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_AbortTxMsgBuff
|
|
* Description : Writes the abort code into the CODE field of the requested
|
|
* Tx message buffer.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_AbortTxMsgBuff(const FLEXCAN_Type * base,
|
|
uint32 msgBuffIdx)
|
|
{
|
|
uint32 flexcan_mb_config = 0;
|
|
uint32 code = FLEXCAN_TX_ABORT;
|
|
|
|
volatile uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
|
|
flexcan_mb_config = *flexcan_mb;
|
|
|
|
/* Reset the code */
|
|
flexcan_mb_config &= (~CAN_CS_CODE_MASK);
|
|
|
|
flexcan_mb_config |= (code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK;
|
|
|
|
*flexcan_mb = flexcan_mb_config;
|
|
}
|
|
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_GetRxFifoMask
|
|
* Description : Calculate the Global Mask as format ID type in FIFO Mode.
|
|
* Based on the ID format type and Mask Type will calculate the and set accordingly
|
|
* the Rx FIFO Individual\Global Mask register.
|
|
*
|
|
*END**************************************************************************/
|
|
uint32 FlexCAN_GetRxFifoMask(Flexcan_Ip_MsgBuffIdType id_type,
|
|
Flexcan_Ip_RxFifoIdElementFormatType formatType,
|
|
uint32 mask)
|
|
{
|
|
uint32 val = 0;
|
|
|
|
switch (formatType)
|
|
{
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_A):
|
|
/* Set RTR bit encoded as bit 31 and IDE bit encoded as bit 30 in mask */
|
|
val = mask & ((1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT) | (1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT));
|
|
if (id_type == FLEXCAN_MSG_ID_STD)
|
|
{
|
|
/* Set standard global mask for RX FIFO and IDE will be 1 and check the FIFO filter ide */
|
|
val |= ((mask << FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_SHIFT) & FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_MASK);
|
|
}
|
|
else if (id_type == FLEXCAN_MSG_ID_EXT)
|
|
{
|
|
/* Set extended global mask for RX FIFO and IDE will be 0 and don't check the FIFO filter ide */
|
|
val |= ((mask << FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_SHIFT) & FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_MASK);
|
|
}
|
|
else
|
|
{
|
|
/* Should not get here */
|
|
}
|
|
|
|
break;
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_B):
|
|
/* Set RTR bit encoded as bit 31 and IDE bit encoded as bit 30 in mask */
|
|
val = mask & ((1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT) | (1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT));
|
|
if (id_type == FLEXCAN_MSG_ID_STD)
|
|
{
|
|
/* Set standard global mask for RX FIFO */
|
|
val |= ((mask & FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT1);
|
|
}
|
|
else if (id_type == FLEXCAN_MSG_ID_EXT)
|
|
{
|
|
/* Set extended global mask for RX FIFO */
|
|
val |= ((mask & FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK1) << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT1);
|
|
}
|
|
else
|
|
{
|
|
/* Should not get here */
|
|
}
|
|
|
|
break;
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_C):
|
|
if ((id_type == FLEXCAN_MSG_ID_EXT) || (id_type == FLEXCAN_MSG_ID_STD))
|
|
{
|
|
val |= ((mask & FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_MASK) << FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1);
|
|
}
|
|
else
|
|
{
|
|
/* Should not get here */
|
|
}
|
|
|
|
break;
|
|
case (FLEXCAN_RX_FIFO_ID_FORMAT_D):
|
|
/* Format not supported.*/
|
|
break;
|
|
default:
|
|
/* Should not get here */
|
|
break;
|
|
} /* End Switch */
|
|
|
|
return val;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_IsMbOutOfRange
|
|
* Description : Check if the mb index is out of range or not.
|
|
*
|
|
*END**************************************************************************/
|
|
boolean FlexCAN_IsMbOutOfRange
|
|
(
|
|
const FLEXCAN_Type * pBase,
|
|
uint8 u8MbIndex,
|
|
boolean bIsLegacyFifoEn,
|
|
uint32 u32MaxMbNum
|
|
)
|
|
{
|
|
boolean returnValue = (boolean)FALSE;
|
|
uint32 u32NumOfFiFoElement = 0U;
|
|
uint32 u32NumOfMbOccupiedByFiFo = 0U;
|
|
|
|
if (u8MbIndex >= (uint8)u32MaxMbNum)
|
|
{
|
|
returnValue = (boolean)TRUE;
|
|
}
|
|
/* Check if RX FIFO is enabled*/
|
|
else if ((boolean)TRUE == bIsLegacyFifoEn)
|
|
{
|
|
/* Get the number of RX FIFO Filters*/
|
|
u32NumOfFiFoElement = (((pBase->CTRL2) & FLEXCAN_CTRL2_RFFN_MASK) >> FLEXCAN_CTRL2_RFFN_SHIFT);
|
|
/* Get the number if MBs occupied by RX FIFO and ID filter table*/
|
|
/* the Rx FIFO occupies the memory space originally reserved for MB0-5*/
|
|
/* Every number of RFFN means 8 number of RX FIFO filters*/
|
|
/* and every 4 number of RX FIFO filters occupied one MB*/
|
|
u32NumOfMbOccupiedByFiFo = 5U + ((((u32NumOfFiFoElement) + 1U) * 8U) / 4U);
|
|
if (u8MbIndex <= u32NumOfMbOccupiedByFiFo)
|
|
{
|
|
returnValue = (boolean)TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
returnValue = (boolean)FALSE;
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FLEXCAN_IsEnhancedRxFifoAvailable
|
|
* Description : Checks if FlexCAN has Enhanced Rx FIFO.
|
|
* This function is private.
|
|
*
|
|
*END**************************************************************************/
|
|
boolean FlexCAN_IsEnhancedRxFifoAvailable(const FLEXCAN_Type * base)
|
|
{
|
|
uint32 i=0U;
|
|
static FLEXCAN_Type * const flexcanBase[] = CAN_BASE_PTRS_HAS_ENHANCED_RX_FIFO;
|
|
boolean returnValue = FALSE;
|
|
for (i = 0U; i < FEATURE_CAN_ENHANCED_RX_FIFO_NUM; i++)
|
|
{
|
|
if (base == flexcanBase[i])
|
|
{
|
|
returnValue = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_EnableEnhancedRxFifo
|
|
* Description : Enable Enhanced Rx FIFO feature.
|
|
* This function will enable the Enhanced Rx FIFO feature.
|
|
*
|
|
*END**************************************************************************/
|
|
Flexcan_Ip_StatusType FlexCAN_EnableEnhancedRxFifo(FLEXCAN_Type * base,
|
|
uint32 numOfStdIDFilters,
|
|
uint32 numOfExtIDFilters,
|
|
uint32 numOfWatermark)
|
|
{
|
|
Flexcan_Ip_StatusType stat = FLEXCAN_STATUS_SUCCESS;
|
|
uint32 numOfEnhancedFilters = 0U;
|
|
|
|
if (FlexCAN_IsEnhancedRxFifoAvailable(base))
|
|
{
|
|
|
|
/* numOfEnhancedFilters equals (numOfStdIDFilters/2) + numOfExtIDFilters - 1u */
|
|
numOfEnhancedFilters = (numOfStdIDFilters >> 1u) + numOfExtIDFilters - 1u;
|
|
|
|
if ((numOfStdIDFilters == 0U) && (numOfExtIDFilters == 0U))
|
|
{
|
|
stat = FLEXCAN_STATUS_ERROR;
|
|
}
|
|
/* If the no of Std Filters is odd */
|
|
if ((numOfStdIDFilters & 1U) == 1U)
|
|
{
|
|
stat = FLEXCAN_STATUS_ERROR;
|
|
}
|
|
/*Enhanced RX FIFO and Legacy RX FIFO cannot be enabled at the same time.*/
|
|
if ((base->MCR & FLEXCAN_MCR_RFEN_MASK) == FLEXCAN_MCR_RFEN_MASK)
|
|
{
|
|
stat = FLEXCAN_STATUS_ERROR;
|
|
}
|
|
|
|
if (stat == FLEXCAN_STATUS_SUCCESS)
|
|
{
|
|
/* Enable Enhanced Rx FIFO */
|
|
base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_ERFEN_MASK) | FLEXCAN_ERFCR_ERFEN(1U);
|
|
/* Reset Enhanced Rx FIFO engine */
|
|
base->ERFSR = (base->ERFSR & ~FLEXCAN_ERFSR_ERFCLR_MASK) | FLEXCAN_ERFSR_ERFCLR(1U);
|
|
/* Clear the status bits of the Enhanced RX FIFO */
|
|
base->ERFSR = base->ERFSR & ~(FLEXCAN_ERFSR_ERFUFW_MASK | FLEXCAN_ERFSR_ERFOVF_MASK | FLEXCAN_ERFSR_ERFWMI_MASK | FLEXCAN_ERFSR_ERFDA_MASK);
|
|
/* Set the total number of enhanced Rx FIFO filter elements */
|
|
base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_NFE_MASK) | ((numOfEnhancedFilters << FLEXCAN_ERFCR_NFE_SHIFT) & FLEXCAN_ERFCR_NFE_MASK);
|
|
/* Set the number of extended ID filter elements */
|
|
base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_NEXIF_MASK) | ((numOfExtIDFilters << FLEXCAN_ERFCR_NEXIF_SHIFT) & FLEXCAN_ERFCR_NEXIF_MASK);
|
|
/* Set the Enhanced Rx FIFO watermark */
|
|
base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_ERFWM_MASK) | ((numOfWatermark << FLEXCAN_ERFCR_ERFWM_SHIFT) & FLEXCAN_ERFCR_ERFWM_MASK);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
stat = FLEXCAN_STATUS_ERROR;
|
|
}
|
|
|
|
return stat;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_SetEnhancedRxFifoFilter
|
|
* Description : Configure Enhanced RX FIFO ID filter table elements.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_SetEnhancedRxFifoFilter(FLEXCAN_Type * base,
|
|
const Flexcan_Ip_EnhancedIdTableType * idFilterTable)
|
|
{
|
|
/* Set Enhanced RX FIFO ID filter table elements*/
|
|
uint32 i, j, n, numOfEnhancedFilter, numOfExtIDFilter, numOfStdIDFilter;
|
|
uint32 val2 = 0U, val1 = 0U, val = 0U;
|
|
|
|
volatile uint32 * filterExtIDTable = NULL_PTR;
|
|
volatile uint32 * filterStdIDTable = NULL_PTR;
|
|
|
|
numOfEnhancedFilter = (((base->ERFCR) & FLEXCAN_ERFCR_NFE_MASK) >> FLEXCAN_ERFCR_NFE_SHIFT);
|
|
numOfExtIDFilter = (((base->ERFCR) & FLEXCAN_ERFCR_NEXIF_MASK) >> FLEXCAN_ERFCR_NEXIF_SHIFT);
|
|
numOfStdIDFilter = 2U * (numOfEnhancedFilter - numOfExtIDFilter + 1U);
|
|
filterExtIDTable = &base->ERFFEL[EnhancedRxFifoFilterTableBase];
|
|
filterStdIDTable = &base->ERFFEL[numOfExtIDFilter * 2U];
|
|
j = 0U;
|
|
n = 0U;
|
|
for (i = 0U; i < (numOfExtIDFilter + numOfStdIDFilter); i++)
|
|
{
|
|
if (!(idFilterTable[i].isExtendedFrame))
|
|
{
|
|
val = 0U;
|
|
if (idFilterTable[i].rtr2)
|
|
{
|
|
val = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_RTR2_SHIFT;
|
|
}
|
|
|
|
if (idFilterTable[i].rtr1)
|
|
{
|
|
val |= FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_RTR1_SHIFT;
|
|
}
|
|
|
|
filterStdIDTable[j] =
|
|
((idFilterTable[i].id2 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_SHIFT2) |
|
|
((idFilterTable[i].id1 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_SHIFT1) | val;
|
|
switch (idFilterTable[i].filterType)
|
|
{
|
|
case FLEXCAN_ENHANCED_RX_FIFO_ONE_ID_FILTER :
|
|
{
|
|
filterStdIDTable[j] |= FlexCanEnhancedRxFifoOneIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
|
|
}break;
|
|
|
|
case FLEXCAN_ENHANCED_RX_FIFO_RANGE_ID_FILTER :
|
|
{
|
|
filterStdIDTable[j] |= FlexCanEnhancedRxFifoRangerIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
|
|
}break;
|
|
|
|
case FLEXCAN_ENHANCED_RX_FIFO_TWO_ID_FILTER :
|
|
{
|
|
filterStdIDTable[j] |= FlexCanEnhancedRxFifoTwoIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
|
|
}break;
|
|
default:
|
|
{
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert((boolean)FALSE);
|
|
/* Should not get here */
|
|
#endif
|
|
}break;
|
|
}
|
|
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
val2 = 0U;
|
|
val1 = 0U;
|
|
if (idFilterTable[i].rtr2)
|
|
{
|
|
val2 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_RTR_SHIFT;
|
|
}
|
|
|
|
if (idFilterTable[i].rtr1)
|
|
{
|
|
val1 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_RTR_SHIFT;
|
|
}
|
|
filterExtIDTable[n] = ((idFilterTable[i].id2 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_SHIFT) |
|
|
val2;
|
|
|
|
filterExtIDTable[n + 1U] = ((idFilterTable[i].id1 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_SHIFT) |
|
|
val1;
|
|
switch (idFilterTable[i].filterType)
|
|
{
|
|
case FLEXCAN_ENHANCED_RX_FIFO_ONE_ID_FILTER :
|
|
{
|
|
filterExtIDTable[n] |= FlexCanEnhancedRxFifoOneIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
|
|
}break;
|
|
case FLEXCAN_ENHANCED_RX_FIFO_RANGE_ID_FILTER :
|
|
{
|
|
filterExtIDTable[n] |= FlexCanEnhancedRxFifoRangerIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
|
|
}break;
|
|
case FLEXCAN_ENHANCED_RX_FIFO_TWO_ID_FILTER :
|
|
{
|
|
filterExtIDTable[n] |= FlexCanEnhancedRxFifoTwoIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
|
|
}break;
|
|
default :
|
|
{
|
|
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
|
|
DevAssert((boolean)FALSE);
|
|
/* Should not get here */
|
|
#endif
|
|
}break;
|
|
}
|
|
n = n + 2U;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_ClearOutputEnhanceFIFO
|
|
* Description : Clear output of enhance fifo.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_ClearOutputEnhanceFIFO(FLEXCAN_Type * base)
|
|
{
|
|
volatile uint32 * Ram = (uint32 *)((uint32)base);
|
|
uint32 lastword_offset = ((uint32)0x204C) / ((uint32)4U); /* fixed, because DMALW is always = 19 */
|
|
uint8 u8TimeOut = 0;
|
|
|
|
/* If Enhanced Rx FIFO has Pending Request that generated error,
|
|
* the EnhancedRxFIFO need to be empty to activate DMA */
|
|
if (FlexCAN_GetEnhancedRxFIFOStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE) == (uint8)1U)
|
|
{
|
|
/* Enter CAN in freeze Mode to allow Enhanced Rx FIFO Clear */
|
|
FlexCAN_EnterFreezeMode(base);
|
|
FlexCAN_ClearEnhancedFIFO(base);
|
|
|
|
do
|
|
{
|
|
if ((uint32)FLEXCAN_MCR_DMA_MASK == (base->MCR & ((uint32)FLEXCAN_MCR_DMA_MASK)))
|
|
{
|
|
/* Read Enhanced Output to clear DMA pending request */
|
|
(void)Ram[lastword_offset];
|
|
}
|
|
else
|
|
{
|
|
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE);
|
|
}
|
|
u8TimeOut++;
|
|
}
|
|
while ((FlexCAN_GetEnhancedRxFIFOStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE) == (uint8)1U) && (u8TimeOut <= ((uint8)64U))); /* avoid blocking */
|
|
|
|
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_OVERFLOW);
|
|
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_WATERMARK);
|
|
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE);
|
|
FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_UNDERFLOW);
|
|
|
|
/* Return CAN to normal Mode */
|
|
FlexCAN_ExitFreezeMode(base);
|
|
}
|
|
}
|
|
#endif /* (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON) */
|
|
#endif /* (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
|
|
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_ClearOutputLegacyFIFO
|
|
* Description : Clear output of legacy fifo.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_ClearOutputLegacyFIFO(FLEXCAN_Type * base)
|
|
{
|
|
volatile uint32 * Ram = (uint32 *)((uint32)base);
|
|
uint32 lastword_offset = ((uint32)0x8C) / ((uint32)4U); /* fixed, dma last word */
|
|
uint8 i = 0;
|
|
|
|
/* Check if FIFO has Pending Request that generated error,
|
|
* the RxFIFO need to be empty to activate DMA */
|
|
if (FlexCAN_GetBuffStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE) == (uint8)1U)
|
|
{
|
|
/* Enter CAN in freeze Mode to allow FIFO Clear */
|
|
FlexCAN_EnterFreezeMode(base);
|
|
FlexCAN_ClearFIFO(base);
|
|
do
|
|
{
|
|
if ((uint32)FLEXCAN_MCR_DMA_MASK == (base->MCR & ((uint32)FLEXCAN_MCR_DMA_MASK)))
|
|
{
|
|
/* Read Offset 0x8C to clear DMA pending request */
|
|
(void)Ram[lastword_offset];
|
|
}
|
|
else
|
|
{
|
|
FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE);
|
|
}
|
|
i++;
|
|
}
|
|
while ((FlexCAN_GetBuffStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE) == (uint8)1U) && (i <= (uint8)12U)); /* avoid blocking */
|
|
FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE);
|
|
FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_WARNING);
|
|
FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_OVERFLOW);
|
|
|
|
/* Return CAN to normal Mode */
|
|
FlexCAN_ExitFreezeMode(base);
|
|
}
|
|
}
|
|
#endif /* FEATURE_CAN_HAS_DMA_ENABLE */
|
|
|
|
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
|
|
void FlexCAN_ConfigTimestamp(FLEXCAN_Type * base, Flexcan_Ip_TimeStampConfigType * config)
|
|
{
|
|
uint32 temp = 0U;
|
|
temp = FLEXCAN_CTRL2_TIMER_SRC(config->timeStampSurce);
|
|
temp |= FLEXCAN_CTRL2_MBTSBASE(config->msgBuffTimeStampType);
|
|
temp |= FLEXCAN_CTRL2_TSTAMPCAP(config->hrConfigType);
|
|
|
|
base->CTRL2 &= ~(FLEXCAN_CTRL2_TIMER_SRC_MASK | FLEXCAN_CTRL2_MBTSBASE_MASK | FLEXCAN_CTRL2_TSTAMPCAP_MASK);
|
|
base->CTRL2 |= temp;
|
|
|
|
if (config->hrConfigType != FLEXCAN_TIMESTAMPCAPTURE_DISABLE)
|
|
{
|
|
FlexCAN_ConfigTimestampModule(config);
|
|
}
|
|
}
|
|
#endif /* (FEATURE_CAN_HAS_HR_TIMER == STD_ON) */
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : FlexCAN_ConfigCtrlOptions
|
|
* Description : configure controller depending on options
|
|
* note: should be call after FD configuration.
|
|
*
|
|
*END**************************************************************************/
|
|
void FlexCAN_ConfigCtrlOptions(FLEXCAN_Type * pBase, uint32 u32Options)
|
|
{
|
|
#if (FEATURE_CAN_SWITCHINGISOMODE == STD_ON)
|
|
/* If the FD feature is enabled, in order to be ISO-compliant. */
|
|
if ((u32Options & CAN_FD_ISO_U32) != 0U)
|
|
{
|
|
FlexCAN_SetIsoCan(pBase, (boolean)TRUE);
|
|
}
|
|
else
|
|
{
|
|
/* This maybe don't have sense if the Deinit returns the state of registers at init values */
|
|
FlexCAN_SetIsoCan(pBase, (boolean)FALSE);
|
|
}
|
|
#endif /*(FEATURE_CAN_SWITCHINGISOMODE == STD_ON) */
|
|
/* Set Entire Frame Arbitration Field Comparison. */
|
|
if ((u32Options & CAN_EACEN_U32) != 0U)
|
|
{
|
|
FlexCAN_SetEntireFrameArbitrationFieldComparison(pBase, (boolean)TRUE);
|
|
}
|
|
else
|
|
{
|
|
FlexCAN_SetEntireFrameArbitrationFieldComparison(pBase, (boolean)FALSE);
|
|
}
|
|
#if (FEATURE_CAN_PROTOCOLEXCEPTION == STD_ON)
|
|
/* Set protocol Exception */
|
|
if ((u32Options & CAN_PROTOCOL_EXCEPTION_U32) != 0U)
|
|
{
|
|
FlexCAN_SetProtocolException(pBase, (boolean)TRUE);
|
|
}
|
|
else
|
|
{
|
|
FlexCAN_SetProtocolException(pBase, (boolean)FALSE);
|
|
}
|
|
#endif /* Endif (FEATURE_CAN_PROTOCOLEXCEPTION == STD_ON) */
|
|
/* Set CAN Bit Sampling */
|
|
if (((u32Options & CAN_THREE_SAMPLES_U32) != 0U) && ((pBase->MCR & FLEXCAN_MCR_FDEN_MASK) == 0U))
|
|
{
|
|
FlexCAN_CanBitSampling(pBase, (boolean)TRUE);
|
|
}
|
|
else
|
|
{
|
|
FlexCAN_CanBitSampling(pBase, (boolean)FALSE);
|
|
}
|
|
|
|
/* Set AutoBusOff Recovery */
|
|
if ((u32Options & CAN_BUSOFF_RECOVERY_U32) != 0U)
|
|
{
|
|
FlexCAN_SetBusOffAutorecovery(pBase, (boolean)TRUE);
|
|
}
|
|
else
|
|
{
|
|
FlexCAN_SetBusOffAutorecovery(pBase, (boolean)FALSE);
|
|
}
|
|
#if (FEATURE_CAN_EDGEFILTER == STD_ON)
|
|
/* Set Edge Filter */
|
|
if ((u32Options & CAN_EDGE_FILTER_U32) != 0U)
|
|
{
|
|
FlexCAN_SetEdgeFilter(pBase, (boolean)TRUE);
|
|
}
|
|
else
|
|
{
|
|
FlexCAN_SetEdgeFilter(pBase, (boolean)FALSE);
|
|
}
|
|
#endif /* End of (FEATURE_CAN_EDGEFILTER == STD_ON) */
|
|
}
|
|
|
|
#define CAN_STOP_SEC_CODE
|
|
#include "Can_MemMap.h"
|
|
|
|
/** @} */
|