/*
* codrv_mcan - driver for mcan
*
* Copyright (c) 2017-2020 emotas embedded communication GmbH
*-------------------------------------------------------------------
* SVN $Id: codrv_mcan.c 51556 2023-12-18 09:35:01Z ro $
*
*
*-------------------------------------------------------------------
*
*
*/

/*
Functionality Singleline:
	- extended and standard id
	- rtr
	- software auto bus on
	- CAN-FD ISO
	- id filter
	- id group filter
*/





/***************************************************************************/
/**
* \file
* \brief   mCAN CAN driver (e.g. STM32, LPC, Atmel)
*
*
*
* Note: This settings should be part of gen_define.h!
* 
*/

/* #define CO_DRV_FILTER 1 */
/* #define CO_DRV_GROUP_FILTER 1 */





/* header of standard C - libraries
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stddef.h>
#include <string.h>

/* header of project specific types
---------------------------------------------------------------------------*/
#include <gen_define.h>

#include <co_datatype.h>
#include <co_drv.h>
#include <codrv_error.h>
#include <co_commtask.h>

#include "codrv_mcan.h"


/* constant definitions
---------------------------------------------------------------------------*/
/*
 * Below is the message RAM setting, it will be stored in the system RAM.
 * Please adjust the message size according to your application.
 */
#if defined(CODRV_MCAN_STM32_L5) || defined(CODRV_MCAN_STM32_G0) || defined(CODRV_MCAN_STM32_G4) || defined(CODRV_MCAN_STM32_U5) || defined(CODRV_MCAN_STM32_H5)
# define CODRV_MCAN_FIXED_MSG_RAM		1u
# define CODRV_MCAN_FILTER_STD_SIZE		28u
# define CODRV_MCAN_FILTER_EXT_SIZE		8u
# define CODRV_MCAN_RXFIFO_SIZE			3u
# define CODRV_MCAN_ELEMENT_DATA_SIZE	64u
# define CODRV_MCAN_TXBUFFER_SIZE		3u
# define CODRV_RX0L_IR_POS				2u
#endif /* defined(CODRV_MCAN_STM32_L5) || defined(CODRV_MCAN_STM32_G0) || defined(CODRV_MCAN_STM32_G4) || defined(CODRV_MCAN_STM32_U5) || defined(CODRV_MCAN_STM32_H5) */

/* The value should be 8/12/16/20/24/32/48/64. */
# ifndef CODRV_MCAN_ELEMENT_DATA_SIZE
#  define CODRV_MCAN_ELEMENT_DATA_SIZE		8u
#  define CODRV_MCAN_ELEMENT_SIZE_CODE		0u
# endif /*CODRV_MCAN_ELEMENT_DATA_SIZE*/

/**
* \define CODRV_MCAN_RXFIFO_SIZE
* Number of rx fifo elements
*/
#ifndef CODRV_MCAN_RXFIFO_SIZE
#  define CODRV_MCAN_RXFIFO_SIZE		(10u)
#endif /* CODRV_MCAN_RXFIFO_SIZE */


/**
* \define CODRV_RX0L_IR_POS
* RX-fifo message lost flag position
*/
#ifndef CODRV_RX0L_IR_POS
# define CODRV_RX0L_IR_POS				3u
#endif /* CODRV_RX0L_IR_POS */

/**
* \define CODRV_MCAN_TXBUFFER_SIZE
* Number of tx buffer elements
*/
#ifndef CODRV_MCAN_TXBUFFER_SIZE
# define CODRV_MCAN_TXBUFFER_SIZE	1u
#endif /* CODRV_MCAN_TXBUFFER_SIZE */

/**
* \define CODRV_MCAN_FILTER_STD_SIZE
* Number of std id filter elements
*/
#ifndef CODRV_MCAN_FILTER_STD_SIZE
# ifdef CO_DRV_FILTER
#   define CODRV_MCAN_FILTER_STD_SIZE		(28u)
# else /* CO_DRV_FILTER */
#  define CODRV_MCAN_FILTER_STD_SIZE		0u
# endif /* CO_DRV_FILTER */
#endif /* CODRV_MCAN_FILTER_STD_SIZE */

/**
* \define CODRV_MCAN_FILTER_EXT_SIZE
* Number of ext id filter elements
*/
#ifndef CODRV_MCAN_FILTER_EXT_SIZE
# ifdef CO_DRV_FILTER
#   define CODRV_MCAN_FILTER_EXT_SIZE		(28u)
# else /* CO_DRV_FILTER */
#  define CODRV_MCAN_FILTER_EXT_SIZE		0u
# endif /* CO_DRV_FILTER */
#endif /* CODRV_MCAN_FILTER_EXT_SIZE */


#define MCAN_SIDF_SIZE       4u  /* standard id filter */
#define MCAN_XIDF_SIZE       8u  /* extended id filter */
#define MCAN_RXF0_SIZE      (MCAN_XIDF_SIZE + CODRV_MCAN_ELEMENT_DATA_SIZE)  /* rx fifo 0 */
#define MCAN_RXB_SIZE       (MCAN_XIDF_SIZE + CODRV_MCAN_ELEMENT_DATA_SIZE)  /* rx buffer */
#define MCAN_TXE_SIZE        8u  /* tx event */
#define MCAN_TXB_SIZE       (MCAN_XIDF_SIZE + CODRV_MCAN_ELEMENT_DATA_SIZE)  /* tx buffer */

/**
* \define CODRV_DEBUG
* UART Debug output
*/
/* #define CODRV_DEBUG 1 */

/**
* \define POLLING
* work without interrupts
* !! Seldom tested - support is not guaranteed !!
*/
/* #define POLLING 1 */


/* OS related macros - default definition */
#ifdef CO_OS_SIGNAL_CAN_TRANSMIT
#else
#  define CO_OS_SIGNAL_CAN_TRANSMIT
#endif

#ifdef CO_OS_SIGNAL_CAN_RECEIVE
#else
#  define CO_OS_SIGNAL_CAN_RECEIVE
#endif


/* local defined data types
---------------------------------------------------------------------------*/
typedef struct {
	UNSIGNED32 id;
	UNSIGNED32 ctrl;
	UNSIGNED8  data[CODRV_MCAN_ELEMENT_DATA_SIZE];
}MCAN_FIFO_ELEMENT_T;

typedef struct {
	UNSIGNED32 F0;
	UNSIGNED32 F1;
}MCAN_EXT_FILTER_ELEMENT_T;

