CAN Bus Hardware Porting Guide#
In order to work properly, Micrium OS CAN Bus requires a specific hardware driver for any CAN Bus controller IP. Moreover, each CAN Bus controller must have a board support package (BSP). The BSP has two purposes:
Initializing and configuring resources needed by the CAN Bus controller that are provided by an external module
Providing hardware information to the CAN Bus driver
Micrium provides examples of BSPs for some popular platforms. If one is available for your platform, we recommend that you use it as a starting point. However, if no example BSP is available for your platform, the information in this section will help you understand how to correctly port the CAN Bus module.
Note that each CAN Bus controller (that you are planning to use) will require a BSP, and all the steps described in this section must be performed for each of them.
CAN Bus BSP Functions Guide#
A Board Support Package contains a set of functions that support your specific hardware platform on Micrium OS. These functions are called by the CAN Bus driver to perform hardware configuration, or initialization of IO pins, interrupts, and so on. It is your responsibility to either create these functions from scratch or to modify example code to fit your needs and the specifics of your hardware.
Each of these functions is described below.
Open#
The Open function is used to set the CAN Bus clock, and set the IO pins and route them to the desired pins. Listing - Open Function Signature in the CAN Bus BSP Functions Guide page shows the signature of the function.
Listing - Open Function Signature#
void BSP_CAN_Open (void);
This function is called each time the CAN controller operations are started by the CAN Bus module.
Close#
The Close function is used to disable the CAN Bus clock, unset IO route, and disable CAN Bus interrupt. Listing - Close Function Signature in the CAN Bus BSP Functions Guide page shows the signature of the function.
Listing - Close Function Signature#
void BSP_CAN_Close (void);
This function is called each time the CAN controller operations are stopped by the CAN Bus module.
Timer Configuration#
The Timer Config function is used to configure and enable a timer that can be used by a CAN high-level protocol. Listing - Timer Configuration Function Signature in the CAN Bus BSP Functions Guide page shows the signature of the function.
Listing - Timer Configuration Function Signature#
void BSP_CAN_TmrCfg (CPU_INT32U tmr_period)
The period of this timer is set to the value of tmr_period in microseconds. The timer configuration typically encompasses:
Initializing the input clock required by the timer peripheral
Configuring the interrupt service routine associated with the timer
Enabling the interrupt line for the timer
Configuring the timer period to periodically generate an interrupt
Refer to the section Timer ISR Handling for more details about the timer ISR.
Interrupt Control#
The Interrupt Control function is used to register the interrupt service routine associated with the CAN controller and enable the CAN Bus interrupt. Listing - Interrupt Control Function Signature in the CAN Bus BSP Functions Guide page shows the signature of the function.
Listing - Interrupt Control Function Signature#
void BSP_CAN_IntCtrl (CAN_BUS_HANDLE bus_handle);
In addition, the function should store a bus handle associated to the CAN controller. The bus handle is provided by the parameter bus_handle. It will be needed inside the controller's interrupt service routine to indicate to the CAN Bus module which CAN controller the interrupt is associated to (see ISR Handling for more details).
ISR Handling#
Each CAN Bus controller driver has an ISR handler function that must be called each time a CAN Bus interrupt is triggered. However, for most platforms, it will be necessary to implement an intermediate ISR handler in the BSP. This BSP ISR will then call the driver's ISR handler. This is necessary because some interrupt controllers may require the interrupt status to be cleared each time it is triggered. It is also necessary if your interrupt controller does not support passing an argument to the interrupt vector, as the driver's ISR handler takes the bus_handle received in the IntCtrl () function of the BSP as an argument.
Listing - Example of BSP ISR Implementation in the CAN Bus BSP Functions Guide page shows an example of an ISR handler implemented in the BSP if using a Silicon Labs chip (that follows the CMSIS naming standard). Note that the global variable BSP_CAN_BusHandle will have been set in the function IntCtrl () .
Listing - Example of BSP ISR Implementation#
void CAN0_IRQHandler (void)
{
OSIntEnter();
CanBus_ISRHandler(BSP_CAN0_BusHandle);
OSIntExit();
}
Timer ISR Handling#
The timer ISR has been configured in the function TmrCfg() . This timer ISR represents the BSP Timer ISR which should call the CAN driver's timer ISR handler. This is necessary, as some interrupt controllers may require the interrupt status to be cleared each time it is triggered.
Listing - Example of BSP Timer ISR Implementation in the CAN Bus BSP Functions Guide page shows an example of a Timer ISR handler implemented in the BSP if using a Silicon Labs chip (that follows the CMSIS naming standard).
Listing - Example of BSP Timer ISR Implementation#
void TIMER0_IRQHandler (void)
{
CPU_INT32U timer_get;
OSIntEnter();
timer_get = TIMER_IntGet(TIMER0);
CanBus_TmrISRHandler();
TIMER_IntClear(TIMER0, timer_get);
OSIntExit();
}
CAN Hardware Information#
Hardware Driver Information#
The CAN Bus driver requires information about the CAN Bus controller on your MCU, which you can provide using a structure of type CAN_CTRLR_HW_INFO. This information can be found in the manual for your MCU.
Table - CAN_CTRLR_HW_INFO Structure in the CAN Hardware Information page describes each configuration field available in this structure.
Table - CAN_CTRLR_HW_INFO Structure#
Field | Description |
---|---|
.BaseAddr | Base address of the CAN Bus controller registers set. |
.InfoExtPtr | Pointer to an extended hardware information structure. Some drivers may require extra information, so the format of this structure is specific to your driver. Most of the time this can be set to DEF_NULL. |
.IF_Rx | Reception interface number. This interface can take the value of 0 or 1. |
.IF_Tx | Transmission interface number. This interface can take the value of 0 or 1. |
BSP API Structure#
In order to provide a pointer to the BSP functions for the CAN Bus controller driver, you must create a structure of type CAN_CTRLR_BSP_API.
Table - CAN_CTRLR_BSP_API Structure in the CAN Hardware Information page describes each field available in this structure.
Table - CAN_CTRLR_BSP_API Structure#
Field | Description |
---|---|
.Open | Pointer to the BSP open function. |
.Close | Pointer to the BSP close function. |
.IntCtrl | Pointer to the BSP interrupt control function. |
.TmrCfg | Pointer to the BSP timer configure function. |
Listing - Example of BSP API Structure in the CAN Hardware Information page shows an example of a BSP API structure.
Listing - Example of BSP API Structure#
const CAN_CTRLR_DRV_INFO BSP_CAN0_BSP_DrvInfo = {
.BSP_API_Ptr = &CAN0_BSP_API,
.HW_Info.BaseAddr = (CPU_ADDR)CAN0,
.HW_Info.InfoExtPtr = DEF_NULL,
.HW_Info.IF_Rx = 1u,
.HW_Info.IF_Tx = 0u
};
Device Hardware Information#
The last step is to create the main device hardware information structure.
Table - CAN_CTRLR_DRV_INFO Structure in the CAN Hardware Information page describes each configuration field available in this structure.
Table - CAN_CTRLR_DRV_INFO Structure#
Field | Description |
---|---|
.HW_Info | Structure explained above in Hardware Driver Information . |
.BSP_API_Ptr | Pointer to the BSP API structure as described above in BSP API Structure . |
CAN Bus Controller Registration to the Platform Manager#
Once the hardware information structure for your CAN Bus controller is ready, it must be registered to the Platform Manager . This should typically be done from the BSP_OS_Init() function that is located in the file bsp_os.c.
There is a macro located in the file can_bus.h that you must call to register a CAN Bus controller. The macro is named CAN_CTRLR_REG().
Listing - Example of CAN Bus Controller Registration in the CAN Bus Controller Registration to the Platform Manager page shows an example of how to register a CAN Bus controller.
Listing - Example of CAN Bus Controller Registration#
#include <rtos_description.h>
#if defined(RTOS_MODULE_CAN_BUS_AVAIL)
#include <rtos/can/include/can_bus.h>
#endif
#if defined(RTOS_MODULE_CAN_BUS_AVAIL) (1)
BSP_HW_INFO_EXT(const CAN_CTRLR_DRV_INFO, BSP_CAN0_BSP_DrvInfo);
BSP_HW_INFO_EXT(const CAN_CTRLR_DRV_INFO, BSP_CAN1_BSP_DrvInfo);
#endif
void BSP_OS_Init (void)
{
/* ... */
/* ------- REGISTER CAN BUS CONTROLLERS ------ */
#if defined(RTOS_MODULE_CAN_BUS_AVAIL)
CAN_CTRLR_REG("can0", &BSP_CAN0_BSP_DrvInfo);
CAN_CTRLR_REG("can1", &BSP_CAN1_BSP_DrvInfo);
#endif
}
(1) Since the hardware information global variables are declared in another file, you must declare them as external in your bsp_os.c file. Always use the BSP_HW_INFO_EXT() macro.