CANBus Driver#
The CANbus driver is responsible for all incoming and outgoing CAN communication on both CAN lines. The driver knows of more than a dozen different CAN messages it can send or receive, and can automatically determine their size and data type. The interface presented by the driver is as follows:
ErrorStatus CANbus_Init(CAN_t bus)— Initialize the canbus given by thebusargument. The options areMOTORCANandCARCAN.ErrorStatus CANbus_Send(CANDATA_t CanData, bool blocking, CAN_t bus)— Send The givenCANDATAstructure tobus. Ifblockingis true, the call blocks until the message can be deposited in a vacant CAN mailbox. Else, the function will return an error if no mailbox is vacant.ErrorStatus CANbus_Read(CANDATA_t* data, bool blocking, CAN_t bus)— Read a CAN message frombusinto the given data structure. Ifblockingis true, wait until a CAN message is available to be read. Else, the function will return an error if no message is ready to be read.
Data Types#
CAN messages are sent from and received into CANDATA_t, which contains the CAN ID, idx byte, and up to 8 data bytes.
Internally, the driver also uses the CANLUT_T type, which is the entry type of a lookup table used to determine the data types used by incoming messages.
This lookup table can also be used to determine the length of incoming messages if it is needed.
See CANbus.h and CANLUT.c for details.
Implementation Details#
The microcontroller’s CAN hardware block includes three sending and three receiving mailboxes, which act as a small queue of CAN messages. The driver will write directly to the write mailboxes as long as they aren’t full, and will block otherwise.
The receive mailboxes are constantly emptied (by the CAN receive interrupt) into a software queue in the BSP layer in order to deepen the queue (we receive a lot of messages). When reading, the driver will read directly from a software queue in the BSP layer. A non-blocking read will return an error if the queue is empty. A blocking read will block on a driver-layer semaphore, to be woken up when data is avilable. Everytime the BSP software queue is posted to, a receive interrupt signals to a driver-layer semaphore that a message has been received. This allows any waiting tasks to wake up and read the message. This is done since tasks that read and write CAN messages don’t usually have anything else to do while waiting, which makes blocking fairly efficient.
- group CANbus
Defines
-
CARCAN CAN_1#
-
MOTORCAN CAN_3#
-
CAN_BLOCKING true#
Standard identifier for whether or not a CAN transaction is blocking or not (DEPRECATED)
-
CAN_NON_BLOCKING false#
Enums
-
enum CANId_t#
This enum is used to signify the ID of the message you want to send. It is used internally to index our lookup table (CANLUT.C) and get message-specific fields. For user purposes, it selects the message to send.
If changing the order of this enum, make sure to mirror that change in the lookup table, or else the driver will not work properly.
If adding new types of CAN messages, add the identifier wherever it fits in (the enum is sorted in ascending order on purpose), and then add an entry to the lookup table.
Values:
-
enumerator BPS_TRIP#
-
enumerator BPS_CONTACTOR#
-
enumerator CURRENT_DATA#
-
enumerator STATE_OF_CHARGE#
-
enumerator SUPPLEMENTAL_VOLTAGE#
-
enumerator VOLTAGE_SUMMARY#
-
enumerator TEMPERATURE_SUMMARY#
-
enumerator MOTOR_DRIVE#
-
enumerator MOTOR_POWER#
-
enumerator MOTOR_RESET#
-
enumerator MOTOR_STATUS#
-
enumerator MC_BUS#
-
enumerator VELOCITY#
-
enumerator MC_PHASE_CURRENT#
-
enumerator VOLTAGE_VEC#
-
enumerator CURRENT_VEC#
-
enumerator BACKEMF#
-
enumerator TEMPERATURE#
-
enumerator ODOMETER_AMPHOURS#
-
enumerator ARRAY_CONTACTOR_STATE_CHANGE#
-
enumerator SLIP_SPEED#
-
enumerator CONTROL_MODE#
-
enumerator IO_STATE#
-
enumerator MAX_CAN_ID#
-
enumerator BPS_TRIP#
Functions
-
ErrorStatus CANbus_Init(CAN_t bus, CANId_t *idWhitelist, uint8_t idWhitelistSize)#
Initializes the CAN system for a given bus.
- Parameters:
bus – The bus to initialize. You can either use CAN_1, CAN_3, or the convenience macros CARCAN and MOTORCAN. CAN2 will not be supported.
idWhitelist – A list of CAN IDs that we want to receive. If NULL, we will receive all messages.
idWhitelistSize – The size of the whitelist.
- Returns:
ERROR if bus != CAN1 or CAN3, SUCCESS otherwise
-
ErrorStatus CANbus_Send(CANDATA_t CanData, bool blocking, CAN_t bus)#
Transmits data onto the CANbus. Transmits up to 8 bytes at a time. If more is necessary, please use an IDX message.
- Parameters:
CanData – The data to be transmitted
blocking – Whether or not this transmission should be a blocking send.
bus – The bus to transmit on. This should be either CARCAN or MOTORCAN.
- Returns:
ERROR if data wasn’t sent, otherwise it was sent.
-
ErrorStatus CANbus_Read(CANDATA_t *data, bool blocking, CAN_t bus)#
Reads a CAN message from the CAN hardware and returns it to the provided pointers.
- Parameters:
data – pointer to where to store the CAN id of the received msg
blocking – Whether or not this read should be a blocking read
bus – The bus to use. This should either be CARCAN or MOTORCAN.
- Returns:
ERROR if read failed, SUCCESS otherwise
-
struct CANLUT_T#
- #include <CANbus.h>
Struct to use in CAN MSG LUT.
- Param idxEn:
Whether or not this message is part of a sequence of messages.
- Param size:
Size of message’s data. Should be a maximum of eight (in decimal).
-
struct CANDATA_t#
- #include <CANbus.h>
Standard CAN packet
- Param ID:
CANId_t value indicating which message we are trying to send
- Param idx:
If message is part of a sequence of messages (for messages longer than 64 bits), this indicates the index of the message. This is not designed to exceed the 8bit unsigned max value.
- Param data:
data of the message
-
CARCAN CAN_1#