typedef struct {
#if defined(CO_DRV_FILTER) || defined(CODRV_MCAN_FIXED_MSG_RAM)
	UNSIGNED32 stdIdFilter[CODRV_MCAN_FILTER_STD_SIZE];
	MCAN_EXT_FILTER_ELEMENT_T extIdFilter[CODRV_MCAN_FILTER_EXT_SIZE];
#endif /* CO_DRV_FILTER || CODRV_MCAN_FIXED_MSG_RAM */
	MCAN_FIFO_ELEMENT_T rxFifo[CODRV_MCAN_RXFIFO_SIZE];
#ifdef CODRV_MCAN_FIXED_MSG_RAM
	MCAN_FIFO_ELEMENT_T rxFifo2[CODRV_MCAN_RXFIFO_SIZE];
	UNSIGNED8 eventfifo[8 * 3];
#endif /* CODRV_MCAN_FIXED_MSG_RAM */
	MCAN_FIFO_ELEMENT_T txBuf[CODRV_MCAN_TXBUFFER_SIZE];
} MCAN_MSGRAM_T;

/* list of external used functions, if not in headers
---------------------------------------------------------------------------*/

/* list of global defined functions
---------------------------------------------------------------------------*/
#ifdef CODRV_DEBUG
# ifdef CO_DRV_FILTER
void printFilter(void);
# endif /* CO_DRV_FILTER */
#endif /* CODRV_DEBUG */

/* list of local defined functions
---------------------------------------------------------------------------*/

static RET_T codrvCanInitController(UNSIGNED16 nomBitrate, UNSIGNED16 datBitrate);

static RET_T codrvCanTransmit(CO_CONST CO_CAN_TR_MSG_T * pBuf);
static CO_CONST CODRV_BTR_T * codrvCanGetBtrSettings(UNSIGNED16 bitRate);

static void codrvCanResetRam(void);

#ifdef CO_DRV_FILTER
# ifdef CO_DRV_GROUP_FILTER
static BOOL_T codrvCanCheckGroupFilter(CO_CONST CO_CAN_COB_T * CO_CONST pCob);
# endif /* CO_DRV_GROUP_FILTER */
static RET_T codrvCanEnableExtIdFilter(CO_CAN_COB_T * CO_CONST pCob);
static RET_T codrvCanEnableStdIdFilter(CO_CAN_COB_T * CO_CONST pCob);
static RET_T codrvCanDisableExtIdFilter(CO_CAN_COB_T * CO_CONST pCob);
static RET_T codrvCanDisableStdIdFilter(CO_CAN_COB_T * CO_CONST pCob);
#endif

#ifdef CODRV_AUTOBAUD
RET_T codrvAutoBaudNextBitrate(void);
UNSIGNED16 codrvAutoBaudGetActualBitrate(void);
#endif /* CODRV_AUTOBAUD */

/* external variables
---------------------------------------------------------------------------*/

/* global variables
---------------------------------------------------------------------------*/

/* local defined variables
---------------------------------------------------------------------------*/



static BOOL_T canEnabled = { CO_FALSE };
static volatile BOOL_T transmissionIsActive = { CO_FALSE };

static UNSIGNED32 oldEsrValue;

/** currently TX message buffer */
static CO_CAN_TR_MSG_T *pTxBuf = { NULL };


/** CAN Controller address */
#ifdef CODRV_MCAN_STM32_H7
# define CODRV_MCAN0_ADDR	((CODRV_MCANFD_T*)0x4000A000ul)
# define CODRV_MCAN1_ADDR	((CODRV_MCANFD_T*)0x4000A400ul)
#endif /* CODRV_MCAN_STM32_H7 */

#ifdef CODRV_MCAN_STM32_MP1
# define CODRV_MCAN0_ADDR	((CODRV_MCANFD_T*)0x4400E000ul)
# define CODRV_MCAN1_ADDR	((CODRV_MCANFD_T*)0x4400F000ul)
#endif /* CODRV_MCAN_STM32_MP1 */

#if defined(CODRV_MCAN_STM32_G0) || defined(CODRV_MCAN_STM32_G4)
# define CODRV_MCAN0_ADDR	((CODRV_MCANFD_T*)0x40006400ul)
# define CODRV_MCAN1_ADDR	((CODRV_MCANFD_T*)0x40006800ul)
# if  defined(CODRV_MCAN_STM32_G4)
#  define CODRV_MCAN2_ADDR	((CODRV_MCANFD_T*)0x40006C00ul)
# endif /* defined(CODRV_MCAN_STM32_G4) */
#endif /* defined(CODRV_MCAN_STM32_G0) || defined(CODRV_MCAN_STM32_G4) */

/* STM32L5 - only CPUs with 1 FDCAN out at the moment! */
#if defined(CODRV_MCAN_STM32_L5)
# define CODRV_MCAN0_ADDR	((CODRV_MCANFD_T*)0x4000A400ul)
#endif /* defined(CODRV_MCAN_STM32_L5) */

/* STM32U5 - only CPUs with 1 FDCAN out at the moment! */
#if defined(CODRV_MCAN_STM32_U5)
# define CODRV_MCAN0_ADDR	((CODRV_MCANFD_T*)0x4000A400ul)
#endif /* defined(CODRV_MCAN_STM32_U5) */

#ifdef CODRV_MCAN_STM32_H5
# define CODRV_MCAN0_ADDR	((CODRV_MCANFD_T*)0x4000A400ul)
# define CODRV_MCAN1_ADDR	((CODRV_MCANFD_T*)0x4000A800ul)
#endif /* CODRV_MCAN_STM32_MP1 */

#ifndef CODRV_MCAN0_ADDR
# error select MCAN configuration first!
#endif /* CODRV_MCAN0_ADDR */


/** \var pCan - used CAN controller address */
# ifdef CONFIG_MCAN0
static volatile CODRV_MCANFD_T * const pCan = CODRV_MCAN0_ADDR; /*lint !e923 CAN controller address */
# endif /* CONFIG_MCAN0 */
# ifdef CONFIG_MCAN1
static volatile CODRV_MCANFD_T * const pCan = CODRV_MCAN1_ADDR; /*lint !e923 CAN controller address */
# endif /* CONFIG_MCAN1 */
# ifdef CONFIG_MCAN2
static volatile CODRV_MCANFD_T * const pCan = CODRV_MCAN2_ADDR; /*lint !e923 CAN controller address */
# endif /* CONFIG_MCAN2 */

/** CAN message RAM address */
#define  CODRV_MCAN_STATIC_MSG_RAM

# ifdef CONFIG_MCAN0
static const UNSIGNED8 mcanMsgRamOffs = 0u;
# endif /* CONFIG_MCAN0 */
# ifdef CONFIG_MCAN1
static const UNSIGNED8 mcanMsgRamOffs = 1u;
# endif /* CONFIG_MCAN1 */
# ifdef CONFIG_MCAN2
static const UNSIGNED8 mcanMsgRamOffs = 2u;
# endif /* CONFIG_MCAN2 */

#ifdef CODRV_MCAN_STATIC_MSG_RAM
# ifdef CODRV_MCAN_STM32_H7
static volatile MCAN_MSGRAM_T * const pMcanMsgRam = (MCAN_MSGRAM_T*)(0x4000AC00u);
# endif /* CODRV_MCAN_STM32_H7 */

