can.h File Reference
#include <stdint.h>
#include <stdbool.h>
Include dependency graph for can.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

union  can_data_t
 
struct  __attribute__
 
struct  __attribute__
 
struct  __attribute__
 
struct  can_std_grp_id_t
 
struct  __attribute__
 
struct  can_ext_grp_id_t
 

Typedefs

typedef void(* can_void_func_t) (uint32_t)
 

Enumerations

enum  can_t { can1, can2, can_max }
 The CAN BUS type. More...
 

Functions

bool CAN_init (can_t can, uint32_t baudrate_kbps, uint16_t rxq_size, uint16_t txq_size, can_void_func_t bus_off_cb, can_void_func_t data_ovr_cb)
 
bool CAN_rx (can_t can, can_msg_t *msg, uint32_t timeout_ms)
 
bool CAN_tx (can_t can, can_msg_t *msg, uint32_t timeout_ms)
 
uint16_t CAN_get_rx_dropped_count (can_t can)
 
void CAN_bypass_filter_accept_all_msgs (void)
 
bool CAN_fullcan_add_entry (can_t can, can_std_id_t id1, can_std_id_t id2)
 
can_fullcan_msg_t * CAN_fullcan_get_entry_ptr (can_std_id_t fc_id)
 
bool CAN_fullcan_read_msg_copy (can_fullcan_msg_t *fc_msg_ptr, can_fullcan_msg_t *msg_copy_ptr)
 
uint8_t CAN_fullcan_get_num_entries (void)
 
bool CAN_setup_filter (const can_std_id_t *std_id_list, uint16_t sid_cnt, const can_std_grp_id_t *std_group_id_list, uint16_t sgp_cnt, const can_ext_id_t *ext_id_list, uint16_t eid_cnt, const can_ext_grp_id_t *ext_group_id_list, uint16_t egp_cnt)
 
bool CAN_is_bus_off (can_t can)
 
void CAN_reset_bus (can_t can)
 
uint16_t CAN_get_rx_watermark (can_t can)
 RX FreeRTOS Queue watermark. More...
 
uint16_t CAN_get_tx_watermark (can_t can)
 TX FreeRTOS Queue watermark. More...
 
uint16_t CAN_get_tx_count (can_t can)
 Number of messages written to the CAN HW. More...
 
uint16_t CAN_get_rx_count (can_t can)
 Number of messages successfully queued from CAN interrupt (not including dropped) More...
 
can_std_id_t CAN_gen_sid (can_t can, uint16_t id)
 
can_ext_id_t CAN_gen_eid (can_t can, uint32_t id)
 

Detailed Description

This is a simple CAN driver that optionally utilizes the FullCAN capability. FullCAN is hardware filtering of the CAN messages and the configured messages are stored directly into the CAN RAM (separate 2K RAM) without CPU intervention.

FullCAN feature summary :

  • Messages go straight into dedicated RAM, SW never needs to be interrupted
  • Each FullCAN entry can generate an interrupt (up to 64 messages)
  • FullCAN entry can only be 11-bit NOT 29-bit type.
  • Note that FullCAN is for BOTH CANs. If you wish to have separate message reads of individual CANs, you can enable non FullCAN filters because the implementation provides queues of separate CAN channels.

When the CAN bus is initialized, we initially configure it to not accept any messages until filtering or bypass option is used. For the filtering, in addition to the FullCAN, you can configure explicit 11-bit and 29-bit IDs (including groups) and only these messages will be accepted.

Note that if you send a message, and no other node acknowledges the message sent, then the CAN BUS may enter "Bus off" state due to error(s). You must correct this situation and reset the CAN BUS.

Typedef Documentation

typedef void(* can_void_func_t) (uint32_t)

CAN function pointer type The 32-bit parameter is the value of the ICR register of CANbus

Enumeration Type Documentation

enum can_t

The CAN BUS type.

Enumerator
can1 

CAN #1.

can2 

CAN #2.

can_max 

Do not use or change.

Function Documentation

void CAN_bypass_filter_accept_all_msgs ( void  )

Enables CAN bypass mode to accept all messages on the bus. Either CAN filters need to be setup or this method should be called to accept CAN messages otherwise no messages will be capture at the CAN HW registers.

Note
The filter is for BOTH CANs
bool CAN_fullcan_add_entry ( can_t  can,
can_std_id_t  id1,
can_std_id_t  id2 
)

