/****************************************************************************
* **File:** csp/interfaces/csp_if_can.h
*
* **Description:** CAN interface
*
* CAN frames contains at most 8 bytes of data, so in order to transmit CSP
* packets larger than this, a fragmentation protocol is required.
* The CAN Fragmentation Protocol (CFP) is based on CAN2.0B, using all 29 bits
* of the identifier. The CAN identifier is divided into these fields:
*
* - Source: 5 bits
* - Destination: 5 bits
* - Type: 1 bit
* - Remain: 8 bits
* - Identifier: 10 bits
*
* The Source and Destination fields must match the source and destiantion addressses
* in the CSP packet. The Type field is used to distinguish the first and subsequent
* frames in a fragmented CSP packet. Type is BEGIN (0) for the first fragment and
* MORE (1) for all other fragments. The Remain field indicates number of remaining
* fragments, and must be decremented by one for each fragment sent. The identifier
* field serves the same purpose as in the Internet Protocol, and should be an auto
* incrementing integer to uniquely separate sessions.
*
* For networks configured as CSP version 2, the CAN identifier is divided into:
*
* - Priority: 2 bits
* - Destination: 14 bits
* - Sender id: 6 bits
* - Packet count: 2 bits
* - Frame count: 3 bits
* - Begin flag: 1 bit
* - End flag: 1 bit
*
* The \b Priority represents the CSP prio field. Placing this as the first bits in
* the transmission ensure that packets with high priority is priotized on the bus
* due to the nature of CAN arbitration.
* The \b Destination field represents the CSP node of the receiving node
* The \b Sender holds the least significant bits of the transmitting interface,
* i.e. the local address when a packet is forwarded by a routing instance.
* The \b Packet \b count is an incrementing value for every CSP packet
* The \b Frame \b count represents the frame fragment index for the particular packet
* The \b Begin \b flag is set for the first CAN frame in a CSP packet
* The \b End \b flag is set for the last CAN frame in a CSP packet
*
* In addition to the 29 bit extended CAN header, CSP utilize four bytes in the
* first CAN fragment in every CSP packet as:
*
* - Source: 14 bits
* - Dest port: 6 bits
* - Source port: 6 bits
* - CSP flags: 6 bits
* The \b Source holds the CSP node address of the origin of the CSP packet.
* The \b Dest and \Source \b port represents the port numbers for the transmission.
* The \b CSP \b flags holds the CSP_HEADER_FLAGS.
*
* Other CAN communication using a standard 11 bit identifier, can co-exist on the wire.
****************************************************************************/
#pragma once
#include <csp/csp_interface.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
@defgroup CFP_SIZE CAN message id field size.
@{
*/
[docs]/** Host - source/destination address. */
#define CFP_HOST_SIZE 5
[docs]/** Type - begin fragment or more fragments. */
#define CFP_TYPE_SIZE 1
[docs]/** Remaining fragments */
#define CFP_REMAIN_SIZE 8
[docs]/** CFP identification. */
#define CFP_ID_SIZE 10
/** @} */
/**
@defgroup CFP_FIELDS Macros for extracting fields from CAN message id.
@{
*/
[docs]/** Helper macro */
#define CFP_FIELD(id,rsiz,fsiz) ((uint32_t)((uint32_t)((id) >> (rsiz)) & (uint32_t)((1 << (fsiz)) - 1)))
[docs]/** Extract source address */
#define CFP_SRC(id) CFP_FIELD(id, CFP_HOST_SIZE + CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_HOST_SIZE)
[docs]/** Extract destination address */
#define CFP_DST(id) CFP_FIELD(id, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_HOST_SIZE)
[docs]/** Extract type (begin or more) */
#define CFP_TYPE(id) CFP_FIELD(id, CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_TYPE_SIZE)
[docs]/** Extract remaining fragments */
#define CFP_REMAIN(id) CFP_FIELD(id, CFP_ID_SIZE, CFP_REMAIN_SIZE)
[docs]/** Extract CFP identification */
#define CFP_ID(id) CFP_FIELD(id, 0, CFP_ID_SIZE)
/** @} */
/**
@defgroup CFP_MAKE Macros for building CAN message id.
@{
*/
[docs]/** Helper macro */
#define CFP_MAKE_FIELD(id,fsiz,rsiz) ((uint32_t)(((id) & (uint32_t)((uint32_t)(1 << (fsiz)) - 1)) << (rsiz)))
[docs]/** Make source */
#define CFP_MAKE_SRC(id) CFP_MAKE_FIELD(id, CFP_HOST_SIZE, CFP_HOST_SIZE + CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE)
[docs]/** Make destination */
#define CFP_MAKE_DST(id) CFP_MAKE_FIELD(id, CFP_HOST_SIZE, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE)
[docs]/** Make type */
#define CFP_MAKE_TYPE(id) CFP_MAKE_FIELD(id, CFP_TYPE_SIZE, CFP_REMAIN_SIZE + CFP_ID_SIZE)
[docs]/** Make remaining fragments */
#define CFP_MAKE_REMAIN(id) CFP_MAKE_FIELD(id, CFP_REMAIN_SIZE, CFP_ID_SIZE)
[docs]/** Make CFP id */
#define CFP_MAKE_ID(id) CFP_MAKE_FIELD(id, CFP_ID_SIZE, 0)
/** @} */
[docs]/** Mask to uniquely separate connections */
#define CFP_ID_CONN_MASK (CFP_MAKE_SRC((uint32_t)(1 << CFP_HOST_SIZE) - 1) | \
CFP_MAKE_DST((uint32_t)(1 << CFP_HOST_SIZE) - 1) | \
CFP_MAKE_ID((uint32_t)(1 << CFP_ID_SIZE) - 1))
#define CFP2_PRIO_MASK 0x3
#define CFP2_PRIO_OFFSET 27
#define CFP2_DST_SIZE 14
#define CFP2_DST_MASK 0x3FFF
#define CFP2_DST_OFFSET 13
#define CFP2_SENDER_SIZE 6
#define CFP2_SENDER_MASK 0x3F
#define CFP2_SENDER_OFFSET 7
#define CFP2_SC_MASK 0x3
#define CFP2_SC_OFFSET 5
#define CFP2_FC_MASK 0x7
#define CFP2_FC_OFFSET 2
#define CFP2_BEGIN_MASK 0x1
#define CFP2_BEGIN_OFFSET 1
#define CFP2_END_MASK 0x1
#define CFP2_END_OFFSET 0
#define CFP2_SRC_SIZE 14
#define CFP2_SRC_MASK 0x3FFF
#define CFP2_SRC_OFFSET 18
#define CFP2_DPORT_MASK 0x3F
#define CFP2_DPORT_OFFSET 12
#define CFP2_SPORT_MASK 0x3F
#define CFP2_SPORT_OFFSET 6
#define CFP2_FLAGS_MASK 0x3F
#define CFP2_FLAGS_OFFSET 0
[docs]/**
* Fields used to uniquely define a CSP packet within each fragment header
*/
#define CFP2_ID_CONN_MASK ((CFP2_DST_MASK << CFP2_DST_OFFSET) | \
(CFP2_SENDER_MASK << CFP2_SENDER_OFFSET) | \
(CFP2_PRIO_MASK << CFP2_PRIO_OFFSET) | \
(CFP2_SC_MASK << CFP2_SC_OFFSET))
[docs]/**
* Default interface name.
*/
#define CSP_IF_CAN_DEFAULT_NAME "CAN"
/**
* Send CAN frame (implemented by driver).
*
* Used by csp_can_tx() to send CAN frames.
*
* @param[in] driver_data driver data from #csp_iface_t
* @param[in] id CAM message id.
* @param[in] data CAN data
* @param[in] dlc data length of \a data.
* @return #CSP_ERR_NONE on success, otherwise an error code.
*/
typedef int (*csp_can_driver_tx_t)(void * driver_data, uint32_t id, const uint8_t * data, uint8_t dlc);
[docs]/**
* Interface data (state information).
*/
typedef struct {
[docs] uint32_t cfp_packet_counter; /**< CFP Identification number - same number on all fragments from same CSP packet. */
[docs] csp_can_driver_tx_t tx_func; /**< Tx function */
[docs] csp_packet_t * pbufs; /**< PBUF queue */
} csp_can_interface_data_t;
[docs]/**
* Add interface.
*
* @param[in] iface CSP interface, initialized with name and inteface_data
* pointing to a valid #csp_can_interface_data_t structure.
* @return #CSP_ERR_NONE on success, otherwise an error code.
*/
int csp_can_add_interface(csp_iface_t * iface);
/**
* Remove interface.
*
* @param[in] iface CSP interface to be removed.
*
* @return #CSP_ERR_NONE on success, otherwise an error code.
*/
int csp_can_remove_interface(csp_iface_t * iface);
[docs]/**
* Send CSP packet over CAN (nexthop).
*
* This function will split the CSP packet into several fragments and call
* csp_can_tx_fram() for sending each fragment.
*
* @param[in] iface CSP interface
* @param[in] via
* @param[in] packet CSP packet
* @return #CSP_ERR_NONE on success, otherwise an error code.
*/
int csp_can_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet);
[docs]/**
* Process received CAN frame.
*
* Called from driver when a single CAN frame (up to 8 bytes) has been received.
* The function will gather the fragments into a single
* CSP packet and route it on when complete.
*
* @param[in] iface incoming interface.
* @param[in] id received CAN message identifier.
* @param[in] data received CAN data.
* @param[in] dlc length of received \a data.
* @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
* @return #CSP_ERR_NONE on success, otherwise an error code.
*/
int csp_can_rx(csp_iface_t * iface, uint32_t id, const uint8_t * data, uint8_t dlc, int *pxTaskWoken);
#ifdef __cplusplus
}
#endif