# ifdef CODRV_MCAN_STM32_MP1
static volatile MCAN_MSGRAM_T * const pMcanMsgRam = (MCAN_MSGRAM_T*)(0x44011000u);
# endif /* CODRV_MCAN_STM32_MP1 */

# ifdef CODRV_MCAN_STM32_G0
static volatile MCAN_MSGRAM_T * const pMcanMsgRam = (MCAN_MSGRAM_T*)(0x4000B400u);
# endif /* CODRV_MCAN_STM32_G0 */

# ifdef CODRV_MCAN_STM32_G4
static volatile MCAN_MSGRAM_T * const pMcanMsgRam = (MCAN_MSGRAM_T*)(0x4000A400u);
# endif /* CODRV_MCAN_STM32_G4 */

# ifdef CODRV_MCAN_STM32_L5
static volatile MCAN_MSGRAM_T * const pMcanMsgRam = (MCAN_MSGRAM_T*)(0x4000AC00u);
# endif /* CODRV_MCAN_STM32_L5 */

# ifdef CODRV_MCAN_STM32_U5
static volatile MCAN_MSGRAM_T * const pMcanMsgRam = (MCAN_MSGRAM_T*)(0x4000AC00u);
# endif /* CODRV_MCAN_STM32_U5 */

# ifdef CODRV_MCAN_STM32_H5
static volatile MCAN_MSGRAM_T * const pMcanMsgRam = (MCAN_MSGRAM_T*)(0x4000AC00u);
# endif /* CODRV_MCAN_STM32_U5 */

# else /* CODRV_MCAN_STATIC_MSG_RAM */
static volatile MCAN_MSGRAM_T mcanMsgRam __attribute__((section(".MCAN_SECTION")));
static volatile MCAN_MSGRAM_T * volatile pMcanMsgRam = &mcanMsgRam;

# ifdef CONFIG_MCAN0
static volatile UNSIGNED32* pMcanMRBA = (UNSIGNED32 *)0x4009D200ul;
# endif /* CONFIG_MCAN0 */
# ifdef CONFIG_MCAN1
static volatile UNSIGNED32* pMcanMRBA = (UNSIGNED32 *)0x4009e200ul;
# endif /* CONFIG_MCAN1 */
#endif /* CODRV_MCAN_STATIC_MSG_RAM */



#ifdef CODRV_BIT_TABLE_EXTERN

extern CO_CONST CODRV_BTR_T codrvCanBittimingTable[];

#else /* CODRV_BIT_TABLE_EXTERN */
/** CAN bittiming table */
static CO_CONST CODRV_BTR_T codrvCanBittimingTable[] = {
# ifdef CODRV_CANCLOCK_PRE_10BIT
		/* 80MHz table */
		{   10u, 500u, 0u, 13u, 2u }, /* 87.5% */
		{   20u, 250u, 0u, 13u, 2u }, /* 87.5% */
		{   50u, 100u, 0u, 13u, 2u }, /* 87.5% */
# endif /* CODRV_CANCLOCK_PRE_10BIT */
		{  100u,  50u, 0u, 13u, 2u }, /* 87.5% */
		{  125u,  40u, 0u, 13u, 2u }, /* 87.5% */
		{  250u,  20u, 0u, 13u, 2u }, /* 87.5% */
		{  500u,  10u, 0u, 13u, 2u }, /* 87.5% */
		{  800u,  10u, 0u,  8u, 1u }, /* 90.0% */
		{ 1000u,   5u, 0u, 13u, 2u }, /* 87.5% */
		{    0u,   0u, 0u,  0u, 0u }  /* last */
	};
#endif /* CODRV_BIT_TABLE_EXTERN */

#ifdef CODRV_AUTOBAUD
static UNSIGNED16	autoBaudBitRateIdx = { 0u };
static UNSIGNED8	autoBaudActive = { 0u };
#endif /* CODRV_AUTOBAUD */


/*---------------------------------------------------------------------------*/
/* #define DEBUG_SEND_TESTMESSAGE */
#ifdef DEBUG_SEND_TESTMESSAGE
static void codrvSendTestMessage(
		void	/* no parameter */
	)
{
MCAN_MSGRAM_T * pRam;

	pRam = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);

	pRam->txBuf[0].id = (0x555 << 18u);
	pRam->txBuf[0].ctrl = (9u << 16u);/* | (3u << 20u)*/;
	pRam->txBuf[0].data[0] = 0x01;
	pRam->txBuf[0].data[7] = 0x08;

	pCan->TXBTIE = 0x01;
	pCan->TXBAR = 0x01;
}
#endif /* DEBUG_SEND_TESTMESSAGE */
/*---------------------------------------------------------------------------*/



/***************************************************************************/
/**
* \brief codrvCanInit - init CAN controller
*
* This Function inits the CAN controller and setup the bitrate
* After that, the CAN controller is disabled.
*
* \param
*	bitrate	- CANopen bitrate
* \results
*	RET_T
*/
RET_T codrvCanInit(
		UNSIGNED16	bitRate			/**< Bitrate */
	)
{
RET_T	retVal;

	/* clear the FD RAM */
	codrvCanResetRam();

#ifdef CO_DRV_FILTER
	/* start of ID filter  */
#endif /* CO_DRV_FILTER */


	retVal = codrvCanInitController(bitRate, 0u);

	return(retVal);
}




/***************************************************************************/
/**
* \brief codrvCanReInit - reinit CAN controller
*
* This Function reinits the CAN controller after deactivation.
* 
* In Filter mode: After this function call all Filter are reset and must
* be reconfigured!
*
* At the end of the function, the CAN controller should be in state disabled.
*
* \param
*	bitrate	- CANopen bitrate
* \results
*	RET_T
*/
RET_T codrvCanReInit(
		UNSIGNED16	bitRate		/**< Bitrate */
	)
{
RET_T	retVal;


	retVal = codrvCanInitController(bitRate,0u);

	return(retVal);
}