Adds two FullCAN entries to the acceptance filter and enables the FullCAN reception. The entries must be added in groups of 2. If the second entry is not needed, simply pass 0xFFFF to CAN_gen_sid() to generate a disabled entry.

Returns
true if successful.
Note
Only 11-bit IDs can use FullCAN.
Warning
This must be done BEFORE setting up other filters using CAN_setup_filter()
CAN BUS should not be enabled to do this because the CAN Filter is put to OFF mode while the entry is added.
Note
TO DO: Enabling fc_intr bit (FullCAN interrupts) is not yet supported
can_fullcan_msg_t* CAN_fullcan_get_entry_ptr ( can_std_id_t  fc_id)

Once all the FulLCAN entries are added, and CAN filters are setup, you can get the pointer in memory where the actual CAN message (FullCAN entry) is stored in memory.

Parameters
fc_idThe FullCAN entry originally passed to CAN_fullcan_add_entry()
uint8_t CAN_fullcan_get_num_entries ( void  )
Returns
the number of FullCAN entries being used
bool CAN_fullcan_read_msg_copy ( can_fullcan_msg_t *  fc_msg_ptr,
can_fullcan_msg_t *  msg_copy_ptr 
)

FullCAN entries may update at any time by the HW, so this method provides a means to safely read the copy of the FullCAN message.

Parameters
msg_copy_ptrThe same message returned from CAN_fullcan_get_entry_ptr()
fc_msg_ptrThe copy of the message you wish to read the data to
Returns
true if a NEW message has been captured since the last call to this method. false if HW did not receive a new message
can_ext_id_t CAN_gen_eid ( can_t  can,
uint32_t  id 
)
can_std_id_t CAN_gen_sid ( can_t  can,
uint16_t  id 
)

Generate and return the ID used to create the standard and extended id list member.

See also
CAN_setup_filter()

To generate a disabled slot, just pass 0xFFFF (id) as the message id, which will disable the message. This is used to generate an empty slot to make an even number of entries as required by the standard id filter.

uint16_t CAN_get_rx_count ( can_t  can)

Number of messages successfully queued from CAN interrupt (not including dropped)

uint16_t CAN_get_rx_dropped_count ( can_t  can)
Returns
The number of CAN messages dropped Messages can be dropped out either if the receive queue is too small, or if there is no consumer or task that dequeues the received messages quickly enough from the CAN_rx() API
uint16_t CAN_get_rx_watermark ( can_t  can)

RX FreeRTOS Queue watermark.

Watermark and counter API

uint16_t CAN_get_tx_count ( can_t  can)

Number of messages written to the CAN HW.

uint16_t CAN_get_tx_watermark ( can_t  can)

TX FreeRTOS Queue watermark.

bool CAN_init ( can_t  can,
uint32_t  baudrate_kbps,
uint16_t  rxq_size,
uint16_t  txq_size,
can_void_func_t  bus_off_cb,
can_void_func_t  data_ovr_cb 
)

Initializes the CAN controller with the given baud-rate.

Warning
This leaves the CAN BUS DISABLED!!! The next steps are :
  • Optionally, configure the FullCAN.
See also
CAN_fullcan_add_entry()
  • Optionally, configure CAN filters.
CAN_setup_filter()
Parameters
canThe can bus type.
See also
can_t
Parameters
baudrate_kbpsThe CAN Bus baud-rate, such as 100, 250, 500, 1000 Precise, external crystal should be used for higher than 100kbps
rxq_sizeThe size of the received messages queue
txq_sizeThe size of the transmit messages queue
bus_off_cbThe callback function when CAN BUS enters BUS error state
data_ovr_cbThe callback function when CAN BUS encounters data-overrun
Note
Both bus_off_cb and data_ovr_cb are optional. BUS overrun callback should be used because if user doesn't correct this, the CAN BUS will never recover once the BUS error state is entered.
Each CAN BUS has separate receive and transmit queues
Postcondition
The CAN bus is initialized, and by default, no messages are accepted until CAN filter is setup, and CAN_reset_bus() is called.

About the AFMR register : B0 B1 Filter Mode | AccOff bit | AccBP bit | CAN Rx interrupt Off Mode 1 0 No messages accepted Bypass Mode X 1 All messages accepted FullCAN 0 0 HW acceptance filtering

bool CAN_is_bus_off ( can_t  can)

