...
There is an available target adaption with the STM32H743x and example projects for the IDE Atollic TrueSTUDIO (based on GCC).
General layers model:
...
Application / Example
...
port CANopen Library
...
Vendor HAL-Layer
...
CAN-HW /Controller
...
port CANopen Driver - Generic-CANHAL
...
CANHAL
...
...
CAN-HW /Controller
...
Vendor HAL-Layer
Notes to the layers:
Layer name | Who takes care of the implementation | Description |
Application/ Example | Customer | User application The delivery from port includes several example applications (e.g. s1, s2).
|
port CANopen Library | Separate delivery from port (source folder: canopen)
| HW independent CANopen Library from port |
port CANopenDriver / Generic-CANHAL | Delivery from port (source folders: “drivers/co_generic”, ”drivers/shar_src”, “drivers/shar_inc”) | General connection layer between CANopen Library and target based on the CAN abstraction layer This layer includes the usual driver API for a CANopen application additionally with necessary CPU/board initializations.
|
port CANopenDriver / CANHAL | Delivery from port (sources: “drivers/canhal/canhal.[c,h]”) | Generic fixed CAN API called by the new CANopen Generic driver. |
port CANopenDriver /
CAN Target Adaption | Customer (port provides the API functions as template). Delivery from port (sources: “drivers/canhal/cantarget.[c,h]”)
| Specific implementation of the API for the target. The code contains additional "Todo’s" to help. |
Vendor HAL-Layer | Supplier of the HAL-Layer, normally the CPU- manufacturer | The Vendor HAL-Layer allows the access to the CAN controller via HAL-Layer functions, e.g. STM32CubeH7 - HAL-layer. But it is also possible to access directly to the CAN controller registers without Vendor HAL-Layer. |
CAN-HW /Controller | HW (CPU, CAN-interface manufacturer) | Possible are also external CAN interfaces.
|
Supported features with the current CAN abstraction layer implementing:
...
Bare metall (without any operating system support)
Folder sructure of driver package “Generic-CANHAL” :
...
Folder structure with comments (sources of the second delivery part marked here in blue):
-:/
--- |-- canopen canopen (CANopen Library, not part from this driver deliverys)
...
| |
| |-- co_generic generic (CPU/Board adaption folder (not CAN), in generic without HW-access)
| |-- co_stm32H7xx stm32H7xx (CPU/Board adaption folder (not CAN), with STM32H7xx HW-access)
...
| |-- co_canhal
| | |-- co_canhal.c,.h (CAN abstraction layer API - CANHAL)
| | |-- co_cantarget.c,.h (CAN abstraction layer API – target adaption template)
| | |-- co_cantartget_stm32h7xx.c,.h (CAN abstraction layer API – target adaption on STM32H743x)
| |
| |-- shar_inc (shared driver includes)
| | |-- can_generic_canhal.h (internal access to the CAN abstraction layer API)
| | |-- cpu_generic.h
| | |-- …
| | |-- cpu_stm32_h7.h (CPU porting to STM32H7xx)
| |
| |-- shar_src src (shared driver sources, especially timer service part)
| |-- can_generic_canhal.c (internal access to the CAN abstraction layer API)
| |-- cpu_generic.c
| |-- …
| |-- cpu_stm32_h7.c (CPU porting to STM32H7xx)
|
--- |-- examples examples (example projects generated by the IDE Atollic TrueSTUDIO)
|-- s1_canhal_generic (generic slave single-line example)
|-- s4_canhal_generic (generic slave multi-line example)
...
|-- s4_canhal_stm32H7xx (slave single-line example ported on STM32H7xx)
If the customer wants to develop his own driver, he can use the generic sources as a template. The sources marked in blue for the STM32H7xx can used as a reference for the own development. These must be adapted or created for a new target.
Short API description of the target adaptation layer functions to be implemented:
(file cantarget.[c,.h]):
Code Block | ||
---|---|---|
| ||
/****************************************************************************/ |
...
/* prototypes */ |
...
/****************************************************************************/ |
...
/****************************************************************************/ |
...
/** Initialize target CAN board peripherals |
...
* |
...
This function sets up the target board for used CAN lines |
...
(e.g. CAN clock, CAN pins). |
...
May not be necessary if this has already been done elsewhere in the project. |
...
* |
...
\return CO_OK - success |
...
\return others - fail |
...
*/ |
...
RET_T coCAN_targetCanBoardInit( |
...
void |
...
); |
...
/****************************************************************************/ |
...
/** Initialize CAN peripherals |
...
* |
...
This function sets up the target CAN interface. |
...
* |
...
\return CO_OK - success |
...
\return others - fail |
...
*/ |
...
RET_T coCAN_targetCanInit( |
...
UNSIGNED8 canLine /**< [in] number of CAN line */ |
...
); |
...
/****************************************************************************/ |
...
/** Get CAN filter max. |
...
* |
...
This function gets the maximal possible filter count. |
...
We need 1 filter for every receive message ID to be received. |
...
Max. value = 0 means filtering not supported - BasicCAN mode. |
...
* |
...
\return filter_count |
...
*/ |
...
UNSIGNED32 coCAN_targetCanGetFilterMax( |
...
UNSIGNED8 canLine /**< [in] number of CAN line */ |
...
); |
...
/****************************************************************************/ |
...
/** Start CAN interface |
...
* |
...
This function starts the target CAN with a given line number. |
...
* |
...
\return CO_OK - success |
...
\return others - fail |
...
*/ |
...
RET_T coCAN_targetCanStart( |
...
UNSIGNED8 canLine /**< [in] number of CAN line */ |
...
); |
...
/****************************************************************************/ |
...
/** Stop CAN interface |
...
* |
...
This function stops the target CAN with a given line number. |
...
After this stop command the CAN interface is still initialized, |
...
but transmit or receive operations are not possible. |
...
* |
...
\return CO_OK - success |
...
\return others - fail |
...
*/ |
...
RET_T coCAN_targetCanStop( |
...
UNSIGNED8 canLine /**< [in] number of CAN line */ |
...
); |
...
/****************************************************************************/ |
...
/** CAN target driver set receive filter |
...
* |
...
CAN target driver set receive filter function. |
...
This function is required if FullCAN is to be implemented. |
...
If function is not implemented only BasicCAN (all messages are received) |
...
is available. |
...
* |
...
\return CAN_OK - success |
...
\return others - fail |
...
*/ |
...
RET_T coCAN_targetCanSetFilter( |
...
UNSIGNED8 canLine, /**< [in] number of CAN line */ |
...
CO_CAN_FILTER_T filter /**< [in] filter struct */ |
...
); |
...
/****************************************************************************/ |
...
/** Set bitrate to CAN peripheries |
...
* |
...
This function sets up the CAN |
...
bit rate in the target CAN. |
...
* |
...
\return CO_OK - success |
...
\return others - fail (bitrate not supported) |
...
*/ |
...
RET_T coCAN_targetCanSetBitrate( |
...
UNSIGNED8 canLine, /**< [in] number of CAN line */ |
...
UNSIGNED32 bitrateindex /**< [in] index for the desired CAN bit rate |
...
from bit timing table 0 according to CiA-305 */ |
...
); |
...
/****************************************************************************/ |
...
/** CAN driver send |
...
* |
...
CAN driver send function. |
...
* |
...
\return CO_OK - success |
...
\return others - fail |
...
*/ |
...
RET_T coCAN_targetCanSend( |
...
UNSIGNED8 canLine, /**< [in] number of CAN line */ |
...
CO_CANHAL_MSG_T *p_can_msg /**< [in] CAN message for transmission */ |
...
); |
...
/****************************************************************************/ |
...
/** CAN target driver interrupt handler |
...
* |
...
This function handles the CAN interrupt(s) for RX messages, TX message done, |
...
CAN controller state changed. |
...
Usually we are using the same handler function for every CAN interrupt. |
...
The callback function coCANHAL_targetCanDriverCallback() of the CANHAL layer |
...
must be called for every event. |
...
* |
...
\return nothing |
...
*/ |
...
void coCAN_targetCanInterrupt( |
...
UNSIGNED8 canLine /**< [in] number of CAN line */ |
...
); |
...
The received data or status events received in the interrupt handler must be transferred to the CANHAL via the following callback: |
...
/* prototype for the callback function of CANHAL layer, |
...
which shall be called by the interrupt handler */ |
...
void coCANHAL_targetCanDriverCallback( |
...
UNSIGNED8 canLine, /**< [in] number of CAN line */ |
...
CO_CAN_EVENT_T event, /**< [in] trigger event for interrupt */ |
...
CO_CANHAL_MSG_T *pData); /**< [in] received data */ |
...
Some examples for calling the callback functions:
/* callback function to upper layer with receive message data */
Some examples for calling the callback functions: /* callback function to upper layer with receive message data */ coCANHAL_targetCanDriverCallback(canLine, CO_CAN_EVENT_RX, &can_msg); |
...
/* callback function to upper layer, TX message done */ |
...
coCANHAL_targetCanDriverCallback(canLine, CO_CAN_EVENT_TXC, NULL); |
...
/* callback function to upper layer, ERR_PASSIV occurred */ |
...
coCANHAL_targetCanDriverCallback(canLine, CO_CAN_EVENT_ERR_PASSIVE, NULL); |
...
/* callback function to upper layer, CAN overrun occurred */ |
...
coCANHAL_targetCanDriverCallback(canLine, CO_CAN_EVENT_ERR_OVERRUN, NULL); |
...
Used data types and parameters for implementing the target layer API:
Used data types and parameters for implementing the target layer API: /**< CAN bit rate */ |
...
/* These index values shall be used for argument bitrateindex for function |
...
coCAN_targetCanSetBitrate(). */ |
...
#define CO_CAN_BAUDRATE_UNKNOWN 0xFFu |
...
#define CO_CAN_BAUDRATE_10 0x00u |
...
#define CO_CAN_BAUDRATE_20 0x01u |
...
#define CO_CAN_BAUDRATE_50 0x02u |
...
#define CO_CAN_BAUDRATE_100 0x03u |
...
#define CO_CAN_BAUDRATE_125 0x04u |
...
#define CO_CAN_BAUDRATE_250 0x05u |
...
#define CO_CAN_BAUDRATE_500 0x06u |
...
#define CO_CAN_BAUDRATE_800 0x07u |
...
#define CO_CAN_BAUDRATE_1000 0x08u |
...
#define CO_CAN_BAUDRATE_INDEX CO_CAN_BAUDRATE_125 /* default used 125 kbit/s */ |
...
/****************************************************************************/ |
...
/* enums */ |
...
/****************************************************************************/ |
...
/**< CAN event */ |
...
typedef enum { |
...
CO_CAN_EVENT_RX = 0, /**< message received */ |
...
CO_CAN_EVENT_TXC, /**< message transmitted */ |
...
CO_CAN_EVENT_ERR_BUSOFF, /**< bus is off */ |
...
CO_CAN_EVENT_ERR_PASSIVE, /**< no acknowledge */ |
...
CO_CAN_EVENT_ERR_ACTIVE, /**< bus ok */ |
...
CO_CAN_EVENT_ERR_ |
...
OVERRUN /**< received message lost */ |
...
} CO_CAN_EVENT_T; |
...
/****************************************************************************/ |
...
/* structures */ |
...
/****************************************************************************/ |
...
/**< CAN message buffer */ |
...
typedef struct { |
...
UNSIGNED32 messageID; /**< message identifier */ |
...
BOOL_T rtrFlag; /**< Remote Transmission requested */ |
...
BOOL_T extendedFlag; /**< extended identifier */ |
...
UNSIGNED8 canLine; /**< number of line */ |
...
UNSIGNED8 dataLen; /**< length of data in byte */ |
...
UNSIGNED8 data[CO_CAN_DATA_LEN]; /**< message data */ |
...
} CO_CANHAL_MSG_T; |
...
/**< CAN Filter type */ |
...
typedef struct { |
...
UNSIGNED32 messageID; /**< filtered message identifier */ |
...
BOOL_T rtrFlag; /**< filter RTR frames */ |
...
BOOL_T extendedFlag; /**< filter frames with extended identifier */ |
...
UNSIGNED8 canLine; /**< number of CAN line */ |
...
} CO_CAN_FILTER_T; |
...
...
...