/***************************************************************************/
/**
* \brief codrvCanInitController - init CAN controller
*
* \internal
*
* This Function inits the CAN controller and setup the bitrate
* After that, the CAN controller is disabled.
*
* \param
*	bitrate	- CANopen bitrate
* \results
*	RET_T
*/
static RET_T codrvCanInitController(
		UNSIGNED16 nomBitrate,
		UNSIGNED16 datBitrate
	)
{
RET_T	retVal = RET_OK;

#ifdef CODRV_MCAN_FIXED_MSG_RAM
#else /* CODRV_MCAN_FIXED_MSG_RAM */
UNSIGNED32 ramOffset = (sizeof(MCAN_MSGRAM_T) * mcanMsgRamOffs);
#endif /* CODRV_MCAN_FIXED_MSG_RAM */

	/* exit from sleep mode */
	pCan->CCCR &= ~MCAN_CCCR_BIT_CSR;
	/* wait for sleep mode acknowledge */
	while((pCan->CCCR & MCAN_CCCR_BIT_CSA) == MCAN_CCCR_BIT_CSA)  {
		;
	}

	/* Request initialization */
	pCan->CCCR |= MCAN_CCCR_BIT_INIT;
	while((pCan->CCCR & MCAN_CCCR_BIT_INIT) != MCAN_CCCR_BIT_INIT)  {
		;
	}

	/* Enable configuration change */
	pCan->CCCR |= MCAN_CCCR_BIT_CCE;
	while((pCan->CCCR & MCAN_CCCR_BIT_CCE) != MCAN_CCCR_BIT_CCE)  {
		;
	}

	/* set the ram address for message ram */
#ifdef CODRV_MCAN_STATIC_MSG_RAM
#else /* CODRV_MCAN_STATIC_MSG_RAM */
	*pMcanMRBA = (UNSIGNED32)pMcanMsgRam;
#endif /* CODRV_MCAN_STATIC_MSG_RAM */

	/* setup filter */
#ifdef CODRV_MCAN_FIXED_MSG_RAM
#else /* CODRV_MCAN_FIXED_MSG_RAM */
	pCan->SIDFC = ((UNSIGNED32)CODRV_MCAN_FILTER_STD_SIZE << 16u) | ramOffset;
	ramOffset += MCAN_SIDF_SIZE  * CODRV_MCAN_FILTER_STD_SIZE;
	pCan->XIDFC = ((UNSIGNED32)CODRV_MCAN_FILTER_EXT_SIZE << 16u) | ramOffset;
	ramOffset += MCAN_XIDF_SIZE  * CODRV_MCAN_FILTER_EXT_SIZE;

	/* RX Buffer/FIFO Element Size 64 bytes data field */
	pCan->RXESC |= (UNSIGNED32)CODRV_MCAN_ELEMENT_SIZE_CODE;

	/* RX Buffer/FIFO configuration */
	pCan->RXF0C = ((UNSIGNED32)CODRV_MCAN_RXFIFO_SIZE << 16u) | ramOffset;
	ramOffset += CODRV_MCAN_RXFIFO_SIZE * MCAN_RXF0_SIZE;
#endif /* CODRV_MCAN_FIXED_MSG_RAM */

#ifdef CO_DRV_FILTER
	/* the GFC register differs if the message ram is fixed or not.
	   This has to be checked if new STM32 derivatives are released,
	   that this is still the case! */
# ifdef CODRV_MCAN_FIXED_MSG_RAM
	pCan->GFC = (UNSIGNED32)(0x3c | (CODRV_MCAN_FILTER_EXT_SIZE << 24) | (CODRV_MCAN_FILTER_STD_SIZE << 16)) ;
# else /* CODRV_MCAN_FIXED_MSG_RAM */
	pCan->GFC = (UNSIGNED32)0x3c;
# endif /* CODRV_MCAN_FIXED_MSG_RAM */
#else /* CO_DRV_FILTER */
	/* Accept Non-matching Frames Into FIFO 0 */
	pCan->GFC = (UNSIGNED32)0x0;
#endif /* CO_DRV_FILTER */

#ifdef CODRV_MCAN_FIXED_MSG_RAM
#else /* CODRV_MCAN_FIXED_MSG_RAM */

	/* only support one Tx Buffer currently */
	pCan->TXBC = ((UNSIGNED32)1u << 16u) | ramOffset;

	/* support up to 64 bytes payload */
	pCan->TXESC = ((UNSIGNED32)CODRV_MCAN_ELEMENT_SIZE_CODE);
#endif /* CODRV_MCAN_FIXED_MSG_RAM */


	/* Set the automatic retransmission */
	pCan->CCCR &= ~MCAN_CCCR_BIT_DAR;


	/* init req. variables */
	canEnabled = CO_FALSE;
	transmissionIsActive = CO_FALSE;

	/* error states */
	codrvCanErrorInit();

	/* set bitrate */
	retVal = codrvCanSetBitRate(nomBitrate);  /*lint !e838 initialization for long function */
	(void)datBitrate;

#ifdef DEBUG_SEND_TESTMESSAGE
	if (retVal == RET_OK)  {
		codrvCanEnable();
		codrvSendTestMessage();
	}
#endif /* DEBUG_SEND_TESTMESSAGE */

	return(retVal);
}


#ifdef CODRV_AUTOBAUD
/***************************************************************************/
/**
*
* codrvAutoBaudNextBitrate - set next bitrate for autobaud
*
* \internal
*
* \returns
*	RET_T
*/
RET_T codrvAutoBaudNextBitrate(
		void	/* no parameter */
	)
{
RET_T retVal;

	autoBaudBitRateIdx++;
	if (codrvCanBittimingTable[autoBaudBitRateIdx].bitRate == 0u)  {
		autoBaudBitRateIdx = 0u;
	}

	retVal = codrvCanSetBitRate(codrvCanBittimingTable[autoBaudBitRateIdx].bitRate);  /*lint !e838 initialization for long function */

	return(retVal);
}


/***********************************************************************/
/**
* codrvAutoBaudGetActualBitrate - get actual used bitrate
*
* This function returns the actual used bitrate.
* They haven't be valid.
*
*
* \returns
*	bitrate
*/
UNSIGNED16 codrvAutoBaudGetActualBitrate(
		void	/* no parameter */
	)
{
	return(codrvCanBittimingTable[autoBaudBitRateIdx].bitRate);
}
#endif /* CODRV_AUTOBAUD */


/***************************************************************************/
/**
* codrvCanGetBtrSettings - get pointer to the btr value structure
*
* \internal
*
* \returns
*	pointer to an btr table entry
*/

static CO_CONST CODRV_BTR_T * codrvCanGetBtrSettings(
		UNSIGNED16 bitRate	/**< required bitrate */
	)
{
CO_CONST CODRV_BTR_T * pBtrEntry = NULL;
UNSIGNED8 i = 0u;

	while (codrvCanBittimingTable[i].bitRate != 0u)  {
		if (codrvCanBittimingTable[i].bitRate == bitRate)  {
			pBtrEntry = &codrvCanBittimingTable[i];
			break;
		}
		i++;
	}

	return(pBtrEntry);
}