CAN Bus Error and Reset API If the CAN BUS encounters error(s), it may turn off, in which case no more transmissions will take place. This must be corrected by the user.

void CAN_reset_bus ( can_t  can)
bool CAN_rx ( can_t  can,
can_msg_t *  msg,
uint32_t  timeout_ms 
)

Receive a message of the given CAN BUS.

Parameters
canThe can bus type.
See also
can_t
Parameters
msgThe CAN message
timeout_msIf FreeRTOS is running, the task will block until a message arrives. Otherwise we will poll and wait this timeout to receive a message.
Returns
true if message was captured within the given timeout.
bool CAN_setup_filter ( const can_std_id_t *  std_id_list,
uint16_t  sid_cnt,
const can_std_grp_id_t std_group_id_list,
uint16_t  sgp_cnt,
const can_ext_id_t *  ext_id_list,
uint16_t  eid_cnt,
const can_ext_grp_id_t ext_group_id_list,
uint16_t  egp_cnt 
)

Enable CAN filter for BOTH CANs; hardware doesn't allow to enable for just ONE CAN controller.

Parameters
std_id_listList of 11-bit IDs to generate an ACK for (can be NULL)
sid_cntThe size of the can_std_id_t array
std_group_id_listList of 11-bit ID groups to generate an ACK for (can be NULL)
sgp_cntThe size of the can_std_grp_id_t array
ext_id_listList of 29-bit IDs to generate an ACK for (can be NULL)
eid_cntThe size of the can_ext_id_t array
ext_group_id_listList of 29-bit ID groups to generate an ACK for (can be NULL)
egp_cntThe size of the can_ext_grp_id_t array
Warning
The list must be in ASCENDING order (lowest first, then highest). The hardware carries out its search taking for granted that the IDs are ordered from lowest to highest. If filters are wrong, CAN ISR will enter a loop and your board will restart (due to watchdog).
CAN BUS should not be enabled to do this because the CAN Filter is put to OFF mode while the entry is added.
Note
The CAN filter must be setup after the CAN controller(s) is initialized.
The size entries is limited to 2K bytes. Each entry size in bytes is :

Here is sample code that enables HW filtering of selected CAN messages. Note that some messages are for CAN2 while most are for CAN1

1 const can_std_id_t slist[] = { CAN_gen_sid(can1, 0x100), CAN_gen_sid(can1, 0x110), // 2 entries
2  CAN_gen_sid(can1, 0x120), CAN_gen_sid(can1, 0x130) // 2 entries
3  };
4 const can_std_grp_id_t sglist[] = { {CAN_gen_sid(can1, 0x150), CAN_gen_sid(can1, 0x200)}, // Group 1
5  {CAN_gen_sid(can2, 0x300), CAN_gen_sid(can2, 0x400)} // Group 2
6  };
7 const can_ext_id_t *elist = NULL; // Not used, so set it to NULL
8 const can_ext_grp_id_t eglist[] = { {CAN_gen_eid(can1, 0x3500), CAN_gen_eid(can1, 0x4500)} }; // Group 1
9 
10 CAN_setup_filter(slist, 4, sglist, 2,
11  elist, 0, eglist, 1);

Standard ID list and group list need to swapped otherwise setting the wrong filter will make the CAN ISR go into a loop for no apparent reason. It looks like the filter data is motorolla big-endian format. See "configuration example 5" in CAN chapter.

bool CAN_tx ( can_t  can,
can_msg_t *  msg,
uint32_t  timeout_ms 
)

Send a CAN message over the CAN BUS

Parameters
canThe can bus type.
See also
can_t
Parameters
msgThe CAN message
timeout_msIf FreeRTOS is running, the task will block for timeout_ms if HW buffers and the transmit queue is full. If FreeRTOS is not running the timeout is simply, ignored, and false is returned if all three HW buffers are full.

The transmit queue is only used if all three buffers of the CAN hardware are busy, in which case, the transmission complete interrupt will later send the queued msg.

Returns
If CAN message was either sent, or queued, true is returned. If all the hardware buffers are full, and the queue is full, then false is returned if timeout occurs waiting for the queue to empty.
1 can_msg_t msg;
2 msg.msg_id = 0x123;
3 msg.frame_fields.is_29bit = 1;
4 msg.frame_fields.data_len = 8; // Send 8 bytes
5 msg.data.qword = 0x1122334455667788; // Write all 8 bytes of data at once
6 CAN_tx(can_1, &msg, portMAX_DELAY);