/* * Author: Jon Trulson * Copyright (c) 2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include #include #include #include #include #include #include #include "mcp2515_regs.h" #ifdef __cplusplus extern "C" { #endif /** * @file mcp2515 * @library mcp2515 * @brief C API for the MCP2515 CAN bus controller * * @include mcp2515.c * @include mcp2515_regs.c */ /** * Device context */ typedef struct _mcp2515_context { mraa_spi_context spi; // CS pin, if we are using one mraa_gpio_context gpio; // interrupt, if enabled mraa_gpio_context intr; } *mcp2515_context; /** * MCP2515 initializer * * @param bus spi bus to use * @param cs_pin The GPIO pin to use for Chip Select (CS). Pass * pass -1 if your CS is handled automatically by your SPI * implementation (Edison). * @return an initialized device context on success, NULL on error. */ mcp2515_context mcp2515_init(int bus, int cs_pin); /** * MCP2515 close * * @param dev Device context. */ void mcp2515_close(mcp2515_context dev); /** * Reset the device. * * @param dev Device context. * @return UPM result. */ upm_result_t mcp2515_reset(const mcp2515_context dev); /** * Set the operating mode of the device. After initialization * (mcp2515_init()), the device mode will be set to NORMAL. Note * that some operations require the device to be placed into CONFIG * mode. This function will wait until the selected mode has been * entered. * * @param dev Device context. * @param opmode One of the MCP2515_OPMODE_T values. * @return UPM result. */ upm_result_t mcp2515_set_opmode(const mcp2515_context dev, MCP2515_OPMODE_T opmode); /** * Set the baud rate of the CAN bus. All devices on a given CAN * bus must be operating at the correct speed. The device must be * switched into CONFIG mode bofore this function will have any * effect. On initialization (mcp2515_init()), the default CAN * bus speed will be set to 50Kbps. * * @param dev Device context. * @param speed One of the MCP2515_SPEED_T values. * @return UPM result. */ upm_result_t mcp2515_set_speed(const mcp2515_context dev, MCP2515_SPEED_T speed); /** * Load a transmit buffer with the id, payload, and other * information. This function does not actually transmit the * buffer. There are 3 TX buffers available. The buffer must be * free (ie: not awaiting transmit) before it can be loaded. Once * a TX buffer has been successfully loaded, it can be transmitted * with the mcp2515_transmit_buffer() function. * * @param dev Device context. * @param bufnum The buffer to load. One of the * MCP2515_TX_BUFFER_T values. * @param id The integer representation of the CAN bus ID. * @param ext True if the ID is an extended identifier, false otherwise. * @param rtr True if this is a Remote Transfer Request, false otherwise. * @param payload A pointer to an array of bytes that make up the * payload to send. * @param len The length of the payload. The length is limited to * 8. * @return UPM result. */ upm_result_t mcp2515_load_tx_buffer(const mcp2515_context dev, MCP2515_TX_BUFFER_T bufnum, int id, bool ext, bool rtr, uint8_t *payload, int len); /** * Transmit a buffer already loaded by mcp2515_load_tx_buffer(). * * @param dev Device context. * @param bufnum The buffer to transmit. One of the * MCP2515_TX_BUFFER_T values. * @param wait True if the function should wait until transmission * is complete before returning, false otherwise. * @return UPM result. */ upm_result_t mcp2515_transmit_buffer(const mcp2515_context dev, MCP2515_TX_BUFFER_T bufnum, bool wait); /** * Determine whether a TX buffer is available for use or not. A TX * buffer is unavailable if a transmit request is pending on it, * but transmission has not yet completed. * * @param dev Device context. * @param bufnum The buffer to check. One of the * MCP2515_TX_BUFFER_T values. * @return True if the buffer is availabe, false otherwise. */ bool mcp2515_tx_buffer_is_free(const mcp2515_context dev, MCP2515_TX_BUFFER_T bufnum); /** * Find a free TX buffer and return it. * * @param dev Device context. * @return One of the MCP2515_TX_BUFFER_T values. If no buffers * are available, MCP2515_TX_NO_BUFFERS will be returned. */ MCP2515_TX_BUFFER_T mcp2515_find_free_tx_buffer(const mcp2515_context dev); /** * Set the transmit priority of a TX buffer. Higher priority * buffers are always transmitted before lower priority buffers. * This function can be called on a buffer at any time prior to * actual transmission. * * @param dev Device context. * @param bufnum The buffer to set priority for. One of the * MCP2515_TX_BUFFER_T values. * @param priority The priority to set for the buffer. One of the * MCP2515_TXP_T values. * @return UPM result. */ upm_result_t mcp2515_set_tx_buffer_priority(const mcp2515_context dev, MCP2515_TX_BUFFER_T bufnum, MCP2515_TXP_T priority); /** * Abort a transmission that has been queued, but not yet * completed. This will also free up the TX buffer for future * use. Note, if you abort a transmission, but transmission has * already started, this call will have no effect, and the buffer * will complete transmission. * * @param dev Device context. * @param bufnum The buffer to abort. One of the * MCP2515_TX_BUFFER_T values. * @return UPM result. */ upm_result_t mcp2515_abort_tx(const mcp2515_context dev, MCP2515_TX_BUFFER_T bufnum); /** * Set the mode for an RX buffer. The mode specifies, at a high * level, what packets should be captured from the bus and placed * into an RX buffer. See the datasheet for details, but the * default, MCP2515_RXMODE_ANY_FILTER, should be sufficient in * most cases. It is also possible to use this to restrict the * types of CAN ids accepted (extended only, standard only) as * well as a debug ANY_NOFILTER mode. * * @param dev Device context. * @param bufnum The buffer to set the mode for. One of the * MCP2515_RX_BUFFER_T values. * @param rxm The mode to set. One of the MCP2515_RXMODE_T values. * @return UPM result. */ upm_result_t mcp2515_set_rx_buffer_mode(const mcp2515_context dev, MCP2515_RX_BUFFER_T bufnum, MCP2515_RXMODE_T rxm); /** * Return a bitmask indicating which of the 2 RX buffers have * packets waiting in them. This can be 0 (no packets), 1(RXB0), * 2(RXB1), or 3 (RXB0 and RXB1). This information is retrieved * using the MCP2515_CMD_RX_STATUS command. * * @param dev Device context. * @return A bitmask indicating which RX buffers (if any) have * packets in them. One of the MCP2515_RXMSG_T values. */ MCP2515_RXMSG_T mcp2515_rx_status_msgs(const mcp2515_context dev); /** * Return the message type present in one of the RX buffers. RXB0 * has the highest priority, so if both RX buffers are full, this * function will only return data for the packet in RXB0. This * information is retrieved using the MCP2515_CMD_RX_STATUS * command. * * @param dev Device context. * @return One of the MCP2515_MSGTYPE_T values. */ MCP2515_MSGTYPE_T mcp2515_rx_status_msg_type(const mcp2515_context dev); /** * Return the filter that matched an RX buffer. RXB0 has the * highest priority, so if both RX buffers are full, this function * will only return data for the packet in RXB0. This information * is retrieved using the MCP2515_CMD_RX_STATUS command. * * @param dev Device context. * @return One of the MCP2515_FILTERMATCH_T values. */ MCP2515_FILTERMATCH_T mcp2515_rx_status_filtermatch(const mcp2515_context dev); /** * This function retrieves a message from the specified RX buffer. * The message (MCP2515_MSG_T) contains all of the data in the * packet, including id, rtr, ext, payload and payload length. In * addition, after retrieving the message, the RX buffer is freed * to receive further data from the CAN bus. * * @param dev Device context. * @param bufnum The buffer to retrieve. One of the * MCP2515_RX_BUFFER_T values. * @param msg A pointer to a MCP2515_MSG_T, which will be filled * with the decoded contents of the RX buffer. * @return UPM result. */ upm_result_t mcp2515_get_rx_msg(const mcp2515_context dev, MCP2515_RX_BUFFER_T bufnum, MCP2515_MSG_T *msg); /** * This is a utility function that accepts a MCP2515_MSG_T and * prints out it's decoded contents. This is of primary * importance for debugging, and to simplify the examples * somewhat. * * The output will look similar to: * * id 00000000 ext 0 rtr 0 filt 0 len 8 * payload: 0xc8 0x01 0x02 0x03 0x04 0x05 0x06 0x07 * * @param dev Device context. * @param msg A pointer to a MCP2515_MSG_T containing the data to * be printed out. */ void mcp2515_print_msg(const mcp2515_context dev, MCP2515_MSG_T *msg); /** * Installs an interrupt service routine (ISR) to be called when * an interrupt occurs. * * @param dev Device context. * @param pin GPIO pin to use as the interrupt pin. * @param fptr Pointer to a function to be called on interrupt. * @param arg Pointer to an object to be supplied as an * argument to the ISR. * @return UPM result. */ upm_result_t mcp2515_install_isr(const mcp2515_context dev, int pin, void (*isr)(void *), void *arg); /** * Uninstalls the previously installed ISR * * @param dev Device context. */ void mcp2515_uninstall_isr(const mcp2515_context dev); /** * Set the interrupt enables register. * * @param dev Device context. * @param enables A bitmask of interrupts to enable from * MCP2515_CANINT_BITS_T. * @return UPM result. */ upm_result_t mcp2515_set_intr_enables(const mcp2515_context dev, uint8_t enables); /** * Retrieve the interrupt flags register. * * @param dev Device context. * @param flags A pointer to a bitmask that will be filled with * values from MCP2515_CANINT_BITS_T, indicating which interrupt * flags are set. * @return UPM result. */ upm_result_t mcp2515_get_intr_flags(const mcp2515_context dev, uint8_t *flags); /** * This function allows you to set specific interrupt flags. If * the corresponding interrupt enable is set, an interrupt will be * generated. * * @param dev Device context. * @param flags A bitmask of interrupt flags to set, from * MCP2515_CANINT_BITS_T values. * @return UPM result. */ upm_result_t mcp2515_set_intr_flags(const mcp2515_context dev, uint8_t flags); /** * This function allows you to clear specific interrupt flags. * See the datasheet. Some flags cannot be cleared until the * underlying cause has been corrected. * * @param dev Device context. * @param flags A bitmask of interrupt flags to clear, from * MCP2515_CANINT_BITS_T values. * @return UPM result. */ upm_result_t mcp2515_clear_intr_flags(const mcp2515_context dev, uint8_t flags); /** * Retrieve the error flags register * * @param dev Device context. * @param flags A pointer to a uint8_t that will hold the flags * with values from MCP2515_EFLG_BITS_T. * @return UPM result. */ upm_result_t mcp2515_get_error_flags(const mcp2515_context dev, uint8_t *flags); /** * Clear error flags. Note, some flags cannot be cleared * until the underlying issues is resolved. * * @param dev Device context. * @param flags A bitmask of values from MCP2515_EFLG_BITS_T * specifying the flags to clear. * @return UPM result. */ upm_result_t mcp2515_clear_error_flags(const mcp2515_context dev, uint8_t flags); /** * This function allows you to set one of the 6 RX filters * available. Filters 0 and 1 are for RXB0 only, while filters * 2-5 are for RXB1. See the datasheet for details on how these * filters (along with the masks) are used to select candidate CAN * bus data for retrieval from the CAN bus. * * These can only be set when the device is in CONFIG mode. * * @param dev Device context. * @param filter One of the 6 MCP2515_RX_FILTER_T values. * @param ext True if the id is extended, false for standard. * @param id Integer representation of a CAN bus ID. * @return UPM result. */ upm_result_t mcp2515_set_filter(const mcp2515_context dev, MCP2515_RX_FILTER_T filter, bool ext, int id); /** * This function allows you to set one of the 2 RX masks. Mask 0 * is for RXB0, mask 1 is for RXB1. The masks specify which bits * in the filters are used for matching CAN bus data. See the * datasheet for details on how these masks (along with the * filters) are used to select candidate CAN bus data for retrieval * from the CAN bus. * * These can only be set when the device is in CONFIG mode. * * @param dev Device context. * @param mask One of the 2 MCP2515_RX_MASK_T values. * @param ext True if the id is extended, false for standard. * @param id Integer representation of a CAN bus ID. * @return UPM result. */ upm_result_t mcp2515_set_mask(const mcp2515_context dev, MCP2515_RX_MASK_T mask, bool ext, int id); /** * Perform a bus read. This function is exposed here for those * users wishing to perform their own low level accesses. This is * a low level function, and should not be used unless you know * what you are doing. * * @param dev Device context. * @param cmd The command to send. * @param args An array of arguments, or NULL. * @param arglen The number of args, or 0. * @param data A pointer to a buffer in which data will be read into. * @param len The number of bytes to read. * @return UPM result. */ upm_result_t mcp2515_bus_read(const mcp2515_context dev, uint8_t cmd, uint8_t *args, unsigned int arglen, uint8_t *data, uint8_t len); /** * Perform a bus write. This function is exposed here for those * users wishing to perform their own low level accesses. This is * a low level function, and should not be used unless you know * what you are doing. * * @param dev Device context * @param cmd The command to send. * @param data A pointer to a buffer containing data to write. * @param len The number of bytes to write. * @return UPM Status */ upm_result_t mcp2515_bus_write(const mcp2515_context dev, uint8_t cmd, uint8_t *data, uint8_t len); /** * Write to a specific register. This function is exposed here * for those users wishing to perform their own low level * accesses. This is a low level function, and should not be used * unless you know what you are doing. * * @param dev Device context * @param reg The register to write to. * @param value The byte to write. * @return UPM Status */ upm_result_t mcp2515_write_reg(const mcp2515_context dev, uint8_t reg, uint8_t value); /** * Write to multiple consecutive registers. This function is * exposed here for those users wishing to perform their own low * level accesses. This is a low level function, and should not * be used unless you know what you are doing. * * @param dev Device context * @param reg The register to start writing to. * @param buffer A pointer to an array of bytes to write. * @param len The number of bytes to write. * @return UPM Status */ upm_result_t mcp2515_write_regs(const mcp2515_context dev, uint8_t reg, uint8_t *buffer, int len); /** * Read a register. This function is exposed here for those users * wishing to perform their own low level accesses. This is a low * level function, and should not be used unless you know what you * are doing. * * @param dev Device context * @param reg The register to read. * @param buffer A pointer to a a byte where the value will be placed. * @return UPM Status */ upm_result_t mcp2515_read_reg(const mcp2515_context dev, uint8_t reg, uint8_t *value); /** * Perform a bit modify operation on a register. Only certain * registers support this method of access - check the datasheet. * This function is exposed here for those users wishing to * perform their own low level accesses. This is a low level * function, and should not be used unless you know what you are * doing. * * @param dev Device context * @param addr The address of the register to access. * @param mask A bitmask used to mask off value bits. * @param value The value to write (bits masked by mask). * @return UPM Status */ upm_result_t mcp2515_bit_modify(const mcp2515_context dev, uint8_t addr, uint8_t mask, uint8_t value); #ifdef __cplusplus } #endif