/***************************************************************************/
/**
* codrvCanSetBitRate - sets the CAN bit rate
*
* \internal
*
* Changing the Bitrate only if the CAN controller is in Reset
*
* \param
*	bitRate in kbit/s
* \results
*	RET_T
*
*/
RET_T codrvCanSetBitRate(
		UNSIGNED16		bitRate		/**< bit rate in kbit/s */
	)
{
CO_CONST CODRV_BTR_T * pBtrEntry;

UNSIGNED32 pre;
UNSIGNED32 seg1;
UNSIGNED32 seg2;

	/* stop CAN controller */
	(void)codrvCanDisable();

	pBtrEntry = codrvCanGetBtrSettings(bitRate);

	if (pBtrEntry == NULL)  {
		/* if bitrate not supported */
		return(RET_DRV_WRONG_BITRATE);
	}
	
	/* Enable configuration change */
	pCan->CCCR |= MCAN_CCCR_BIT_CCE;
	while((pCan->CCCR & MCAN_CCCR_BIT_CCE) != MCAN_CCCR_BIT_CCE)  {
		;
	}

	pre = (UNSIGNED32)pBtrEntry->pre;
	seg1 = (UNSIGNED32)pBtrEntry->seg1 + (UNSIGNED32)pBtrEntry->prop;
	seg2 = (UNSIGNED32)pBtrEntry->seg2;

#ifdef CODRV_AUTOBAUD
# warning "autobaud not supported yet"
#endif
	pCan->NBTP = ((UNSIGNED32)(seg2 - 1u) << 25) | /*use same size for sjw as seg2*/\
							 ((UNSIGNED32)(pre - 1u) << 16) | \
							 ((UNSIGNED32)(seg1 - 1u) << 8) | \
							 ((UNSIGNED32)(seg2 - 1u));

	return(RET_OK);
}




/***************************************************************************/
/**
* codrvCanEnable - enable CAN controller
*
* \internal
*
* \param
*	none
* \results
*	RET_T
*/
RET_T codrvCanEnable(
		void	/* no parameter */
	)
{
	pCan->CCCR &= ~MCAN_CCCR_BIT_INIT;
	/* Error active is later checked */

	/* enable interrupts */
	codrvCanEnableInterrupt();
	/* enable interrupt line 0 */
	pCan->ILE = 1u;

	pCan->IE = MCAN_IE_BIT_RF0NE | MCAN_IE_BIT_TCE | MCAN_IE_BIT_BO | MCAN_IE_BIT_EP;

#ifdef CO_DRV_FILTER
# ifdef CODRV_DEBUG
	printFilter();
# endif /* CODRV_DEBUG */
#endif /* CO_DRV_FILTER */
	canEnabled = CO_TRUE;
	oldEsrValue = 0xFFffFFffu;

	return(RET_OK);
}


/***************************************************************************/
/**
* codrvCanDisable - disable CAN controller
*
* This function disables the CAN controller.  The function waits
* for the CAN controller being disabled. Code calling this function
* typically expects that after returning the CAN controller is in Init mode.
*
* But note, the time the CAN controller needs to enter the Init mode
* can be as long as the duration of one CAN frame.
*
* \internal
*
* \param
*	none
* \results
*	RET_OK CAN controller is set to be disabled
*/
RET_T codrvCanDisable(
		void	/* no parameter */
	)
{
	/* disable CAN controller */
	pCan->CCCR |= MCAN_CCCR_BIT_INIT;
	while ((pCan->CCCR & MCAN_CCCR_BIT_INIT) == 0u)  {
		/* 500us on 250kbit/s */
	}

	pCan->ILE = 0u;

	pCan->IE &= ~MCAN_IE_BIT_RF0NE;
	pCan->IE &= ~MCAN_IE_BIT_TCE;
	pCan->IE &= ~MCAN_IE_BIT_BO;
	pCan->IE &= ~MCAN_IE_BIT_EP;

	canEnabled = CO_FALSE;

	return(RET_OK);
}


#ifdef CO_DRV_FILTER
# ifdef CO_DRV_GROUP_FILTER
/***********************************************************************/
/**
* \brief codrvCheckGroupFilter - check, if the canId part of the group filter
*
* Depend of some settings the group filter are for the IDs
*	0x700..0x77F - Heartbeat
*	0x80..0xFF   - Emergency (and default Sync)
*
* \return BOOL_T
* \retval CO_TRUE
*	The ID is part of the group filter.
* \retval CO_FALSE
*	The ID is not part of the group filter.
*	
*	
*
*/
static BOOL_T codrvCanCheckGroupFilter(
		CO_CONST CO_CAN_COB_T * CO_CONST pCob
	)
{
BOOL_T retval;
UNSIGNED32 canId = pCob->canId;

	retval = CO_FALSE;


	if ((pCob->flags & CO_COBFLAG_RTR) != CO_COBFLAG_RTR)
	{
#  ifdef CO_HB_CONSUMER_CNT
		if ((canId & 0x0780u) == 0x700u)  {
			/* part of the group filter */
			retval = CO_TRUE;
		}
#  endif /* CO_HB_CONSUMER_CNT */
#  ifdef CO_EMCY_CONSUMER_CNT
		if ((canId & 0x0780u) == 0x80u)  {
			/* part of the group filter */
			retval = CO_TRUE;
		}
#  endif /* CO_EMCY_CONSUMER_CNT */
	}

	return(retval);
}
# endif /* CO_DRV_GROUP_FILTER */


/***************************************************************************/
/* codrvCanDisableExtIdFilter -disables an extended filter element
*
* This function disables an extended filter element from a given cob. The
* element number is coded in the upper 8bits of the canChan member.
*
* \internal
*
* \results
*	RET_T
*/
static RET_T codrvCanDisableExtIdFilter(
		CO_CAN_COB_T * CO_CONST pCob
	)
{
UNSIGNED16 chan;
MCAN_MSGRAM_T * pRam;

	pRam = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);

	if ((pCob->canChan & 0xff00) == 0xff00)  {
		/* already disabled */
		return(RET_OK);  /*lint !e904 function entry check */
	}
	chan = pCob->canChan >> 8u;
	pRam->extIdFilter[chan].F0 = 0u;
	pRam->extIdFilter[chan].F1= 0u;
	pCob->canChan |= 0xff00;

	return(RET_OK);
}


/***************************************************************************/
/* codrvCanDisableStdIdFilter -disables an standard filter element
*
* This function disables an standard filter element from a given cob. The
* element number is coded in the lower 8bits of the canChan member.
*
* \internal
*
* \results
*	RET_T
*/
static RET_T codrvCanDisableStdIdFilter(
		CO_CAN_COB_T * CO_CONST pCob
	)
{
UNSIGNED16 chan;
MCAN_MSGRAM_T * pRam;

	pRam = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);

	if ((pCob->canChan & 0x00ff) == 0x00ff)  {
		/* already disabled */
		return(RET_OK);  /*lint !e904 function entry check */
	}
	chan = pCob->canChan & 0x00ff;
	pRam->stdIdFilter[chan] = 0x00000000u;
	pCob->canChan |= 0x00ff;

	return(RET_OK);
}


static RET_T codrvCanEnableExtIdFilter(
		CO_CAN_COB_T * CO_CONST pCob
	)
{
UNSIGNED16 chan;
UNSIGNED32 mask;
MCAN_MSGRAM_T * pRam;

	pRam = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);

	chan = pCob->canChan >> 8u;

	if (chan == 0xff)  {
		/* search next free entry */
		for (chan = 0u; chan < CODRV_MCAN_FILTER_EXT_SIZE; chan++)  {
			if (pRam->extIdFilter[chan].F0 == 0u)  {
				break;
			}
		}
		if (chan == CODRV_MCAN_FILTER_EXT_SIZE)  {
			return(RET_DRV_ERROR);
		}
	}
	pRam->extIdFilter[chan].F0 = pCob->canId & 0x1fffffff;

	mask = ~(pCob->ignore);
	mask &= 0x1fffffff;

	pRam->extIdFilter[chan].F1 = 0x2u << 30u;
	pRam->extIdFilter[chan].F1 |= mask;

	/* enable filter */
	pRam->extIdFilter[chan].F0 |= 0x20000000;

	pCob->canChan &= 0x00ff;
	pCob->canChan |= (chan << 8u);


	return(RET_OK);
}



static RET_T codrvCanEnableStdIdFilter(
		CO_CAN_COB_T * CO_CONST pCob
	)
{
UNSIGNED16 chan;
UNSIGNED32 mask;
MCAN_MSGRAM_T * pRam;

	pRam = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);

	chan = pCob->canChan & 0xff;

	if (chan == 0xff)  {
		/* search next free entry */
		for (chan = 0u; chan < CODRV_MCAN_FILTER_STD_SIZE; chan++)  {
			if (pRam->stdIdFilter[chan] == 0x00000000u)  {
				break;
			}
		}
		if (chan == CODRV_MCAN_FILTER_STD_SIZE)  {
			return(RET_DRV_ERROR);
		}
	}
	pRam->stdIdFilter[chan] = pCob->canId & 0x7ff;
	pRam->stdIdFilter[chan] <<= 16u;

	mask = ~(pCob->ignore);
	mask &= 0x7ff;

	pRam->stdIdFilter[chan] |= mask;

	/* enable filter */
	pRam->stdIdFilter[chan] |= (1u<<27);
	pRam->stdIdFilter[chan] |= (2u<<30);

	pCob->canChan &= 0xff00;
	pCob->canChan |= chan;


	return(RET_OK);
}


/***********************************************************************/
/**
* codrvCanSetFilter - activate and configure the receive filter
*
* Depend of the COB entry's the driver specific filter will 
* be configured. 
*
* For the bxCan only Base Identifiere are allowed.
* 
*
* \retval RET_OK
*	OK
* \retval RET_INVALID_PARAMETER
*	invalid COB reference
* \retval RET_DRV_ERROR
*	filter cannot be set, e.g. no free entry
*
*/

RET_T codrvCanSetFilter(
		CO_CAN_COB_T * pCanCob /**< COB reference */
	)
{

# ifdef CODRV_DEBUG
	printf("codrvCanSetFilter: 0x%04x rtr: %d enabled: %d\n", pCanCob->canId, (pCanCob->flags & CO_COBFLAG_RTR), (pCanCob->flags & CO_COBFLAG_ENABLED));
# endif



	/* get a filter entry in case of:
	 * - COB has a filter entry from older setting or
	 * - COB is enabled and
	 * - COB is a Receive Data Frame or
	 * - COB is a Transmit Data Frame, but can be query by RTR
	 */
	(void)codrvCanDisableExtIdFilter(pCanCob);
	(void)codrvCanDisableStdIdFilter(pCanCob);

	if ((pCanCob->flags & CO_COBFLAG_ENABLED) == CO_COBFLAG_ENABLED)  {
		if ((pCanCob->flags & CO_COBFLAG_EXTENDED) == CO_COBFLAG_EXTENDED)  {
			return(codrvCanEnableExtIdFilter(pCanCob));
		} else {
			return(codrvCanEnableStdIdFilter(pCanCob));
		}
	}


# ifdef CODRV_DEBUG
	printFilter();
# endif

	return(RET_OK);
}
#endif /* CO_DRV_FILTER */


/***********************************************************************/
/**
* codrvCanStartTransmission - start can transmission if not active
*
* Transmission of CAN messages should be interrupt driven.
* If a message was sent, the Transmit Interrupt is called
* and the next message can be transmitted.
* To start the transmission of the first message,
* this function is called from the stack.
*
* The easiest way to implement this function is
* to trigger the transmit interrupt, 
* but only if the transmission is not already active.
*
* \internal
*
* \return RET_T
*
*/
RET_T codrvCanStartTransmission(
		void	/* no parameter */
	)
{
RET_T retVal = RET_DRV_BUSY;
	
	/* if can is not enabled, return with error */
	if (canEnabled != CO_TRUE)  {
		return(RET_DRV_ERROR); /*lint !e904 function entry check */
	}

	if (transmissionIsActive == CO_FALSE)  {
		/* trigger transmit interrupt */
#ifdef POLLING
		retVal = codrvCanTransmitInterrupt();
#else /* POLLING */
		/* enable global interrupt pending bit to call interrupt */
		codrvCanSetTxInterrupt();
#endif /* POLLING */
	} else {
		codrvCanDriverHandler();
	}

	return(retVal);
}


/***************************************************************************/
/* codrvCanTransmit - transmit can message
*
* This function writes a new message to the CAN controller and transmits it.
* Normally called from transmit Interrupt
*
* \internal
*
* \results
*	RET_T
*/
static RET_T codrvCanTransmit(
		CO_CONST CO_CAN_TR_MSG_T * pBuf		/**< pointer to data */
	)
{
RET_T			retVal = RET_OK;
/* currently, general MB 0 */
UNSIGNED32 ctrl;
UNSIGNED8 i;
MCAN_MSGRAM_T * pRam;

	pRam = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);

	/* return if device is not initialized or enabled */
	if (canEnabled == CO_FALSE)  {
		return(RET_DRV_ERROR);
	}

	/* busy check */
	if (pCan->TXBRP != 0ul)  {
		return(RET_DRV_BUSY);  /*lint !e904 function entry check */
	}

	ctrl = pBuf->len;
	if (ctrl > 8u)  {
		ctrl = 8u;
	}
	pRam->txBuf[0u].ctrl = (ctrl << 16u);

	/* extended CAN ID */
	if ((pBuf->flags & CO_COBFLAG_EXTENDED) == CO_COBFLAG_EXTENDED)  {
		/* message with 29 bit identifier */
		pRam->txBuf[0u].id = pBuf->canId;
		pRam->txBuf[0u].id |= MCAN_CANID_BIT_XTD;
	} else {
		/* message with 11 bit identifier */
		pRam->txBuf[0u].id = (pBuf->canId << 18u);
	}

	/* remote transmission request */
	if ((pBuf->flags & CO_COBFLAG_RTR) == CO_COBFLAG_RTR)  {
		/* message is remote frame */
		pRam->txBuf[0u].id |= MCAN_CANID_BIT_RTR;
	}

	/* copy message data */
	if ((pBuf->flags & CO_COBFLAG_RTR) != CO_COBFLAG_RTR)  {
		for (i = 0u; i < CODRV_MCAN_ELEMENT_DATA_SIZE; i = i + 4u)  {
			*((UNSIGNED32*)&(pRam->txBuf[0u].data[i])) =
					(UNSIGNED32)pBuf->data[i] | \
					((UNSIGNED32)pBuf->data[i + 1] << 8u) | \
					((UNSIGNED32)pBuf->data[i + 2] << 16u) | \
					((UNSIGNED32)pBuf->data[i + 3] << 24u);
		}
	}

	/* transmit it */
	/* currently, general MB 0 */
	pCan->TXBAR = 1ul;
	pCan->TXBTIE = 0x01;

	transmissionIsActive = CO_TRUE;

	return(retVal);
}


/***************************************************************************/
/* codrvCanDriverTransmitInterrupt - can driver transmit interrupt
*
* \internal
*
* This function is called, after message was transmitted.
* As first, inform stack about message transmission.
* Get the next message from the transmit buffer, write it to the CAN controller
* and transmit it.
*
* \param
*	none
* \results
*	none
*/
RET_T codrvCanTransmitInterrupt(
		void	/* no parameter */
	)
{
RET_T retVal = RET_OK;

	/* reset interrupt request 
	* => currently reset all possible TX IRQ requests
	*
	* -> very simple implementation
	*/

	if (pCan->TXBRP == 0ul)  {
		transmissionIsActive = CO_FALSE;

		/* inform stack about transmitted message */
		if (pTxBuf != NULL)  {
			coQueueMsgTransmitted(pTxBuf);
			pTxBuf = NULL;

			/* signal transmitted message */
			CO_OS_SIGNAL_CAN_TRANSMIT
		}

		/* get next message from transmit queue */
		pTxBuf = coQueueGetNextTransmitMessage();
		if (pTxBuf != NULL)  {
			/* and transmit it - CAN message buffer is free */
			retVal = codrvCanTransmit(pTxBuf);
		}
		/* clear interrupt flag */
		pCan->IR = MCAN_IE_BIT_TCE;
	} else {
		retVal = RET_DRV_BUSY;
	}
	
	return(retVal);
}


/***********************************************************************
* codrvCanReceiveInterrupt - can driver receive interrupt
*
* \internal
*
* This function is called, if a new message was received
* As first get the pointer to the receive buffer
* and save the message there.
* Then set the buffer as filled and inform the library about new data.
*
*
* \param
*	none
* \results
*	none
*/
void codrvCanReceiveInterrupt(
		void	/* no parameter */
	)
{
UNSIGNED8 *pRecBuf;
UNSIGNED8 coFlags;
UNSIGNED8 len;
UNSIGNED8 mbNr = 0u;
UNSIGNED32 id;
CAN_ERROR_FLAGS_T * pError;
UNSIGNED8 i;
MCAN_MSGRAM_T * pRam;
#ifdef CO_CAN_TIMESTAMP_SUPPORTED
CO_CAN_TIMESTAMP_T timestamp;
#endif /* CO_CAN_TIMESTAMP_SUPPORTED */

	pRam = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);

	pCan->IR = MCAN_IE_BIT_RF0NE;

	if ((pCan->RXF0S & 0x7f) == 0u)  {
		return;
	}


	do {
		/* delete pending interrupt */
		pCan->IR = MCAN_IE_BIT_RF0NE;
		/* initialize COB flag */
		coFlags = CO_COBFLAG_NONE;

		/* currently only Fifo 0 */
		mbNr = ((pCan->RXF0S >> 8u) & 0x3f);

		/* get Identifier */
		id = pRam->rxFifo[mbNr].id;

		/* extended CAN-ID */
		if ((id & MCAN_CANID_BIT_XTD) == MCAN_CANID_BIT_XTD)  {
			coFlags |= CO_COBFLAG_EXTENDED;
		}

		/* remote transmission request */
		if ((id & MCAN_CANID_BIT_RTR) == MCAN_CANID_BIT_RTR)  {
			coFlags |= CO_COBFLAG_RTR;
		}

		len = (pRam->rxFifo[mbNr].ctrl >> 16) & 0x0f;
		/* FD frame */
		if (((pRam->rxFifo[mbNr].ctrl >> 21) & 0x01) == 1u)  {
			continue;
		} else {
			if (len > 8u)  {
				len = 8u;
			}
		}

		/* save 11/29 bit CAN-ID */
		if ((id & MCAN_CANID_BIT_XTD) != MCAN_CANID_BIT_XTD)  {
			/* save 11 bit CAN-ID */
			id = (id >> 18u) & 0x7FFul;
		} else {
			/* save 29 bit CAN-ID */
			id = id & 0x1FFFFFFFul;
		}

#ifdef CO_CAN_TIMESTAMP_SUPPORTED
		/* get RX timestamp */
		timestamp = (UNSIGNED32)(pRam->rxFifo[mbNr].ctrl & 0xffFF);
#endif /* CO_CAN_TIMESTAMP_SUPPORTED */

		/* get receiveBuffer */
		pRecBuf = coQueueGetReceiveBuffer(id, len, coFlags
#ifdef CO_CAN_TIMESTAMP_SUPPORTED
			, timestamp
#endif /* CO_CAN_TIMESTAMP_SUPPORTED */
		);
		if (pRecBuf == NULL)  {
			/* error, no buffer available */

			/* release mailbox */
			pCan->RXF0A = mbNr;

			/* signal received message - but there was generated
			 * signals for all older received messages 
			 * that are in the buffer 
			 */
			/* CO_OS_SIGNAL_CAN_RECEIVE */

			return;	/*lint !e904 no buffer possible */
		}

		/* save message at buffer */
		if ((id & MCAN_CANID_BIT_RTR) != MCAN_CANID_BIT_RTR)  {
			for (i = 0u; i < len; i++)  {
				pRecBuf[i] = pRam->rxFifo[mbNr].data[i];
			}
		}

		if ((pCan->RXF0S & (1u << 25u)) == (1u << 25u))  {
			pError = codrvCanErrorGetFlags();
			pError->canErrorRxOverrun = CO_TRUE;

			/* reset message lost error */
			pCan->IR |= (1u << CODRV_RX0L_IR_POS);
		}

		/* release mailbox */
		pCan->RXF0A = mbNr;

		/* set buffer filled */
		coQueueReceiveBufferIsFilled();
	} while (pCan->RXF0S & 0x7f);

	/* signal received message */
	CO_OS_SIGNAL_CAN_RECEIVE

}


/***********************************************************************
* codrvCanErrorInterrupt - can driver error interrupt
*
* \internal
*
* This function is called, if a error passive or Busoff event
* occurs.
*
* \param
*	none
* \results
*	none
*/
void codrvCanErrorInterrupt(
		void	/* no parameter */
	)
{
	if ((pCan->IR & (MCAN_IE_BIT_BO | MCAN_IE_BIT_EP)) != 0u)  {
	CAN_ERROR_FLAGS_T * pError;

		/* set flag to signal the state change */
		pError = codrvCanErrorGetFlags();
		if ((pCan->IR & MCAN_IE_BIT_BO) != 0)  {
			pError->canErrorBusoff = CO_TRUE;
			/* clear init bit to get buss on again */
			pCan->CCCR &= ~MCAN_CCCR_BIT_INIT;
		} else
		if ((pCan->IR & MCAN_IE_BIT_EP) != 0)  {
			pError->canErrorPassive = CO_TRUE;
		} else {
			/* never occur, because the error interrupt is not
			 * calling for this state change */
			pError->canErrorActive = CO_TRUE;
		}

		/* clear interrupt bit */
		pCan->IR = (MCAN_IE_BIT_BO | MCAN_IE_BIT_EP);
	}
}


/***************************************************************************/
/**
* codrvCanErrorHandler - Error handler
*
* This function polls the current state of the CAN controller
* and checks explicitly all situation that are not signaled
* within the interrupts.
*
* Call outside of interrupts!
* Typical call in codrvCanDriverHandler().
*/

static void codrvCanErrorHandler(
		void	/* no parameter */
	)
{

UNSIGNED32 err;
UNSIGNED32 change;
CAN_ERROR_FLAGS_T * pError;
BOOL_T fStartTransmission = CO_FALSE;

	pError = codrvCanErrorGetFlags();

	/*
	* Error active/passive/busoff check 
	*/
	err = pCan->PSR;


	/* check only changes of passive and busoff */
	change = err ^ oldEsrValue;
	change &= ((MCAN_PSR_BIT_BO) | (MCAN_PSR_BIT_EP));

	if (change != 0ul)  {
		if ((err & MCAN_PSR_BIT_BO) != 0ul)  {
			/* busoff */
			/* canErrorBusoff = CO_TRUE;*/
			pError->canNewState = Error_Busoff; /* current state */
		} else
		if ((err & MCAN_PSR_BIT_EP) != 0ul)  {
			/* error passive */
			/* canErrorPassive = CO_TRUE; */
			pError->canNewState = Error_Passive; /* current state */
		} else {
			/* error active */
			/* canErrorActive = CO_TRUE; */
			pError->canNewState = Error_Active; /* current state */
		}
	}
	oldEsrValue = err;

	/* busoff recovery */
	if ((err & MCAN_PSR_BIT_BO) != 0ul)  {
		/* busoff */
		pCan->CCCR &= ~MCAN_CCCR_BIT_INIT;
	}

	/* more for polling - software interrupt, but TX object was sended */
	if (pCan->TXBRP == 0ul)  {
		/* correct possible Errors -> CAN has deactivated the transmission */
		transmissionIsActive = CO_FALSE;
	}

	if (canEnabled == CO_TRUE)  {
		/* check for stopped transmissions */
		if ((transmissionIsActive == CO_FALSE) && (pTxBuf != NULL))  {
			/* transmission aborted, e.g. busoff, 
		     * discard message -> is done within the tx interrupt
			*/
			fStartTransmission = CO_TRUE;
		}
	}

	if (fStartTransmission == CO_TRUE)  {
		(void)codrvCanStartTransmission(); /* -> call Interrupt at this point */
	}
}


/***************************************************************************/
/** codrvCanDriverHandler - can driver handler
*
* \internal
*
* is cyclically called from stack to get actual CAN state
* (BUS_OFF, PASSIVE, ACTIVE)
* and return to bus on again after bus off was occurred.
*
* \param
*	none
* \results
*	none
*/
void codrvCanDriverHandler(
		void	/* no parameter */
	)
{
	/* check current state */
	codrvCanErrorHandler();

	/*
	* inform the CANopen Stack about state changes
	*/
	(void)codrvCanErrorInformStack();

#ifdef POLLING
	codrvCanReceiveInterrupt();
	codrvCanTransmitInterrupt();
#endif /* POLLING */

	return;
}



#ifdef CODRV_DEBUG
#include <stdio.h>
void printFilter(void)
{
# ifdef CODRV_DEBUG_MAX
int i,j;
volatile UNSIGNED32 *pCanFilter = pCanFilterAddr;

	printf("\nFiltersettings:\n");
	printf("FINIT %d\n", pCanFilter[BXCAN_CANFMR] & BXCAN_CANFMR_FINIT );
	printf("Filter active (0 off 1 on)       0x%08lx\n", pCanFilter[BXCAN_CANFA1R]);
	printf("Filtermode (0 mask 1 list)       0x%08lx\n", pCanFilter[BXCAN_CANFM1R]);
	printf("Filterscale (0 16-bit 1 32-bit)  0x%08lx\n", pCanFilter[BXCAN_CANFS1R]);
	printf("Filter assignm (0 fifo0 1 fifo1) 0x%08lx\n", pCanFilter[BXCAN_CANFFA1R]);

	printf("\n");
	//for(i = 0; i < 14; i++) 
	for(i = 0; i <= 0; i++)
	{
		for (j = 1; j <= 2; j++)  {
			printf("\n");
			printf("Filterbank %d Register %d\n", i,j );
			printf("Adr: 0x%08lx\n", &pCanFilter[BXCAN_CANFIRX(i,j)]);

			printf("  ID 0x%04x\n", (pCanFilter[BXCAN_CANFIRX(i,j)] & 0xFFFFul) >> 5 );
			if( (pCanFilter[BXCAN_CANFM1R] & (1ul << i)) != 0)  {
				printf("  ID 0x%04x\n", (pCanFilter[BXCAN_CANFIRX(i,j)] >> (16 + 5) )& 0xFFFFul);
			} else {
				printf("Mask 0x%04x\n", (pCanFilter[BXCAN_CANFIRX(i,j)] >> (16 + 5) )& 0xFFFFul);
			}
		}

	}

	for(i = 1; i < 14; i++)
	{
		if( (pCanFilter[BXCAN_CANFA1R] & (1ul << i)) != 0)  {
			for (j = 1; j <= 2; j++)  {
				printf("\n");
				printf("Filterbank %d Register %d Val 0x%08lx\n", i,j, pCanFilter[BXCAN_CANFIRX(i,j)] );

				printf("  ID 0x%04x\n", (pCanFilter[BXCAN_CANFIRX(i,j)] & 0xFFFFul) >> 5);


				printf("  ID 0x%04x\n", ((pCanFilter[BXCAN_CANFIRX(i,j)] >> 16 )& 0xFFFFul) >> 5);
			}
		}

	}
# endif

}

#endif

static void codrvCanResetRam(
		void	/* no parameter */
	)
{
volatile MCAN_MSGRAM_T *pOffset;

	pOffset = (MCAN_MSGRAM_T *)(pMcanMsgRam + mcanMsgRamOffs);
	memset((void*)pOffset, 0x00u, sizeof(MCAN_MSGRAM_T));
}

