From cf862e5883f31a2cd80b5d38766a881d383a39f1 Mon Sep 17 00:00:00 2001 From: wangcoolc <1387172050@163.com> Date: Thu, 5 Nov 2020 20:19:47 +0800 Subject: [PATCH] Add mcp2518fd canfd spi function --- mcp2518fd_can_def.h | 891 +++++++++ mcp2518fd_can_dfs.h | 799 ++++++++ mcp2518fd_canfdspi_api.cpp | 3890 ++++++++++++++++++++++++++++++++++++ mcp2518fd_canfdspi_api.h | 1120 +++++++++++ 4 files changed, 6700 insertions(+) create mode 100644 mcp2518fd_can_def.h create mode 100644 mcp2518fd_can_dfs.h create mode 100644 mcp2518fd_canfdspi_api.cpp create mode 100644 mcp2518fd_canfdspi_api.h diff --git a/mcp2518fd_can_def.h b/mcp2518fd_can_def.h new file mode 100644 index 0000000..6e116b6 --- /dev/null +++ b/mcp2518fd_can_def.h @@ -0,0 +1,891 @@ +/******************************************************************************* + CAN FD SPI Driver: API Defines Header File + + Company: + Microchip Technology Inc. + + File Name: + drv_canfdspi_defines.h + + Summary: + This header file contains object declarations used in the API. + This also contains device specific defines. + + Description: + None. + *******************************************************************************/ + +//DOM-IGNORE-BEGIN +/******************************************************************************* +Copyright (c) 2018 Microchip Technology Inc. and its subsidiaries. + +Subject to your compliance with these terms, you may use Microchip software and +any derivatives exclusively with Microchip products. It is your responsibility +to comply with third party license terms applicable to your use of third party +software (including open source software) that may accompany Microchip software. + +THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, +IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES +OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. + +IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, +INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER +RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF +THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED +BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO +THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID +DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + *******************************************************************************/ +//DOM-IGNORE-END + +#ifndef _DRV_CANFDSPI_DEFINES_H +#define _DRV_CANFDSPI_DEFINES_H + +// ***************************************************************************** +// ***************************************************************************** +// Section: Included Files + +#include +#include +#include +#include + + +// DOM-IGNORE-BEGIN +#ifdef __cplusplus // Provide C++ Compatibility +extern "C" { +#endif +// DOM-IGNORE-END + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Implementation + +// Device selection +#define MCP2517FD +//#define MCP2518FD + +// Maximum Size of TX/RX Object +#define MAX_MSG_SIZE 76 + +// Maximum number of data bytes in message +#define MAX_DATA_BYTES 64 + +// ***************************************************************************** +// ***************************************************************************** +// Section: Object definitions + +//! CAN FIFO Channels + +typedef enum { + CAN_FIFO_CH0, // CAN_TXQUEUE_CH0 + CAN_FIFO_CH1, + CAN_FIFO_CH2, + CAN_FIFO_CH3, + CAN_FIFO_CH4, + CAN_FIFO_CH5, + CAN_FIFO_CH6, + CAN_FIFO_CH7, + CAN_FIFO_CH8, + CAN_FIFO_CH9, + CAN_FIFO_CH10, + CAN_FIFO_CH11, + CAN_FIFO_CH12, + CAN_FIFO_CH13, + CAN_FIFO_CH14, + CAN_FIFO_CH15, + CAN_FIFO_CH16, + CAN_FIFO_CH17, + CAN_FIFO_CH18, + CAN_FIFO_CH19, + CAN_FIFO_CH20, + CAN_FIFO_CH21, + CAN_FIFO_CH22, + CAN_FIFO_CH23, + CAN_FIFO_CH24, + CAN_FIFO_CH25, + CAN_FIFO_CH26, + CAN_FIFO_CH27, + CAN_FIFO_CH28, + CAN_FIFO_CH29, + CAN_FIFO_CH30, + CAN_FIFO_CH31, + CAN_FIFO_TOTAL_CHANNELS +} CAN_FIFO_CHANNEL; + +// FIFO0 is a special FIFO, the TX Queue +#define CAN_TXQUEUE_CH0 CAN_FIFO_CH0 + +//! CAN Filter Channels + +typedef enum { + CAN_FILTER0, + CAN_FILTER1, + CAN_FILTER2, + CAN_FILTER3, + CAN_FILTER4, + CAN_FILTER5, + CAN_FILTER6, + CAN_FILTER7, + CAN_FILTER8, + CAN_FILTER9, + CAN_FILTER10, + CAN_FILTER11, + CAN_FILTER12, + CAN_FILTER13, + CAN_FILTER14, + CAN_FILTER15, + CAN_FILTER16, + CAN_FILTER17, + CAN_FILTER18, + CAN_FILTER19, + CAN_FILTER20, + CAN_FILTER21, + CAN_FILTER22, + CAN_FILTER23, + CAN_FILTER24, + CAN_FILTER25, + CAN_FILTER26, + CAN_FILTER27, + CAN_FILTER28, + CAN_FILTER29, + CAN_FILTER30, + CAN_FILTER31, + CAN_FILTER_TOTAL, +} CAN_FILTER; + + +//! CAN Operation Modes + +typedef enum { + CAN_NORMAL_MODE = 0x00, + CAN_SLEEP_MODE = 0x01, + CAN_INTERNAL_LOOPBACK_MODE = 0x02, + CAN_LISTEN_ONLY_MODE = 0x03, + CAN_CONFIGURATION_MODE = 0x04, + CAN_EXTERNAL_LOOPBACK_MODE = 0x05, + CAN_CLASSIC_MODE = 0x06, + CAN_RESTRICTED_MODE = 0x07, + CAN_INVALID_MODE = 0xFF +} CAN_OPERATION_MODE; + +//! Transmit Bandwidth Sharing + +typedef enum { + CAN_TXBWS_NO_DELAY, + CAN_TXBWS_2, + CAN_TXBWS_4, + CAN_TXBWS_8, + CAN_TXBWS_16, + CAN_TXBWS_32, + CAN_TXBWS_64, + CAN_TXBWS_128, + CAN_TXBWS_256, + CAN_TXBWS_512, + CAN_TXBWS_1024, + CAN_TXBWS_2048, + CAN_TXBWS_4096 +} CAN_TX_BANDWITH_SHARING; + +//! Wake-up Filter Time + +typedef enum { + CAN_WFT00, + CAN_WFT01, + CAN_WFT10, + CAN_WFT11 +} CAN_WAKEUP_FILTER_TIME; + +//! Data Byte Filter Number + +typedef enum { + CAN_DNET_FILTER_DISABLE = 0, + CAN_DNET_FILTER_SIZE_1_BIT, + CAN_DNET_FILTER_SIZE_2_BIT, + CAN_DNET_FILTER_SIZE_3_BIT, + CAN_DNET_FILTER_SIZE_4_BIT, + CAN_DNET_FILTER_SIZE_5_BIT, + CAN_DNET_FILTER_SIZE_6_BIT, + CAN_DNET_FILTER_SIZE_7_BIT, + CAN_DNET_FILTER_SIZE_8_BIT, + CAN_DNET_FILTER_SIZE_9_BIT, + CAN_DNET_FILTER_SIZE_10_BIT, + CAN_DNET_FILTER_SIZE_11_BIT, + CAN_DNET_FILTER_SIZE_12_BIT, + CAN_DNET_FILTER_SIZE_13_BIT, + CAN_DNET_FILTER_SIZE_14_BIT, + CAN_DNET_FILTER_SIZE_15_BIT, + CAN_DNET_FILTER_SIZE_16_BIT, + CAN_DNET_FILTER_SIZE_17_BIT, + CAN_DNET_FILTER_SIZE_18_BIT +} CAN_DNET_FILTER_SIZE; + +//! FIFO Payload Size + +typedef enum { + CAN_PLSIZE_8, + CAN_PLSIZE_12, + CAN_PLSIZE_16, + CAN_PLSIZE_20, + CAN_PLSIZE_24, + CAN_PLSIZE_32, + CAN_PLSIZE_48, + CAN_PLSIZE_64 +} CAN_FIFO_PLSIZE; + +//! CAN Configure + +typedef struct _CAN_CONFIG { + uint32_t DNetFilterCount : 5; + uint32_t IsoCrcEnable : 1; + uint32_t ProtocolExpectionEventDisable : 1; + uint32_t WakeUpFilterEnable : 1; + uint32_t WakeUpFilterTime : 2; + uint32_t BitRateSwitchDisable : 1; + uint32_t RestrictReTxAttempts : 1; + uint32_t EsiInGatewayMode : 1; + uint32_t SystemErrorToListenOnly : 1; + uint32_t StoreInTEF : 1; + uint32_t TXQEnable : 1; + uint32_t TxBandWidthSharing : 4; +} CAN_CONFIG; + +//! CAN Transmit Channel Configure + +typedef struct _CAN_TX_FIFO_CONFIG { + uint32_t RTREnable : 1; + uint32_t TxPriority : 5; + uint32_t TxAttempts : 2; + uint32_t FifoSize : 5; + uint32_t PayLoadSize : 3; +} CAN_TX_FIFO_CONFIG; + +//! CAN Transmit Queue Configure + +typedef struct _CAN_TX_QUEUE_CONFIG { + uint32_t TxPriority : 5; + uint32_t TxAttempts : 2; + uint32_t FifoSize : 5; + uint32_t PayLoadSize : 3; +} CAN_TX_QUEUE_CONFIG; + +//! CAN Receive Channel Configure + +typedef struct _CAN_RX_FIFO_CONFIG { + uint32_t RxTimeStampEnable : 1; + uint32_t FifoSize : 5; + uint32_t PayLoadSize : 3; +} CAN_RX_FIFO_CONFIG; + +//! CAN Transmit Event FIFO Configure + +typedef struct _CAN_TEF_CONFIG { + uint32_t TimeStampEnable : 1; + uint32_t FifoSize : 5; +} CAN_TEF_CONFIG; + +/* CAN Message Objects */ + +//! CAN Message Object ID + +typedef struct _CAN_MSGOBJ_ID { + uint32_t SID : 11; + uint32_t EID : 18; + uint32_t SID11 : 1; + uint32_t unimplemented1 : 2; +} CAN_MSGOBJ_ID; + +//! CAN Data Length Code + +typedef enum { + CAN_DLC_0, + CAN_DLC_1, + CAN_DLC_2, + CAN_DLC_3, + CAN_DLC_4, + CAN_DLC_5, + CAN_DLC_6, + CAN_DLC_7, + CAN_DLC_8, + CAN_DLC_12, + CAN_DLC_16, + CAN_DLC_20, + CAN_DLC_24, + CAN_DLC_32, + CAN_DLC_48, + CAN_DLC_64 +} CAN_DLC; + +//! CAN TX Message Object Control + +typedef struct _CAN_TX_MSGOBJ_CTRL { + uint32_t DLC : 4; + uint32_t IDE : 1; + uint32_t RTR : 1; + uint32_t BRS : 1; + uint32_t FDF : 1; + uint32_t ESI : 1; +#ifdef MCP2517FD + uint32_t SEQ : 7; + uint32_t unimplemented1 : 16; +#else + uint32_t SEQ : 23; +#endif +} CAN_TX_MSGOBJ_CTRL; + +//! CAN RX Message Object Control + +typedef struct _CAN_RX_MSGOBJ_CTRL { + uint32_t DLC : 4; + uint32_t IDE : 1; + uint32_t RTR : 1; + uint32_t BRS : 1; + uint32_t FDF : 1; + uint32_t ESI : 1; + uint32_t unimplemented1 : 2; + uint32_t FilterHit : 5; + uint32_t unimplemented2 : 16; +} CAN_RX_MSGOBJ_CTRL; + +//! CAN Message Time Stamp +typedef uint32_t CAN_MSG_TIMESTAMP; + +//! CAN TX Message Object + +typedef union _CAN_TX_MSGOBJ { + + struct { + CAN_MSGOBJ_ID id; + CAN_TX_MSGOBJ_CTRL ctrl; + CAN_MSG_TIMESTAMP timeStamp; + } bF; + uint32_t word[3]; + uint8_t byte[12]; +} CAN_TX_MSGOBJ; + +//! CAN RX Message Object + +typedef union _CAN_RX_MSGOBJ { + + struct { + CAN_MSGOBJ_ID id; + CAN_RX_MSGOBJ_CTRL ctrl; + CAN_MSG_TIMESTAMP timeStamp; + } bF; + uint32_t word[3]; + uint8_t byte[12]; +} CAN_RX_MSGOBJ; + +//! CAN TEF Message Object + +typedef union _CAN_TEF_MSGOBJ { + + struct { + CAN_MSGOBJ_ID id; + CAN_TX_MSGOBJ_CTRL ctrl; + CAN_MSG_TIMESTAMP timeStamp; + } bF; + uint32_t word[3]; + uint8_t byte[12]; +} CAN_TEF_MSGOBJ; + +//! CAN Filter Object ID + +typedef struct _CAN_FILTEROBJ_ID { + uint32_t SID : 11; + uint32_t EID : 18; + uint32_t SID11 : 1; + uint32_t EXIDE : 1; + uint32_t unimplemented1 : 1; +} CAN_FILTEROBJ_ID; + +//! CAN Mask Object ID + +typedef struct _CAN_MASKOBJ_ID { + uint32_t MSID : 11; + uint32_t MEID : 18; + uint32_t MSID11 : 1; + uint32_t MIDE : 1; + uint32_t unimplemented1 : 1; +} CAN_MASKOBJ_ID; + +//! CAN RX FIFO Status + +typedef enum { + CAN_RX_FIFO_EMPTY = 0, + CAN_RX_FIFO_STATUS_MASK = 0x0F, + CAN_RX_FIFO_NOT_EMPTY = 0x01, + CAN_RX_FIFO_HALF_FULL = 0x02, + CAN_RX_FIFO_FULL = 0x04, + CAN_RX_FIFO_OVERFLOW = 0x08 +} CAN_RX_FIFO_STATUS; + +//! CAN TX FIFO Status + +typedef enum { + CAN_TX_FIFO_FULL = 0, + CAN_TX_FIFO_STATUS_MASK = 0x1F7, + CAN_TX_FIFO_NOT_FULL = 0x01, + CAN_TX_FIFO_HALF_FULL = 0x02, + CAN_TX_FIFO_EMPTY = 0x04, + CAN_TX_FIFO_ATTEMPTS_EXHAUSTED = 0x10, + CAN_TX_FIFO_ERROR = 0x20, + CAN_TX_FIFO_ARBITRATION_LOST = 0x40, + CAN_TX_FIFO_ABORTED = 0x80, + CAN_TX_FIFO_TRANSMITTING = 0x100 +} CAN_TX_FIFO_STATUS; + +//! CAN TEF FIFO Status + +typedef enum { + CAN_TEF_FIFO_EMPTY = 0, + CAN_TEF_FIFO_STATUS_MASK = 0x0F, + CAN_TEF_FIFO_NOT_EMPTY = 0x01, + CAN_TEF_FIFO_HALF_FULL = 0x02, + CAN_TEF_FIFO_FULL = 0x04, + CAN_TEF_FIFO_OVERFLOW = 0x08 +} CAN_TEF_FIFO_STATUS; + +//! CAN Module Event (Interrupts) + +typedef enum { + CAN_NO_EVENT = 0, + CAN_ALL_EVENTS = 0xFF1F, + CAN_TX_EVENT = 0x0001, + CAN_RX_EVENT = 0x0002, + CAN_TIME_BASE_COUNTER_EVENT = 0x0004, + CAN_OPERATION_MODE_CHANGE_EVENT = 0x0008, + CAN_TEF_EVENT = 0x0010, + + CAN_RAM_ECC_EVENT = 0x0100, + CAN_SPI_CRC_EVENT = 0x0200, + CAN_TX_ATTEMPTS_EVENT = 0x0400, + CAN_RX_OVERFLOW_EVENT = 0x0800, + CAN_SYSTEM_ERROR_EVENT = 0x1000, + CAN_BUS_ERROR_EVENT = 0x2000, + CAN_BUS_WAKEUP_EVENT = 0x4000, + CAN_RX_INVALID_MESSAGE_EVENT = 0x8000 +} CAN_MODULE_EVENT; + +//! CAN TX FIFO Event (Interrupts) + +typedef enum { + CAN_TX_FIFO_NO_EVENT = 0, + CAN_TX_FIFO_ALL_EVENTS = 0x17, + CAN_TX_FIFO_NOT_FULL_EVENT = 0x01, + CAN_TX_FIFO_HALF_FULL_EVENT = 0x02, + CAN_TX_FIFO_EMPTY_EVENT = 0x04, + CAN_TX_FIFO_ATTEMPTS_EXHAUSTED_EVENT = 0x10 +} CAN_TX_FIFO_EVENT; + +//! CAN RX FIFO Event (Interrupts) + +typedef enum { + CAN_RX_FIFO_NO_EVENT = 0, + CAN_RX_FIFO_ALL_EVENTS = 0x0F, + CAN_RX_FIFO_NOT_EMPTY_EVENT = 0x01, + CAN_RX_FIFO_HALF_FULL_EVENT = 0x02, + CAN_RX_FIFO_FULL_EVENT = 0x04, + CAN_RX_FIFO_OVERFLOW_EVENT = 0x08 +} CAN_RX_FIFO_EVENT; + +//! CAN TEF FIFO Event (Interrupts) + +typedef enum { + CAN_TEF_FIFO_NO_EVENT = 0, + CAN_TEF_FIFO_ALL_EVENTS = 0x0F, + CAN_TEF_FIFO_NOT_EMPTY_EVENT = 0x01, + CAN_TEF_FIFO_HALF_FULL_EVENT = 0x02, + CAN_TEF_FIFO_FULL_EVENT = 0x04, + CAN_TEF_FIFO_OVERFLOW_EVENT = 0x08 +} CAN_TEF_FIFO_EVENT; + +//! CAN Bit Time Setup: Arbitration/Data Bit Phase + +typedef enum { + CAN_500K_1M, // 0x00 + CAN_500K_2M, // 0x01 + CAN_500K_3M, + CAN_500K_4M, + CAN_500K_5M, // 0x04 + CAN_500K_6M7, + CAN_500K_8M, // 0x06 + CAN_500K_10M, + CAN_250K_500K, // 0x08 + CAN_250K_833K, + CAN_250K_1M, + CAN_250K_1M5, + CAN_250K_2M, + CAN_250K_3M, + CAN_250K_4M, + CAN_1000K_4M, // 0x0f + CAN_1000K_8M, + CAN_125K_500K // 0x11 +} CAN_BITTIME_SETUP; + +//! CAN Nominal Bit Time Setup + +typedef enum { + CAN_NBT_125K, + CAN_NBT_250K, + CAN_NBT_500K, + CAN_NBT_1M +} CAN_NOMINAL_BITTIME_SETUP; + +//! CAN Data Bit Time Setup + +typedef enum { + CAN_DBT_500K, + CAN_DBT_833K, + CAN_DBT_1M, + CAN_DBT_1M5, + CAN_DBT_2M, + CAN_DBT_3M, + CAN_DBT_4M, + CAN_DBT_5M, + CAN_DBT_6M7, + CAN_DBT_8M, + CAN_DBT_10M +} CAN_DATA_BITTIME_SETUP; + +//! Secondary Sample Point Mode + +typedef enum { + CAN_SSP_MODE_OFF, + CAN_SSP_MODE_MANUAL, + CAN_SSP_MODE_AUTO +} CAN_SSP_MODE; + +//! CAN Error State + +typedef enum { + CAN_ERROR_FREE_STATE = 0, + CAN_ERROR_ALL = 0x3F, + CAN_TX_RX_WARNING_STATE = 0x01, + CAN_RX_WARNING_STATE = 0x02, + CAN_TX_WARNING_STATE = 0x04, + CAN_RX_BUS_PASSIVE_STATE = 0x08, + CAN_TX_BUS_PASSIVE_STATE = 0x10, + CAN_TX_BUS_OFF_STATE = 0x20 +} CAN_ERROR_STATE; + +//! CAN Time Stamp Mode Select + +typedef enum { + CAN_TS_SOF = 0x00, + CAN_TS_EOF = 0x01, + CAN_TS_RES = 0x02 +} CAN_TS_MODE; + +//! CAN ECC EVENT + +typedef enum { + CAN_ECC_NO_EVENT = 0x00, + CAN_ECC_ALL_EVENTS = 0x06, + CAN_ECC_SEC_EVENT = 0x02, + CAN_ECC_DED_EVENT = 0x04 +} CAN_ECC_EVENT; + +//! CAN CRC EVENT + +typedef enum { + CAN_CRC_NO_EVENT = 0x00, + CAN_CRC_ALL_EVENTS = 0x03, + CAN_CRC_CRCERR_EVENT = 0x01, + CAN_CRC_FORMERR_EVENT = 0x02 +} CAN_CRC_EVENT; + +//! GPIO Pin Position + +typedef enum { + GPIO_PIN_0, + GPIO_PIN_1 +} GPIO_PIN_POS; + +//! GPIO Pin Modes + +typedef enum { + GPIO_MODE_INT, + GPIO_MODE_GPIO +} GPIO_PIN_MODE; + +//! GPIO Pin Directions + +typedef enum { + GPIO_OUTPUT, + GPIO_INPUT +} GPIO_PIN_DIRECTION; + +//! GPIO Open Drain Mode + +typedef enum { + GPIO_PUSH_PULL, + GPIO_OPEN_DRAIN +} GPIO_OPEN_DRAIN_MODE; + +//! GPIO Pin State + +typedef enum { + GPIO_LOW, + GPIO_HIGH +} GPIO_PIN_STATE; + +//! Clock Output Mode + +typedef enum { + GPIO_CLKO_CLOCK, + GPIO_CLKO_SOF +} GPIO_CLKO_MODE; + +//! CAN Bus Diagnostic flags + +typedef struct _CAN_BUS_DIAG_FLAGS { + uint32_t NBIT0_ERR : 1; + uint32_t NBIT1_ERR : 1; + uint32_t NACK_ERR : 1; + uint32_t NFORM_ERR : 1; + uint32_t NSTUFF_ERR : 1; + uint32_t NCRC_ERR : 1; + uint32_t unimplemented1 : 1; + uint32_t TXBO_ERR : 1; + uint32_t DBIT0_ERR : 1; + uint32_t DBIT1_ERR : 1; + uint32_t unimplemented2 : 1; + uint32_t DFORM_ERR : 1; + uint32_t DSTUFF_ERR : 1; + uint32_t DCRC_ERR : 1; + uint32_t ESI : 1; + uint32_t DLC_MISMATCH : 1; +} CAN_BUS_DIAG_FLAGS; + +//! CAN Bus Diagnostic Error Counts + +typedef struct _CAN_BUS_ERROR_COUNT { + uint8_t NREC; + uint8_t NTEC; + uint8_t DREC; + uint8_t DTEC; +} CAN_BUS_ERROR_COUNT; + +//! CAN BUS DIAGNOSTICS + +typedef union _CAN_BUS_DIAGNOSTIC { + + struct { + CAN_BUS_ERROR_COUNT errorCount; + uint16_t errorFreeMsgCount; + CAN_BUS_DIAG_FLAGS flag; + } bF; + uint32_t word[3]; + uint8_t byte[12]; +} CAN_BUS_DIAGNOSTIC; + +//! TXREQ Channel Bits +// Multiple channels can be or'ed together + +typedef enum { + CAN_TXREQ_CH0 = 0x00000001, + CAN_TXREQ_CH1 = 0x00000002, + CAN_TXREQ_CH2 = 0x00000004, + CAN_TXREQ_CH3 = 0x00000008, + CAN_TXREQ_CH4 = 0x00000010, + CAN_TXREQ_CH5 = 0x00000020, + CAN_TXREQ_CH6 = 0x00000040, + CAN_TXREQ_CH7 = 0x00000080, + + CAN_TXREQ_CH8 = 0x00000100, + CAN_TXREQ_CH9 = 0x00000200, + CAN_TXREQ_CH10 = 0x00000400, + CAN_TXREQ_CH11 = 0x00000800, + CAN_TXREQ_CH12 = 0x00001000, + CAN_TXREQ_CH13 = 0x00002000, + CAN_TXREQ_CH14 = 0x00004000, + CAN_TXREQ_CH15 = 0x00008000, + + CAN_TXREQ_CH16 = 0x00010000, + CAN_TXREQ_CH17 = 0x00020000, + CAN_TXREQ_CH18 = 0x00040000, + CAN_TXREQ_CH19 = 0x00080000, + CAN_TXREQ_CH20 = 0x00100000, + CAN_TXREQ_CH21 = 0x00200000, + CAN_TXREQ_CH22 = 0x00400000, + CAN_TXREQ_CH23 = 0x00800000, + + CAN_TXREQ_CH24 = 0x01000000, + CAN_TXREQ_CH25 = 0x02000000, + CAN_TXREQ_CH26 = 0x04000000, + CAN_TXREQ_CH27 = 0x08000000, + CAN_TXREQ_CH28 = 0x10000000, + CAN_TXREQ_CH29 = 0x20000000, + CAN_TXREQ_CH30 = 0x40000000, + CAN_TXREQ_CH31 = 0x80000000 +} CAN_TXREQ_CHANNEL; + +//! Oscillator Control + +typedef struct _CAN_OSC_CTRL { + uint32_t PllEnable : 1; + uint32_t OscDisable : 1; + uint32_t SclkDivide : 1; + uint32_t ClkOutDivide : 2; +#ifndef MCP2517FD + uint32_t LowPowerModeEnable : 1; +#endif +} CAN_OSC_CTRL; + +//! Oscillator Status + +typedef struct _CAN_OSC_STATUS { + uint32_t PllReady : 1; + uint32_t OscReady : 1; + uint32_t SclkReady : 1; +} CAN_OSC_STATUS; + +//! ICODE + +typedef enum { + CAN_ICODE_FIFO_CH0, + CAN_ICODE_FIFO_CH1, + CAN_ICODE_FIFO_CH2, + CAN_ICODE_FIFO_CH3, + CAN_ICODE_FIFO_CH4, + CAN_ICODE_FIFO_CH5, + CAN_ICODE_FIFO_CH6, + CAN_ICODE_FIFO_CH7, + CAN_ICODE_FIFO_CH8, + CAN_ICODE_FIFO_CH9, + CAN_ICODE_FIFO_CH10, + CAN_ICODE_FIFO_CH11, + CAN_ICODE_FIFO_CH12, + CAN_ICODE_FIFO_CH13, + CAN_ICODE_FIFO_CH14, + CAN_ICODE_FIFO_CH15, + CAN_ICODE_FIFO_CH16, + CAN_ICODE_FIFO_CH17, + CAN_ICODE_FIFO_CH18, + CAN_ICODE_FIFO_CH19, + CAN_ICODE_FIFO_CH20, + CAN_ICODE_FIFO_CH21, + CAN_ICODE_FIFO_CH22, + CAN_ICODE_FIFO_CH23, + CAN_ICODE_FIFO_CH24, + CAN_ICODE_FIFO_CH25, + CAN_ICODE_FIFO_CH26, + CAN_ICODE_FIFO_CH27, + CAN_ICODE_FIFO_CH28, + CAN_ICODE_FIFO_CH29, + CAN_ICODE_FIFO_CH30, + CAN_ICODE_FIFO_CH31, + CAN_ICODE_TOTAL_CHANNELS, + CAN_ICODE_NO_INT = 0x40, + CAN_ICODE_CERRIF, + CAN_ICODE_WAKIF, + CAN_ICODE_RXOVIF, + CAN_ICODE_ADDRERR_SERRIF, + CAN_ICODE_MABOV_SERRIF, + CAN_ICODE_TBCIF, + CAN_ICODE_MODIF, + CAN_ICODE_IVMIF, + CAN_ICODE_TEFIF, + CAN_ICODE_TXATIF, + CAN_ICODE_RESERVED +} CAN_ICODE; + +//! RXCODE + +typedef enum { + CAN_RXCODE_FIFO_CH1=1, + CAN_RXCODE_FIFO_CH2, + CAN_RXCODE_FIFO_CH3, + CAN_RXCODE_FIFO_CH4, + CAN_RXCODE_FIFO_CH5, + CAN_RXCODE_FIFO_CH6, + CAN_RXCODE_FIFO_CH7, + CAN_RXCODE_FIFO_CH8, + CAN_RXCODE_FIFO_CH9, + CAN_RXCODE_FIFO_CH10, + CAN_RXCODE_FIFO_CH11, + CAN_RXCODE_FIFO_CH12, + CAN_RXCODE_FIFO_CH13, + CAN_RXCODE_FIFO_CH14, + CAN_RXCODE_FIFO_CH15, + CAN_RXCODE_FIFO_CH16, + CAN_RXCODE_FIFO_CH17, + CAN_RXCODE_FIFO_CH18, + CAN_RXCODE_FIFO_CH19, + CAN_RXCODE_FIFO_CH20, + CAN_RXCODE_FIFO_CH21, + CAN_RXCODE_FIFO_CH22, + CAN_RXCODE_FIFO_CH23, + CAN_RXCODE_FIFO_CH24, + CAN_RXCODE_FIFO_CH25, + CAN_RXCODE_FIFO_CH26, + CAN_RXCODE_FIFO_CH27, + CAN_RXCODE_FIFO_CH28, + CAN_RXCODE_FIFO_CH29, + CAN_RXCODE_FIFO_CH30, + CAN_RXCODE_FIFO_CH31, + CAN_RXCODE_TOTAL_CHANNELS, + CAN_RXCODE_NO_INT = 0x40, + CAN_RXCODE_RESERVED +} CAN_RXCODE; + +//! TXCODE + +typedef enum { + CAN_TXCODE_FIFO_CH0, + CAN_TXCODE_FIFO_CH1, + CAN_TXCODE_FIFO_CH2, + CAN_TXCODE_FIFO_CH3, + CAN_TXCODE_FIFO_CH4, + CAN_TXCODE_FIFO_CH5, + CAN_TXCODE_FIFO_CH6, + CAN_TXCODE_FIFO_CH7, + CAN_TXCODE_FIFO_CH8, + CAN_TXCODE_FIFO_CH9, + CAN_TXCODE_FIFO_CH10, + CAN_TXCODE_FIFO_CH11, + CAN_TXCODE_FIFO_CH12, + CAN_TXCODE_FIFO_CH13, + CAN_TXCODE_FIFO_CH14, + CAN_TXCODE_FIFO_CH15, + CAN_TXCODE_FIFO_CH16, + CAN_TXCODE_FIFO_CH17, + CAN_TXCODE_FIFO_CH18, + CAN_TXCODE_FIFO_CH19, + CAN_TXCODE_FIFO_CH20, + CAN_TXCODE_FIFO_CH21, + CAN_TXCODE_FIFO_CH22, + CAN_TXCODE_FIFO_CH23, + CAN_TXCODE_FIFO_CH24, + CAN_TXCODE_FIFO_CH25, + CAN_TXCODE_FIFO_CH26, + CAN_TXCODE_FIFO_CH27, + CAN_TXCODE_FIFO_CH28, + CAN_TXCODE_FIFO_CH29, + CAN_TXCODE_FIFO_CH30, + CAN_TXCODE_FIFO_CH31, + CAN_TXCODE_TOTAL_CHANNELS, + CAN_TXCODE_NO_INT = 0x40, + CAN_TXCODE_RESERVED +} CAN_TXCODE; + +//! System Clock Selection + +typedef enum { + CAN_SYSCLK_40M, + CAN_SYSCLK_20M, + CAN_SYSCLK_10M +} CAN_SYSCLK_SPEED; + +//! CLKO Divide + +typedef enum { + OSC_CLKO_DIV1, + OSC_CLKO_DIV2, + OSC_CLKO_DIV4, + OSC_CLKO_DIV10 +} OSC_CLKO_DIVIDE; + +#endif // _DRV_CANFDSPI_DEFINES_H diff --git a/mcp2518fd_can_dfs.h b/mcp2518fd_can_dfs.h new file mode 100644 index 0000000..23b07d3 --- /dev/null +++ b/mcp2518fd_can_dfs.h @@ -0,0 +1,799 @@ +/******************************************************************************* + CAN FD SPI Driver: Register Header File + + Company: + Microchip Technology Inc. + + File Name: + drv_canfdspi_register.h + + Summary: + This header file contains SPI instruction defines, register address defines, + register structures, and reset values of registers. + + Description: + This file is used by the API. + *******************************************************************************/ + +//DOM-IGNORE-BEGIN +/******************************************************************************* +Copyright (c) 2018 Microchip Technology Inc. and its subsidiaries. + +Subject to your compliance with these terms, you may use Microchip software and +any derivatives exclusively with Microchip products. It is your responsibility +to comply with third party license terms applicable to your use of third party +software (including open source software) that may accompany Microchip software. + +THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, +IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES +OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. + +IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, +INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER +RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF +THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED +BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO +THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID +DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + *******************************************************************************/ +//DOM-IGNORE-END + +#ifndef _DRV_CANFDSPI_REGISTER_H +#define _DRV_CANFDSPI_REGISTER_H + +// ***************************************************************************** +// ***************************************************************************** +// Section: Included Files + +#include "drv_canfdspi_defines.h" + +// DOM-IGNORE-BEGIN +#ifdef __cplusplus // Provide C++ Compatibility +extern "C" { +#endif +// DOM-IGNORE-END + + +// ***************************************************************************** +// ***************************************************************************** +/* SPI Instruction Set */ + +#define cINSTRUCTION_RESET 0x00 +#define cINSTRUCTION_READ 0x03 +#define cINSTRUCTION_READ_CRC 0x0B +#define cINSTRUCTION_WRITE 0x02 +#define cINSTRUCTION_WRITE_CRC 0x0A +#define cINSTRUCTION_WRITE_SAFE 0x0C + +// ***************************************************************************** +// ***************************************************************************** +/* Register Addresses */ + +/* CAN FD Controller */ +#define cREGADDR_CiCON 0x000 +#define cREGADDR_CiNBTCFG 0x004 +#define cREGADDR_CiDBTCFG 0x008 +#define cREGADDR_CiTDC 0x00C + +#define cREGADDR_CiTBC 0x010 +#define cREGADDR_CiTSCON 0x014 +#define cREGADDR_CiVEC 0x018 +#define cREGADDR_CiINT 0x01C +#define cREGADDR_CiINTFLAG cREGADDR_CiINT +#define cREGADDR_CiINTENABLE (cREGADDR_CiINT+2) + +#define cREGADDR_CiRXIF 0x020 +#define cREGADDR_CiTXIF 0x024 +#define cREGADDR_CiRXOVIF 0x028 +#define cREGADDR_CiTXATIF 0x02C + +#define cREGADDR_CiTXREQ 0x030 +#define cREGADDR_CiTREC 0x034 +#define cREGADDR_CiBDIAG0 0x038 +#define cREGADDR_CiBDIAG1 0x03C + +#define cREGADDR_CiTEFCON 0x040 +#define cREGADDR_CiTEFSTA 0x044 +#define cREGADDR_CiTEFUA 0x048 +#define cREGADDR_CiFIFOBA 0x04C + +#define cREGADDR_CiFIFOCON 0x050 +#define cREGADDR_CiFIFOSTA 0x054 +#define cREGADDR_CiFIFOUA 0x058 +#define CiFIFO_OFFSET (3*4) + +#define cREGADDR_CiTXQCON 0x050 +#define cREGADDR_CiTXQSTA 0x054 +#define cREGADDR_CiTXQUA 0x058 + +// The filters start right after the FIFO control/status registers +#define cREGADDR_CiFLTCON (cREGADDR_CiFIFOCON+(CiFIFO_OFFSET*CAN_FIFO_TOTAL_CHANNELS)) +#define cREGADDR_CiFLTOBJ (cREGADDR_CiFLTCON+CAN_FIFO_TOTAL_CHANNELS) +#define cREGADDR_CiMASK (cREGADDR_CiFLTOBJ+4) + +#define CiFILTER_OFFSET (2*4) + +/* MCP25xxFD Specific */ +#define cREGADDR_OSC 0xE00 +#define cREGADDR_IOCON 0xE04 +#define cREGADDR_CRC 0xE08 +#define cREGADDR_ECCCON 0xE0C +#define cREGADDR_ECCSTA 0xE10 +#ifndef MCP2517FD +#define cREGADDR_DEVID 0xE14 +#endif + +/* RAM addresses */ +#if defined(MCP2517FD) || defined(MCP2518FD) +#define cRAM_SIZE 2048 +#endif + +#define cRAMADDR_START 0x400 +#define cRAMADDR_END (cRAMADDR_START+cRAM_SIZE) + +// ***************************************************************************** +// ***************************************************************************** +/* Register Structures */ + +// ***************************************************************************** +//! General 32-bit Register + +typedef union _REG_t { + uint8_t byte[4]; + uint32_t word; +} REG_t; + + +// ***************************************************************************** +// ***************************************************************************** +/* CAN FD Controller */ + +// ***************************************************************************** +//! CAN Control Register + +typedef union _REG_CiCON { + + struct { + uint32_t DNetFilterCount : 5; + uint32_t IsoCrcEnable : 1; + uint32_t ProtocolExceptionEventDisable : 1; + uint32_t unimplemented1 : 1; + uint32_t WakeUpFilterEnable : 1; + uint32_t WakeUpFilterTime : 2; + uint32_t unimplemented2 : 1; + uint32_t BitRateSwitchDisable : 1; + uint32_t unimplemented3 : 3; + uint32_t RestrictReTxAttempts : 1; + uint32_t EsiInGatewayMode : 1; + uint32_t SystemErrorToListenOnly : 1; + uint32_t StoreInTEF : 1; + uint32_t TXQEnable : 1; + uint32_t OpMode : 3; + uint32_t RequestOpMode : 3; + uint32_t AbortAllTx : 1; + uint32_t TxBandWidthSharing : 4; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiCON; + +// ***************************************************************************** +//! Nominal Bit Time Configuration Register + +typedef union _REG_CiNBTCFG { + + struct { + uint32_t SJW : 7; + uint32_t unimplemented1 : 1; + uint32_t TSEG2 : 7; + uint32_t unimplemented2 : 1; + uint32_t TSEG1 : 8; + uint32_t BRP : 8; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiNBTCFG; + +// ***************************************************************************** +//! Data Bit Time Configuration Register + +typedef union _REG_CiDBTCFG { + + struct { + uint32_t SJW : 4; + uint32_t unimplemented1 : 4; + uint32_t TSEG2 : 4; + uint32_t unimplemented2 : 4; + uint32_t TSEG1 : 5; + uint32_t unimplemented3 : 3; + uint32_t BRP : 8; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiDBTCFG; + +// ***************************************************************************** +//! Transmitter Delay Compensation Register + +typedef union _REG_CiTDC { + + struct { + uint32_t TDCValue : 6; + uint32_t unimplemented1 : 2; + uint32_t TDCOffset : 7; + uint32_t unimplemented2 : 1; + uint32_t TDCMode : 2; + uint32_t unimplemented3 : 6; + uint32_t SID11Enable : 1; + uint32_t EdgeFilterEnable : 1; + uint32_t unimplemented4 : 6; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiTDC; + +// ***************************************************************************** +//! Time Stamp Configuration Register + +typedef union _REG_CiTSCON { + + struct { + uint32_t TBCPrescaler : 10; + uint32_t unimplemented1 : 6; + uint32_t TBCEnable : 1; + uint32_t TimeStampEOF : 1; + uint32_t unimplemented2 : 14; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiTSCON; + +// ***************************************************************************** +//! Interrupt Vector Register + +typedef union _REG_CiVEC { + + struct { + uint32_t ICODE : 7; + uint32_t unimplemented1 : 1; + uint32_t FilterHit : 5; + uint32_t unimplemented2 : 3; + uint32_t TXCODE : 7; + uint32_t unimplemented3 : 1; + uint32_t RXCODE : 7; + uint32_t unimplemented4 : 1; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiVEC; + +// ***************************************************************************** +//! Interrupt Flags + +typedef struct _CAN_INT_FLAGS { + uint32_t TXIF : 1; + uint32_t RXIF : 1; + uint32_t TBCIF : 1; + uint32_t MODIF : 1; + uint32_t TEFIF : 1; + uint32_t unimplemented1 : 3; + + uint32_t ECCIF : 1; + uint32_t SPICRCIF : 1; + uint32_t TXATIF : 1; + uint32_t RXOVIF : 1; + uint32_t SERRIF : 1; + uint32_t CERRIF : 1; + uint32_t WAKIF : 1; + uint32_t IVMIF : 1; +} CAN_INT_FLAGS; + +// ***************************************************************************** +//! Interrupt Enables + +typedef struct _CAN_INT_ENABLES { + uint32_t TXIE : 1; + uint32_t RXIE : 1; + uint32_t TBCIE : 1; + uint32_t MODIE : 1; + uint32_t TEFIE : 1; + uint32_t unimplemented2 : 3; + + uint32_t ECCIE : 1; + uint32_t SPICRCIE : 1; + uint32_t TXATIE : 1; + uint32_t RXOVIE : 1; + uint32_t SERRIE : 1; + uint32_t CERRIE : 1; + uint32_t WAKIE : 1; + uint32_t IVMIE : 1; +} CAN_INT_ENABLES; + +// ***************************************************************************** +//! Interrupt Register + +typedef union _REG_CiINT { + + struct { + CAN_INT_FLAGS IF; + CAN_INT_ENABLES IE; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiINT; + +// ***************************************************************************** +//! Interrupt Flag Register + +typedef union _REG_CiINTFLAG { + CAN_INT_FLAGS IF; + uint16_t word; + uint8_t byte[2]; +} REG_CiINTFLAG; + +// ***************************************************************************** +//! Interrupt Enable Register + +typedef union _REG_CiINTENABLE { + CAN_INT_ENABLES IE; + uint16_t word; + uint8_t byte[2]; +} REG_CiINTENABLE; + +// ***************************************************************************** +//! Transmit/Receive Error Count Register + +typedef union _REG_CiTREC { + + struct { + uint32_t RxErrorCount : 8; + uint32_t TxErrorCount : 8; + uint32_t ErrorStateWarning : 1; + uint32_t RxErrorStateWarning : 1; + uint32_t TxErrorStateWarning : 1; + uint32_t RxErrorStatePassive : 1; + uint32_t TxErrorStatePassive : 1; + uint32_t TxErrorStateBusOff : 1; + uint32_t unimplemented1 : 10; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiTREC; + +// ***************************************************************************** +//! Diagnostic Register 0 + +typedef union _REG_CiBDIAG0 { + + struct { + uint32_t NRxErrorCount : 8; + uint32_t NTxErrorCount : 8; + uint32_t DRxErrorCount : 8; + uint32_t DTxErrorCount : 8; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiBDIAG0; + +// ***************************************************************************** +//! Diagnostic Register 1 + +typedef union _REG_CiBDIAG1 { + + struct { + uint32_t ErrorFreeMsgCount : 16; + + uint32_t NBit0Error : 1; + uint32_t NBit1Error : 1; + uint32_t NAckError : 1; + uint32_t NFormError : 1; + uint32_t NStuffError : 1; + uint32_t NCRCError : 1; + uint32_t unimplemented1 : 1; + uint32_t TXBOError : 1; + uint32_t DBit0Error : 1; + uint32_t DBit1Error : 1; + uint32_t DAckError : 1; + uint32_t DFormError : 1; + uint32_t DStuffError : 1; + uint32_t DCRCError : 1; + uint32_t ESI : 1; + uint32_t unimplemented2 : 1; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiBDIAG1; + +// ***************************************************************************** +//! Transmit Event FIFO Control Register + +typedef union _REG_CiTEFCON { + + struct { + uint32_t TEFNEIE : 1; + uint32_t TEFHFIE : 1; + uint32_t TEFFULIE : 1; + uint32_t TEFOVIE : 1; + uint32_t unimplemented1 : 1; + uint32_t TimeStampEnable : 1; + uint32_t unimplemented2 : 2; + uint32_t UINC : 1; + uint32_t unimplemented3 : 1; + uint32_t FRESET : 1; + uint32_t unimplemented4 : 13; + uint32_t FifoSize : 5; + uint32_t unimplemented5 : 3; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiTEFCON; + +// ***************************************************************************** +//! Transmit Event FIFO Status Register + +typedef union _REG_CiTEFSTA { + + struct { + uint32_t TEFNotEmptyIF : 1; + uint32_t TEFHalfFullIF : 1; + uint32_t TEFFullIF : 1; + uint32_t TEFOVIF : 1; + uint32_t unimplemented1 : 28; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiTEFSTA; + +// ***************************************************************************** +//! Transmit Queue Control Register + +typedef union _REG_CiTXQCON { + + struct { + uint32_t TxNotFullIE : 1; + uint32_t unimplemented1 : 1; + uint32_t TxEmptyIE : 1; + uint32_t unimplemented2 : 1; + uint32_t TxAttemptIE : 1; + uint32_t unimplemented3 : 2; + uint32_t TxEnable : 1; + uint32_t UINC : 1; + uint32_t TxRequest : 1; + uint32_t FRESET : 1; + uint32_t unimplemented4 : 5; + uint32_t TxPriority : 5; + uint32_t TxAttempts : 2; + uint32_t unimplemented5 : 1; + uint32_t FifoSize : 5; + uint32_t PayLoadSize : 3; + } txBF; + uint32_t word; + uint8_t byte[4]; +} REG_CiTXQCON; + +// ***************************************************************************** +//! Transmit Queue Status Register + +typedef union _REG_CiTXQSTA { + + struct { + uint32_t TxNotFullIF : 1; + uint32_t unimplemented1 : 1; + uint32_t TxEmptyIF : 1; + uint32_t unimplemented2 : 1; + uint32_t TxAttemptIF : 1; + uint32_t TxError : 1; + uint32_t TxLostArbitration : 1; + uint32_t TxAborted : 1; + uint32_t FifoIndex : 5; + uint32_t unimplemented3 : 19; + } txBF; + uint32_t word; + uint8_t byte[4]; +} REG_CiTXQSTA; + +// ***************************************************************************** +//! FIFO Control Register + +typedef union _REG_CiFIFOCON { + // Receive FIFO + + struct { + uint32_t RxNotEmptyIE : 1; + uint32_t RxHalfFullIE : 1; + uint32_t RxFullIE : 1; + uint32_t RxOverFlowIE : 1; + uint32_t unimplemented1 : 1; + uint32_t RxTimeStampEnable : 1; + uint32_t unimplemented2 : 1; + uint32_t TxEnable : 1; + uint32_t UINC : 1; + uint32_t unimplemented3 : 1; + uint32_t FRESET : 1; + uint32_t unimplemented4 : 13; + uint32_t FifoSize : 5; + uint32_t PayLoadSize : 3; + } rxBF; + + // Transmit FIFO + + struct { + uint32_t TxNotFullIE : 1; + uint32_t TxHalfFullIE : 1; + uint32_t TxEmptyIE : 1; + uint32_t unimplemented1 : 1; + uint32_t TxAttemptIE : 1; + uint32_t unimplemented2 : 1; + uint32_t RTREnable : 1; + uint32_t TxEnable : 1; + uint32_t UINC : 1; + uint32_t TxRequest : 1; + uint32_t FRESET : 1; + uint32_t unimplemented3 : 5; + uint32_t TxPriority : 5; + uint32_t TxAttempts : 2; + uint32_t unimplemented4 : 1; + uint32_t FifoSize : 5; + uint32_t PayLoadSize : 3; + } txBF; + uint32_t word; + uint8_t byte[4]; +} REG_CiFIFOCON; + +// ***************************************************************************** +//! FIFO Status Register + +typedef union _REG_CiFIFOSTA { + // Receive FIFO + + struct { + uint32_t RxNotEmptyIF : 1; + uint32_t RxHalfFullIF : 1; + uint32_t RxFullIF : 1; + uint32_t RxOverFlowIF : 1; + uint32_t unimplemented1 : 4; + uint32_t FifoIndex : 5; + uint32_t unimplemented2 : 19; + } rxBF; + + // Transmit FIFO + + struct { + uint32_t TxNotFullIF : 1; + uint32_t TxHalfFullIF : 1; + uint32_t TxEmptyIF : 1; + uint32_t unimplemented1 : 1; + uint32_t TxAttemptIF : 1; + uint32_t TxError : 1; + uint32_t TxLostArbitration : 1; + uint32_t TxAborted : 1; + uint32_t FifoIndex : 5; + uint32_t unimplemented2 : 19; + } txBF; + uint32_t word; + uint8_t byte[4]; +} REG_CiFIFOSTA; + +// ***************************************************************************** +//! FIFO User Address Register + +typedef union _REG_CiFIFOUA { + + struct { + uint32_t UserAddress : 12; + uint32_t unimplemented1 : 20; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiFIFOUA; + +// ***************************************************************************** +//! Filter Control Register + +typedef union _REG_CiFLTCON_BYTE { + + struct { + uint32_t BufferPointer : 5; + uint32_t unimplemented1 : 2; + uint32_t Enable : 1; + } bF; + uint8_t byte; +} REG_CiFLTCON_BYTE; + +// ***************************************************************************** +//! Filter Object Register + +typedef union _REG_CiFLTOBJ { + CAN_FILTEROBJ_ID bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiFLTOBJ; + +// ***************************************************************************** +//! Mask Object Register + +typedef union _REG_CiMASK { + CAN_MASKOBJ_ID bF; + uint32_t word; + uint8_t byte[4]; +} REG_CiMASK; + + +// ***************************************************************************** +// ***************************************************************************** +/* MCP25xxFD Specific */ + +// ***************************************************************************** +//! Oscillator Control Register + +typedef union _REG_OSC { + + struct { + uint32_t PllEnable : 1; + uint32_t unimplemented1 : 1; + uint32_t OscDisable : 1; +#ifdef MCP2517FD + uint32_t unimplemented2 : 1; +#else + uint32_t LowPowerModeEnable : 1; +#endif + uint32_t SCLKDIV : 1; + uint32_t CLKODIV : 2; + uint32_t unimplemented3 : 1; + uint32_t PllReady : 1; + uint32_t unimplemented4 : 1; + uint32_t OscReady : 1; + uint32_t unimplemented5 : 1; + uint32_t SclkReady : 1; + uint32_t unimplemented6 : 19; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_OSC; + +// ***************************************************************************** +//! I/O Control Register + +typedef union _REG_IOCON { + + struct { + uint32_t TRIS0 : 1; + uint32_t TRIS1 : 1; + uint32_t unimplemented1 : 2; + uint32_t ClearAutoSleepOnMatch : 1; + uint32_t AutoSleepEnable : 1; + uint32_t XcrSTBYEnable : 1; + uint32_t unimplemented2 : 1; + uint32_t LAT0 : 1; + uint32_t LAT1 : 1; + uint32_t unimplemented3 : 5; + uint32_t HVDETSEL : 1; + uint32_t GPIO0 : 1; + uint32_t GPIO1 : 1; + uint32_t unimplemented4 : 6; + uint32_t PinMode0 : 1; + uint32_t PinMode1 : 1; + uint32_t unimplemented5 : 2; + uint32_t TXCANOpenDrain : 1; + uint32_t SOFOutputEnable : 1; + uint32_t INTPinOpenDrain : 1; + uint32_t unimplemented6 : 1; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_IOCON; + +// ***************************************************************************** +//! CRC Regsiter + +typedef union _REG_CRC { + + struct { + uint32_t CRC : 16; + uint32_t CRCERRIF : 1; + uint32_t FERRIF : 1; + uint32_t unimplemented1 : 6; + uint32_t CRCERRIE : 1; + uint32_t FERRIE : 1; + uint32_t unimplemented2 : 6; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_CRC; + +// ***************************************************************************** +//! ECC Control Register + +typedef union _REG_ECCCON { + + struct { + uint32_t EccEn : 1; + uint32_t SECIE : 1; + uint32_t DEDIE : 1; + uint32_t unimplemented1 : 5; + uint32_t Parity : 7; + uint32_t unimplemented2 : 17; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_ECCCON; + +// ***************************************************************************** +//! ECC Status Register + +typedef union _REG_ECCSTA { + + struct { + uint32_t unimplemented1 : 1; + uint32_t SECIF : 1; + uint32_t DEDIF : 1; + uint32_t unimplemented2 : 13; + uint32_t ErrorAddress : 12; + uint32_t unimplemented3 : 4; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_ECCSTA; + +// ***************************************************************************** +//! DEVID Register + +#ifndef MCP2517FD +typedef union _REG_DEVID { + + struct { + uint32_t REV : 4; + uint32_t DEV : 4; + uint32_t unimplemented : 24; + } bF; + uint32_t word; + uint8_t byte[4]; +} REG_DEVID; +#endif + + +// ***************************************************************************** +// ***************************************************************************** +/* Register Reset Values */ + +// ***************************************************************************** +/* CAN FD Controller */ + +// Control Register Reset Values up to FIFOs +static const uint32_t canControlResetValues[] = { + /* Address 0x000 to 0x00C */ + 0x04980760, 0x003E0F0F, 0x000E0303, 0x00021000, + /* Address 0x010 to 0x01C */ + 0x00000000, 0x00000000, 0x40400040, 0x00000000, + /* Address 0x020 to 0x02C */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* Address 0x030 to 0x03C */ + 0x00000000, 0x00200000, 0x00000000, 0x00000000, + /* Address 0x040 to 0x04C */ + 0x00000400, 0x00000000, 0x00000000, 0x00000000 +}; + +// FIFO Register Reset Values +static const uint32_t canFifoResetValues[] = { + 0x00600400, 0x00000000, 0x00000000 +}; + +// Filter Control Register Reset Values +static const uint32_t canFilterControlResetValue = 0x00000000; + +// Filter and Mask Object Reset Values +static const uint32_t canFilterObjectResetValues[] = { + 0x00000000, 0x00000000 +}; + +// ***************************************************************************** +/* MCP25xxFD */ + +#if defined(MCP2517FD) || defined(MCP2518FD) +static const uint32_t mcp25xxfdControlResetValues[] = { + 0x00000460, 0x00000003, 0x00000000, 0x00000000, 0x00000000 +}; +#endif + + +#endif // _DRV_CANFDSPI_REGISTER_H diff --git a/mcp2518fd_canfdspi_api.cpp b/mcp2518fd_canfdspi_api.cpp new file mode 100644 index 0000000..3cdf799 --- /dev/null +++ b/mcp2518fd_canfdspi_api.cpp @@ -0,0 +1,3890 @@ +/******************************************************************************* + CAN FD SPI Driver: Implementation + + Company: + Microchip Technology Inc. + + File Name: + drv_canfdspi_api.c + + Summary: + API implementation. + + Description: + . + *******************************************************************************/ + +//DOM-IGNORE-BEGIN +/******************************************************************************* +Copyright (c) 2018 Microchip Technology Inc. and its subsidiaries. + +Subject to your compliance with these terms, you may use Microchip software and +any derivatives exclusively with Microchip products. It is your responsibility +to comply with third party license terms applicable to your use of third party +software (including open source software) that may accompany Microchip software. + +THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, +IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES +OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. + +IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, +INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER +RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF +THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED +BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO +THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID +DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + *******************************************************************************/ +//DOM-IGNORE-END + +// ***************************************************************************** +// ***************************************************************************** +// Section: Included Files + +#include "drv_canfdspi_api.h" +#include "drv_canfdspi_register.h" +#include "drv_canfdspi_defines.h" +#include "../spi/drv_spi.h" + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Defines + +#define CRCBASE 0xFFFF +#define CRCUPPER 1 + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Variables + +//! SPI Transmit buffer +uint8_t spiTransmitBuffer[SPI_DEFAULT_BUFFER_LENGTH]; + +//! SPI Receive buffer +uint8_t spiReceiveBuffer[SPI_DEFAULT_BUFFER_LENGTH]; + +//! Reverse order of bits in byte +const uint8_t BitReverseTable256[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +//! Look-up table for CRC calculation +const uint16_t crc16_table[256] = { + 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, + 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, + 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, + 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, + 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, + 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, + 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, + 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, + 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, + 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, + 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, + 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, + 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, + 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, + 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, + 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, + 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 +}; + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Reset + +int8_t DRV_CANFDSPI_Reset(CANFDSPI_MODULE_ID index) +{ + uint16_t spiTransferSize = 2; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) (cINSTRUCTION_RESET << 4); + spiTransmitBuffer[1] = 0; + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: SPI Access Functions + +int8_t DRV_CANFDSPI_ReadByte(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t *rxd) +{ + uint16_t spiTransferSize = 3; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + spiTransmitBuffer[2] = 0; + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + // Update data + *rxd = spiReceiveBuffer[2]; + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteByte(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t txd) +{ + uint16_t spiTransferSize = 3; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + spiTransmitBuffer[2] = txd; + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReadWord(CANFDSPI_MODULE_ID index, uint16_t address, uint32_t *rxd) +{ + uint8_t i; + uint32_t x; + uint16_t spiTransferSize = 6; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + if (spiTransferError) { + return spiTransferError; + } + + // Update data + *rxd = 0; + for (i = 2; i < 6; i++) { + x = (uint32_t) spiReceiveBuffer[i]; + *rxd += x << ((i - 2)*8); + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteWord(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t txd) +{ + uint8_t i; + uint16_t spiTransferSize = 6; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + + // Split word into 4 bytes and add them to buffer + for (i = 0; i < 4; i++) { + spiTransmitBuffer[i + 2] = (uint8_t) ((txd >> (i * 8)) & 0xFF); + } + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReadHalfWord(CANFDSPI_MODULE_ID index, uint16_t address, uint16_t *rxd) +{ + uint8_t i; + uint32_t x; + uint16_t spiTransferSize = 4; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + if (spiTransferError) { + return spiTransferError; + } + + // Update data + *rxd = 0; + for (i = 2; i < 4; i++) { + x = (uint32_t) spiReceiveBuffer[i]; + *rxd += x << ((i - 2)*8); + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteHalfWord(CANFDSPI_MODULE_ID index, uint16_t address, + uint16_t txd) +{ + uint8_t i; + uint16_t spiTransferSize = 4; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + + // Split word into 2 bytes and add them to buffer + for (i = 0; i < 2; i++) { + spiTransmitBuffer[i + 2] = (uint8_t) ((txd >> (i * 8)) & 0xFF); + } + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteByteSafe(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t txd) +{ + uint16_t crcResult = 0; + uint16_t spiTransferSize = 5; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE_SAFE << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + spiTransmitBuffer[2] = txd; + + // Add CRC + crcResult = DRV_CANFDSPI_CalculateCRC16(spiTransmitBuffer, 3); + spiTransmitBuffer[3] = (crcResult >> 8) & 0xFF; + spiTransmitBuffer[4] = crcResult & 0xFF; + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteWordSafe(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t txd) +{ + uint8_t i; + uint16_t crcResult = 0; + uint16_t spiTransferSize = 8; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE_SAFE << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + + // Split word into 4 bytes and add them to buffer + for (i = 0; i < 4; i++) { + spiTransmitBuffer[i + 2] = (uint8_t) ((txd >> (i * 8)) & 0xFF); + } + + // Add CRC + crcResult = DRV_CANFDSPI_CalculateCRC16(spiTransmitBuffer, 6); + spiTransmitBuffer[6] = (crcResult >> 8) & 0xFF; + spiTransmitBuffer[7] = crcResult & 0xFF; + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReadByteArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *rxd, uint16_t nBytes) +{ + uint16_t i; + uint16_t spiTransferSize = nBytes + 2; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + + // Clear data + for (i = 2; i < spiTransferSize; i++) { + spiTransmitBuffer[i] = 0; + } + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + // Update data + for (i = 0; i < nBytes; i++) { + rxd[i] = spiReceiveBuffer[i + 2]; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReadByteArrayWithCRC(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *rxd, uint16_t nBytes, bool fromRam, bool* crcIsCorrect) +{ + uint8_t i; + uint16_t crcFromSpiSlave = 0; + uint16_t crcAtController = 0; + uint16_t spiTransferSize = nBytes + 5; //first two bytes for sending command & address, third for size, last two bytes for CRC + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ_CRC << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + if (fromRam) { + spiTransmitBuffer[2] = nBytes >> 2; + } else { + spiTransmitBuffer[2] = nBytes; + } + + // Clear data + for (i = 3; i < spiTransferSize; i++) { + spiTransmitBuffer[i] = 0; + } + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + if (spiTransferError) { + return spiTransferError; + } + + // Get CRC from controller + crcFromSpiSlave = (uint16_t) (spiReceiveBuffer[spiTransferSize - 2] << 8) + (uint16_t) (spiReceiveBuffer[spiTransferSize - 1]); + + // Use the receive buffer to calculate CRC + // First three bytes need to be command + spiReceiveBuffer[0] = spiTransmitBuffer[0]; + spiReceiveBuffer[1] = spiTransmitBuffer[1]; + spiReceiveBuffer[2] = spiTransmitBuffer[2]; + crcAtController = DRV_CANFDSPI_CalculateCRC16(spiReceiveBuffer, nBytes + 3); + + // Compare CRC readings + if (crcFromSpiSlave == crcAtController) { + *crcIsCorrect = true; + } else { + *crcIsCorrect = false; + } + + // Update data + for (i = 0; i < nBytes; i++) { + rxd[i] = spiReceiveBuffer[i + 3]; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteByteArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *txd, uint16_t nBytes) +{ + uint16_t i; + uint16_t spiTransferSize = nBytes + 2; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + + // Add data + for (i = 2; i < spiTransferSize; i++) { + spiTransmitBuffer[i] = txd[i - 2]; + } + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteByteArrayWithCRC(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *txd, uint16_t nBytes, bool fromRam) +{ + uint16_t i; + uint16_t crcResult = 0; + uint16_t spiTransferSize = nBytes + 5; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE_CRC << 4) + ((address >> 8) & 0xF)); + spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); + if (fromRam) { + spiTransmitBuffer[2] = nBytes >> 2; + } else { + spiTransmitBuffer[2] = nBytes; + } + + // Add data + for (i = 0; i < nBytes; i++) { + spiTransmitBuffer[i + 3] = txd[i]; + } + + // Add CRC + crcResult = DRV_CANFDSPI_CalculateCRC16(spiTransmitBuffer, spiTransferSize - 2); + spiTransmitBuffer[spiTransferSize - 2] = (uint8_t) ((crcResult >> 8) & 0xFF); + spiTransmitBuffer[spiTransferSize - 1] = (uint8_t) (crcResult & 0xFF); + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReadWordArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t *rxd, uint16_t nWords) +{ + uint16_t i, j, n; + REG_t w; + uint16_t spiTransferSize = nWords * 4 + 2; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF); + spiTransmitBuffer[1] = address & 0xFF; + + // Clear data + for (i = 2; i < spiTransferSize; i++) { + spiTransmitBuffer[i] = 0; + } + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + if (spiTransferError) { + return spiTransferError; + } + + // Convert Byte array to Word array + n = 2; + for (i = 0; i < nWords; i++) { + w.word = 0; + for (j = 0; j < 4; j++, n++) { + w.byte[j] = spiReceiveBuffer[n]; + } + rxd[i] = w.word; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_WriteWordArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t *txd, uint16_t nWords) +{ + uint16_t i, j, n; + REG_t w; + uint16_t spiTransferSize = nWords * 4 + 2; + int8_t spiTransferError = 0; + + // Compose command + spiTransmitBuffer[0] = (cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF); + spiTransmitBuffer[1] = address & 0xFF; + + // Convert ByteArray to word array + n = 2; + for (i = 0; i < nWords; i++) { + w.word = txd[i]; + for (j = 0; j < 4; j++, n++) { + spiTransmitBuffer[n] = w.byte[j]; + } + } + + spiTransferError = DRV_SPI_TransferData(index, spiTransmitBuffer, spiReceiveBuffer, spiTransferSize); + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Configuration + +int8_t DRV_CANFDSPI_Configure(CANFDSPI_MODULE_ID index, CAN_CONFIG* config) +{ + REG_CiCON ciCon; + int8_t spiTransferError = 0; + + ciCon.word = canControlResetValues[cREGADDR_CiCON / 4]; + + ciCon.bF.DNetFilterCount = config->DNetFilterCount; + ciCon.bF.IsoCrcEnable = config->IsoCrcEnable; + ciCon.bF.ProtocolExceptionEventDisable = config->ProtocolExpectionEventDisable; + ciCon.bF.WakeUpFilterEnable = config->WakeUpFilterEnable; + ciCon.bF.WakeUpFilterTime = config->WakeUpFilterTime; + ciCon.bF.BitRateSwitchDisable = config->BitRateSwitchDisable; + ciCon.bF.RestrictReTxAttempts = config->RestrictReTxAttempts; + ciCon.bF.EsiInGatewayMode = config->EsiInGatewayMode; + ciCon.bF.SystemErrorToListenOnly = config->SystemErrorToListenOnly; + ciCon.bF.StoreInTEF = config->StoreInTEF; + ciCon.bF.TXQEnable = config->TXQEnable; + ciCon.bF.TxBandWidthSharing = config->TxBandWidthSharing; + + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiCON, ciCon.word); + if (spiTransferError) { + return -1; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ConfigureObjectReset(CAN_CONFIG* config) +{ + REG_CiCON ciCon; + ciCon.word = canControlResetValues[cREGADDR_CiCON / 4]; + + config->DNetFilterCount = ciCon.bF.DNetFilterCount; + config->IsoCrcEnable = ciCon.bF.IsoCrcEnable; + config->ProtocolExpectionEventDisable = ciCon.bF.ProtocolExceptionEventDisable; + config->WakeUpFilterEnable = ciCon.bF.WakeUpFilterEnable; + config->WakeUpFilterTime = ciCon.bF.WakeUpFilterTime; + config->BitRateSwitchDisable = ciCon.bF.BitRateSwitchDisable; + config->RestrictReTxAttempts = ciCon.bF.RestrictReTxAttempts; + config->EsiInGatewayMode = ciCon.bF.EsiInGatewayMode; + config->SystemErrorToListenOnly = ciCon.bF.SystemErrorToListenOnly; + config->StoreInTEF = ciCon.bF.StoreInTEF; + config->TXQEnable = ciCon.bF.TXQEnable; + config->TxBandWidthSharing = ciCon.bF.TxBandWidthSharing; + + return 0; +} + +// ***************************************************************************** +// ***************************************************************************** +// Section: Operating mode + +int8_t DRV_CANFDSPI_OperationModeSelect(CANFDSPI_MODULE_ID index, + CAN_OPERATION_MODE opMode) +{ + uint8_t d = 0; + int8_t spiTransferError = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON + 3, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= ~0x07; + d |= opMode; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiCON + 3, d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +CAN_OPERATION_MODE DRV_CANFDSPI_OperationModeGet(CANFDSPI_MODULE_ID index) +{ + uint8_t d = 0; + CAN_OPERATION_MODE mode = CAN_INVALID_MODE; + int8_t spiTransferError = 0; + + // Read Opmode + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON + 2, &d); + if (spiTransferError) { + return CAN_INVALID_MODE; + } + + // Get Opmode bits + d = (d >> 5) & 0x7; + + // Decode Opmode + switch (d) { + case CAN_NORMAL_MODE: + mode = CAN_NORMAL_MODE; + break; + case CAN_SLEEP_MODE: + mode = CAN_SLEEP_MODE; + break; + case CAN_INTERNAL_LOOPBACK_MODE: + mode = CAN_INTERNAL_LOOPBACK_MODE; + break; + case CAN_EXTERNAL_LOOPBACK_MODE: + mode = CAN_EXTERNAL_LOOPBACK_MODE; + break; + case CAN_LISTEN_ONLY_MODE: + mode = CAN_LISTEN_ONLY_MODE; + break; + case CAN_CONFIGURATION_MODE: + mode = CAN_CONFIGURATION_MODE; + break; + case CAN_CLASSIC_MODE: + mode = CAN_CLASSIC_MODE; + break; + case CAN_RESTRICTED_MODE: + mode = CAN_RESTRICTED_MODE; + break; + default: + mode = CAN_INVALID_MODE; + break; + } + + return mode; +} + +int8_t DRV_CANFDSPI_LowPowerModeEnable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + +#ifdef MCP2517FD + // LPM not implemented + spiTransferError = -100; +#else + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d |= 0x08; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, d); + if (spiTransferError) { + return -2; + } +#endif + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_LowPowerModeDisable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + +#ifdef MCP2517FD + // LPM not implemented + spiTransferError = -100; +#else + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= ~0x08; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, d); + if (spiTransferError) { + return -2; + } +#endif + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: CAN Transmit + +int8_t DRV_CANFDSPI_TransmitChannelConfigure(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_CONFIG* config) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Setup FIFO + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = canFifoResetValues[0]; + ciFifoCon.txBF.TxEnable = 1; + ciFifoCon.txBF.FifoSize = config->FifoSize; + ciFifoCon.txBF.PayLoadSize = config->PayLoadSize; + ciFifoCon.txBF.TxAttempts = config->TxAttempts; + ciFifoCon.txBF.TxPriority = config->TxPriority; + ciFifoCon.txBF.RTREnable = config->RTREnable; + + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_WriteWord(index, a, ciFifoCon.word); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelConfigureObjectReset(CAN_TX_FIFO_CONFIG* config) +{ + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = canFifoResetValues[0]; + + config->RTREnable = ciFifoCon.txBF.RTREnable; + config->TxPriority = ciFifoCon.txBF.TxPriority; + config->TxAttempts = ciFifoCon.txBF.TxAttempts; + config->FifoSize = ciFifoCon.txBF.FifoSize; + config->PayLoadSize = ciFifoCon.txBF.PayLoadSize; + + return 0; +} + +int8_t DRV_CANFDSPI_TransmitQueueConfigure(CANFDSPI_MODULE_ID index, + CAN_TX_QUEUE_CONFIG* config) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Setup FIFO + REG_CiTXQCON ciFifoCon; + ciFifoCon.word = canFifoResetValues[0]; + + ciFifoCon.txBF.TxEnable = 1; + ciFifoCon.txBF.FifoSize = config->FifoSize; + ciFifoCon.txBF.PayLoadSize = config->PayLoadSize; + ciFifoCon.txBF.TxAttempts = config->TxAttempts; + ciFifoCon.txBF.TxPriority = config->TxPriority; + + a = cREGADDR_CiTXQCON; + spiTransferError = DRV_CANFDSPI_WriteWord(index, a, ciFifoCon.word); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitQueueConfigureObjectReset(CAN_TX_QUEUE_CONFIG* config) +{ + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = canFifoResetValues[0]; + + config->TxPriority = ciFifoCon.txBF.TxPriority; + config->TxAttempts = ciFifoCon.txBF.TxAttempts; + config->FifoSize = ciFifoCon.txBF.FifoSize; + config->PayLoadSize = ciFifoCon.txBF.PayLoadSize; + + return 0; +} + +int8_t DRV_CANFDSPI_TransmitChannelLoad(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_MSGOBJ* txObj, + uint8_t *txd, uint32_t txdNumBytes, bool flush) +{ + uint16_t a; + uint32_t fifoReg[3]; + uint32_t dataBytesInObject; + REG_CiFIFOCON ciFifoCon; + REG_CiFIFOSTA ciFifoSta; + REG_CiFIFOUA ciFifoUa; + int8_t spiTransferError = 0; + + // Get FIFO registers + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 3); + if (spiTransferError) { + return -1; + } + + // Check that it is a transmit buffer + ciFifoCon.word = fifoReg[0]; + if (!ciFifoCon.txBF.TxEnable) { + return -2; + } + + // Check that DLC is big enough for data + dataBytesInObject = DRV_CANFDSPI_DlcToDataBytes((CAN_DLC) txObj->bF.ctrl.DLC); + if (dataBytesInObject < txdNumBytes) { + return -3; + } + + // Get status + ciFifoSta.word = fifoReg[1]; + + // Get address + ciFifoUa.word = fifoReg[2]; +#ifdef USERADDRESS_TIMES_FOUR + a = 4 * ciFifoUa.bF.UserAddress; +#else + a = ciFifoUa.bF.UserAddress; +#endif + a += cRAMADDR_START; + + uint8_t txBuffer[MAX_MSG_SIZE]; + + txBuffer[0] = txObj->byte[0]; //not using 'for' to reduce no of instructions + txBuffer[1] = txObj->byte[1]; + txBuffer[2] = txObj->byte[2]; + txBuffer[3] = txObj->byte[3]; + + txBuffer[4] = txObj->byte[4]; + txBuffer[5] = txObj->byte[5]; + txBuffer[6] = txObj->byte[6]; + txBuffer[7] = txObj->byte[7]; + + uint8_t i; + for (i = 0; i < txdNumBytes; i++) { + txBuffer[i + 8] = txd[i]; + } + + // Make sure we write a multiple of 4 bytes to RAM + uint16_t n = 0; + uint8_t j = 0; + + if (txdNumBytes % 4) { + // Need to add bytes + n = 4 - (txdNumBytes % 4); + i = txdNumBytes + 8; + + for (j = 0; j < n; j++) { + txBuffer[i + 8 + j] = 0; + } + } + + spiTransferError = DRV_CANFDSPI_WriteByteArray(index, a, txBuffer, txdNumBytes + 8 + n); + if (spiTransferError) { + return -4; + } + + // Set UINC and TXREQ + spiTransferError = DRV_CANFDSPI_TransmitChannelUpdate(index, channel, flush); + if (spiTransferError) { + return -5; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelFlush(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel) +{ + uint8_t d = 0; + uint16_t a = 0; + int8_t spiTransferError = 0; + + // Address of TXREQ + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + a += 1; + + // Set TXREQ + d = 0x02; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, d); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelStatusGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_STATUS* status) +{ + uint16_t a = 0; + uint32_t sta = 0; + uint32_t fifoReg[2]; + REG_CiFIFOSTA ciFifoSta; + REG_CiFIFOCON ciFifoCon; + int8_t spiTransferError = 0; + + // Get FIFO registers + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 2); + if (spiTransferError) { + return -1; + } + + // Update data + ciFifoCon.word = fifoReg[0]; + ciFifoSta.word = fifoReg[1]; + + // Update status + sta = ciFifoSta.byte[0]; + + if (ciFifoCon.txBF.TxRequest) { + sta |= CAN_TX_FIFO_TRANSMITTING; + } + + *status = (CAN_TX_FIFO_STATUS) (sta & CAN_TX_FIFO_STATUS_MASK); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelReset(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel) +{ + return DRV_CANFDSPI_ReceiveChannelReset(index, channel); +} + +int8_t DRV_CANFDSPI_TransmitChannelUpdate(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, bool flush) +{ + uint16_t a; + REG_CiFIFOCON ciFifoCon; + int8_t spiTransferError = 0; + + // Set UINC + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET) + 1; // Byte that contains FRESET + ciFifoCon.word = 0; + ciFifoCon.txBF.UINC = 1; + + // Set TXREQ + if (flush) { + ciFifoCon.txBF.TxRequest = 1; + } + + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[1]); + if (spiTransferError) { + return -1; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitRequestSet(CANFDSPI_MODULE_ID index, + CAN_TXREQ_CHANNEL txreq) +{ + int8_t spiTransferError = 0; + + // Write TXREQ register + uint32_t w = txreq; + + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTXREQ, w); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitRequestGet(CANFDSPI_MODULE_ID index, + uint32_t* txreq) +{ + int8_t spiTransferError = 0; + + spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTXREQ, txreq); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelAbort(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel) +{ + uint16_t a; + uint8_t d; + int8_t spiTransferError = 0; + + // Address + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + a += 1; // byte address of TXREQ + + // Clear TXREQ + d = 0x00; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, d); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitAbortAll(CANFDSPI_MODULE_ID index) +{ + uint8_t d; + int8_t spiTransferError = 0; + + // Read CiCON byte 3 + spiTransferError = DRV_CANFDSPI_ReadByte(index, (cREGADDR_CiCON + 3), &d); + if (spiTransferError) { + return -1; + } + + // Modify + d |= 0x8; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, (cREGADDR_CiCON + 3), d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitBandWidthSharingSet(CANFDSPI_MODULE_ID index, + CAN_TX_BANDWITH_SHARING txbws) +{ + uint8_t d = 0; + int8_t spiTransferError = 0; + + // Read CiCON byte 3 + spiTransferError = DRV_CANFDSPI_ReadByte(index, (cREGADDR_CiCON + 3), &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= 0x0f; + d |= (txbws << 4); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, (cREGADDR_CiCON + 3), d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: CAN Receive + +int8_t DRV_CANFDSPI_FilterObjectConfigure(CANFDSPI_MODULE_ID index, + CAN_FILTER filter, CAN_FILTEROBJ_ID* id) +{ + uint16_t a; + REG_CiFLTOBJ fObj; + int8_t spiTransferError = 0; + + // Setup + fObj.word = 0; + fObj.bF = *id; + a = cREGADDR_CiFLTOBJ + (filter * CiFILTER_OFFSET); + + spiTransferError = DRV_CANFDSPI_WriteWord(index, a, fObj.word); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_FilterMaskConfigure(CANFDSPI_MODULE_ID index, + CAN_FILTER filter, CAN_MASKOBJ_ID* mask) +{ + uint16_t a; + REG_CiMASK mObj; + int8_t spiTransferError = 0; + + // Setup + mObj.word = 0; + mObj.bF = *mask; + a = cREGADDR_CiMASK + (filter * CiFILTER_OFFSET); + + spiTransferError = DRV_CANFDSPI_WriteWord(index, a, mObj.word); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_FilterToFifoLink(CANFDSPI_MODULE_ID index, + CAN_FILTER filter, CAN_FIFO_CHANNEL channel, bool enable) +{ + uint16_t a; + REG_CiFLTCON_BYTE fCtrl; + int8_t spiTransferError = 0; + + // Enable + if (enable) { + fCtrl.bF.Enable = 1; + } else { + fCtrl.bF.Enable = 0; + } + + // Link + fCtrl.bF.BufferPointer = channel; + a = cREGADDR_CiFLTCON + filter; + + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, fCtrl.byte); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_FilterEnable(CANFDSPI_MODULE_ID index, CAN_FILTER filter) +{ + uint16_t a; + REG_CiFLTCON_BYTE fCtrl; + int8_t spiTransferError = 0; + + // Read + a = cREGADDR_CiFLTCON + filter; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &fCtrl.byte); + if (spiTransferError) { + return -1; + } + + // Modify + fCtrl.bF.Enable = 1; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, fCtrl.byte); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_FilterDisable(CANFDSPI_MODULE_ID index, CAN_FILTER filter) +{ + uint16_t a; + REG_CiFLTCON_BYTE fCtrl; + int8_t spiTransferError = 0; + + // Read + a = cREGADDR_CiFLTCON + filter; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &fCtrl.byte); + if (spiTransferError) { + return -1; + } + + // Modify + fCtrl.bF.Enable = 0; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, fCtrl.byte); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_DeviceNetFilterCountSet(CANFDSPI_MODULE_ID index, + CAN_DNET_FILTER_SIZE dnfc) +{ + uint8_t d = 0; + int8_t spiTransferError = 0; + + // Read CiCON byte 0 + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= 0x1f; + d |= dnfc; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiCON, d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveChannelConfigure(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_CONFIG* config) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + if (channel == CAN_TXQUEUE_CH0) { + return -100; + } + + // Setup FIFO + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = canFifoResetValues[0]; + + ciFifoCon.rxBF.TxEnable = 0; + ciFifoCon.rxBF.FifoSize = config->FifoSize; + ciFifoCon.rxBF.PayLoadSize = config->PayLoadSize; + ciFifoCon.rxBF.RxTimeStampEnable = config->RxTimeStampEnable; + + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_WriteWord(index, a, ciFifoCon.word); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveChannelConfigureObjectReset(CAN_RX_FIFO_CONFIG* config) +{ + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = canFifoResetValues[0]; + + config->FifoSize = ciFifoCon.rxBF.FifoSize; + config->PayLoadSize = ciFifoCon.rxBF.PayLoadSize; + config->RxTimeStampEnable = ciFifoCon.rxBF.RxTimeStampEnable; + + return 0; +} + +int8_t DRV_CANFDSPI_ReceiveChannelStatusGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_STATUS* status) +{ + uint16_t a; + REG_CiFIFOSTA ciFifoSta; + int8_t spiTransferError = 0; + + // Read + ciFifoSta.word = 0; + a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Update data + *status = (CAN_RX_FIFO_STATUS) (ciFifoSta.byte[0] & 0x0F); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveMessageGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_MSGOBJ* rxObj, + uint8_t *rxd, uint8_t nBytes) +{ + uint8_t n = 0; + uint8_t i = 0; + uint16_t a; + uint32_t fifoReg[3]; + REG_CiFIFOCON ciFifoCon; + REG_CiFIFOSTA ciFifoSta; + REG_CiFIFOUA ciFifoUa; + int8_t spiTransferError = 0; + + // Get FIFO registers + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 3); + if (spiTransferError) { + return -1; + } + + // Check that it is a receive buffer + ciFifoCon.word = fifoReg[0]; + if (ciFifoCon.txBF.TxEnable) { + return -2; + } + + // Get Status + ciFifoSta.word = fifoReg[1]; + + // Get address + ciFifoUa.word = fifoReg[2]; +#ifdef USERADDRESS_TIMES_FOUR + a = 4 * ciFifoUa.bF.UserAddress; +#else + a = ciFifoUa.bF.UserAddress; +#endif + a += cRAMADDR_START; + + // Number of bytes to read + n = nBytes + 8; // Add 8 header bytes + + if (ciFifoCon.rxBF.RxTimeStampEnable) { + n += 4; // Add 4 time stamp bytes + } + + // Make sure we read a multiple of 4 bytes from RAM + if (n % 4) { + n = n + 4 - (n % 4); + } + + // Read rxObj using one access + uint8_t ba[MAX_MSG_SIZE]; + + if (n > MAX_MSG_SIZE) { + n = MAX_MSG_SIZE; + } + + spiTransferError = DRV_CANFDSPI_ReadByteArray(index, a, ba, n); + if (spiTransferError) { + return -3; + } + + // Assign message header + REG_t myReg; + + myReg.byte[0] = ba[0]; + myReg.byte[1] = ba[1]; + myReg.byte[2] = ba[2]; + myReg.byte[3] = ba[3]; + rxObj->word[0] = myReg.word; + + myReg.byte[0] = ba[4]; + myReg.byte[1] = ba[5]; + myReg.byte[2] = ba[6]; + myReg.byte[3] = ba[7]; + rxObj->word[1] = myReg.word; + + if (ciFifoCon.rxBF.RxTimeStampEnable) { + myReg.byte[0] = ba[8]; + myReg.byte[1] = ba[9]; + myReg.byte[2] = ba[10]; + myReg.byte[3] = ba[11]; + rxObj->word[2] = myReg.word; + + // Assign message data + for (i = 0; i < nBytes; i++) { + rxd[i] = ba[i + 12]; + } + } else { + rxObj->word[2] = 0; + + // Assign message data + for (i = 0; i < nBytes; i++) { + rxd[i] = ba[i + 8]; + } + } + + // UINC channel + spiTransferError = DRV_CANFDSPI_ReceiveChannelUpdate(index, channel); + if (spiTransferError) { + return -4; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveChannelReset(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel) +{ + uint16_t a = 0; + REG_CiFIFOCON ciFifoCon; + int8_t spiTransferError = 0; + + // Address and data + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET) + 1; // Byte that contains FRESET + ciFifoCon.word = 0; + ciFifoCon.rxBF.FRESET = 1; + + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[1]); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveChannelUpdate(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel) +{ + uint16_t a = 0; + REG_CiFIFOCON ciFifoCon; + int8_t spiTransferError = 0; + ciFifoCon.word = 0; + + // Set UINC + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET) + 1; // Byte that contains FRESET + ciFifoCon.rxBF.UINC = 1; + + // Write byte + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[1]); + + return spiTransferError; +} + +// ***************************************************************************** +// ***************************************************************************** +// Section: Transmit Event FIFO + +int8_t DRV_CANFDSPI_TefStatusGet(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_STATUS* status) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + REG_CiTEFSTA ciTefSta; + ciTefSta.word = 0; + a = cREGADDR_CiTEFSTA; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Update data + *status = (CAN_TEF_FIFO_STATUS) (ciTefSta.byte[0] & CAN_TEF_FIFO_STATUS_MASK); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefMessageGet(CANFDSPI_MODULE_ID index, + CAN_TEF_MSGOBJ* tefObj) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + uint32_t fifoReg[3]; + uint8_t n = 0; + + // Get FIFO registers + a = cREGADDR_CiTEFCON; + + spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 3); + if (spiTransferError) { + return -1; + } + + // Get control + REG_CiTEFCON ciTefCon; + ciTefCon.word = fifoReg[0]; + + // Get status + REG_CiTEFSTA ciTefSta; + ciTefSta.word = fifoReg[1]; + + // Get address + REG_CiFIFOUA ciTefUa; + ciTefUa.word = fifoReg[2]; +#ifdef USERADDRESS_TIMES_FOUR + a = 4 * ciTefUa.bF.UserAddress; +#else + a = ciTefUa.bF.UserAddress; +#endif + a += cRAMADDR_START; + + // Number of bytes to read + n = 8; // 8 header bytes + + if (ciTefCon.bF.TimeStampEnable) { + n += 4; // Add 4 time stamp bytes + } + + // Read rxObj using one access + uint8_t ba[12]; + + spiTransferError = DRV_CANFDSPI_ReadByteArray(index, a, ba, n); + if (spiTransferError) { + return -2; + } + + // Assign message header + REG_t myReg; + + myReg.byte[0] = ba[0]; + myReg.byte[1] = ba[1]; + myReg.byte[2] = ba[2]; + myReg.byte[3] = ba[3]; + tefObj->word[0] = myReg.word; + + myReg.byte[0] = ba[4]; + myReg.byte[1] = ba[5]; + myReg.byte[2] = ba[6]; + myReg.byte[3] = ba[7]; + tefObj->word[1] = myReg.word; + + if (ciTefCon.bF.TimeStampEnable) { + myReg.byte[0] = ba[8]; + myReg.byte[1] = ba[9]; + myReg.byte[2] = ba[10]; + myReg.byte[3] = ba[11]; + tefObj->word[2] = myReg.word; + } else { + tefObj->word[2] = 0; + } + + // Set UINC + spiTransferError = DRV_CANFDSPI_TefUpdate(index); + if (spiTransferError) { + return -3; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefReset(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Set FRESET + a = cREGADDR_CiTEFCON + 1; + REG_CiTEFCON ciTefCon; + ciTefCon.word = 0; + ciTefCon.bF.FRESET = 1; + + // Write byte + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[1]); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefUpdate(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Set UINC + a = cREGADDR_CiTEFCON + 1; + REG_CiTEFCON ciTefCon; + ciTefCon.word = 0; + ciTefCon.bF.UINC = 1; + + // Write byte + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[1]); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefConfigure(CANFDSPI_MODULE_ID index, CAN_TEF_CONFIG* config) +{ + int8_t spiTransferError = 0; + + // Setup FIFO + REG_CiTEFCON ciTefCon; + ciTefCon.word = canControlResetValues[cREGADDR_CiTEFCON / 4]; + + ciTefCon.bF.FifoSize = config->FifoSize; + ciTefCon.bF.TimeStampEnable = config->TimeStampEnable; + + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTEFCON, ciTefCon.word); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefConfigureObjectReset(CAN_TEF_CONFIG* config) +{ + REG_CiTEFCON ciTefCon; + ciTefCon.word = canFifoResetValues[0]; + + config->FifoSize = ciTefCon.bF.FifoSize; + config->TimeStampEnable = ciTefCon.bF.TimeStampEnable; + + return 0; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Module Events + +int8_t DRV_CANFDSPI_ModuleEventGet(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT* flags) +{ + int8_t spiTransferError = 0; + + // Read Interrupt flags + REG_CiINTFLAG intFlags; + intFlags.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, cREGADDR_CiINTFLAG, &intFlags.word); + if (spiTransferError) { + return -1; + } + + // Update data + *flags = (CAN_MODULE_EVENT) (intFlags.word & CAN_ALL_EVENTS); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ModuleEventEnable(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Enables + a = cREGADDR_CiINTENABLE; + REG_CiINTENABLE intEnables; + intEnables.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, a, &intEnables.word); + if (spiTransferError) { + return -1; + } + + // Modify + intEnables.word |= (flags & CAN_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, a, intEnables.word); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ModuleEventDisable(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Enables + a = cREGADDR_CiINTENABLE; + REG_CiINTENABLE intEnables; + intEnables.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, a, &intEnables.word); + if (spiTransferError) { + return -1; + } + + // Modify + intEnables.word &= ~(flags & CAN_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, a, intEnables.word); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ModuleEventClear(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt flags + a = cREGADDR_CiINTFLAG; + REG_CiINTFLAG intFlags; + intFlags.word = 0; + + // Write 1 to all flags except the ones that we want to clear + // Writing a 1 will not set the flag + // Only writing a 0 will clear it + // The flags are HS/C + intFlags.word = CAN_ALL_EVENTS; + intFlags.word &= ~flags; + + // Write + spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, a, intFlags.word); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ModuleEventRxCodeGet(CANFDSPI_MODULE_ID index, + CAN_RXCODE* rxCode) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + uint8_t rxCodeByte = 0; + + // Read + a = cREGADDR_CiVEC + 3; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &rxCodeByte); + if (spiTransferError) { + return -1; + } + + // Decode data + // 0x40 = "no interrupt" (CAN_FIFO_CIVEC_NOINTERRUPT) + if ((rxCodeByte < CAN_RXCODE_TOTAL_CHANNELS) || (rxCodeByte == CAN_RXCODE_NO_INT)) { + *rxCode = (CAN_RXCODE) rxCodeByte; + } else { + *rxCode = CAN_RXCODE_RESERVED; // shouldn't get here + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ModuleEventTxCodeGet(CANFDSPI_MODULE_ID index, + CAN_TXCODE* txCode) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + uint8_t txCodeByte = 0; + + // Read + a = cREGADDR_CiVEC + 2; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &txCodeByte); + if (spiTransferError) { + return -1; + } + + // Decode data + // 0x40 = "no interrupt" (CAN_FIFO_CIVEC_NOINTERRUPT) + if ((txCodeByte < CAN_TXCODE_TOTAL_CHANNELS) || (txCodeByte == CAN_TXCODE_NO_INT)) { + *txCode = (CAN_TXCODE) txCodeByte; + } else { + *txCode = CAN_TXCODE_RESERVED; // shouldn't get here + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ModuleEventFilterHitGet(CANFDSPI_MODULE_ID index, + CAN_FILTER* filterHit) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + uint8_t filterHitByte = 0; + + // Read + a = cREGADDR_CiVEC + 1; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &filterHitByte); + if (spiTransferError) { + return -1; + } + + // Update data + *filterHit = (CAN_FILTER) filterHitByte; + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ModuleEventIcodeGet(CANFDSPI_MODULE_ID index, + CAN_ICODE* icode) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + uint8_t icodeByte = 0; + + // Read + a = cREGADDR_CiVEC; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &icodeByte); + if (spiTransferError) { + return -1; + } + + // Decode + if ((icodeByte < CAN_ICODE_RESERVED) && ((icodeByte < CAN_ICODE_TOTAL_CHANNELS) || (icodeByte >= CAN_ICODE_NO_INT))) { + *icode = (CAN_ICODE) icodeByte; + } else { + *icode = CAN_ICODE_RESERVED; // shouldn't get here + } + + return spiTransferError; +} + +// ***************************************************************************** +// ***************************************************************************** +// Section: Transmit FIFO Events + +int8_t DRV_CANFDSPI_TransmitChannelEventGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT* flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt flags + REG_CiFIFOSTA ciFifoSta; + ciFifoSta.word = 0; + a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Update data + *flags = (CAN_TX_FIFO_EVENT) (ciFifoSta.byte[0] & CAN_TX_FIFO_ALL_EVENTS); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitEventGet(CANFDSPI_MODULE_ID index, uint32_t* txif) +{ + int8_t spiTransferError = 0; + + spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTXIF, txif); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitEventAttemptGet(CANFDSPI_MODULE_ID index, + uint32_t* txatif) +{ + int8_t spiTransferError = 0; + + spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTXATIF, txatif); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelIndexGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, uint8_t* idx) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read index + REG_CiFIFOSTA ciFifoSta; + ciFifoSta.word = 0; + a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadWord(index, a, &ciFifoSta.word); + if (spiTransferError) { + return -1; + } + + // Update data + *idx = ciFifoSta.txBF.FifoIndex; + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelEventEnable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Enables + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciFifoCon.byte[0] |= (flags & CAN_TX_FIFO_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelEventDisable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Enables + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciFifoCon.byte[0] &= ~(flags & CAN_TX_FIFO_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TransmitChannelEventAttemptClear(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Enables + a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); + REG_CiFIFOSTA ciFifoSta; + ciFifoSta.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciFifoSta.byte[0] &= ~CAN_TX_FIFO_ATTEMPTS_EXHAUSTED_EVENT; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoSta.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Receive FIFO Events + +int8_t DRV_CANFDSPI_ReceiveChannelEventGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT* flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + if (channel == CAN_TXQUEUE_CH0) return -100; + + // Read Interrupt flags + REG_CiFIFOSTA ciFifoSta; + ciFifoSta.word = 0; + a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Update data + *flags = (CAN_RX_FIFO_EVENT) (ciFifoSta.byte[0] & CAN_RX_FIFO_ALL_EVENTS); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveEventGet(CANFDSPI_MODULE_ID index, uint32_t* rxif) +{ + int8_t spiTransferError = 0; + + spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiRXIF, rxif); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveEventOverflowGet(CANFDSPI_MODULE_ID index, + uint32_t* rxovif) +{ + int8_t spiTransferError = 0; + + spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiRXOVIF, rxovif); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveChannelIndexGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, uint8_t* idx) +{ + return DRV_CANFDSPI_TransmitChannelIndexGet(index, channel, idx); +} + +int8_t DRV_CANFDSPI_ReceiveChannelEventEnable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + if (channel == CAN_TXQUEUE_CH0) return -100; + + // Read Interrupt Enables + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciFifoCon.byte[0] |= (flags & CAN_RX_FIFO_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveChannelEventDisable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + if (channel == CAN_TXQUEUE_CH0) return -100; + + // Read Interrupt Enables + a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); + REG_CiFIFOCON ciFifoCon; + ciFifoCon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciFifoCon.byte[0] &= ~(flags & CAN_RX_FIFO_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ReceiveChannelEventOverflowClear(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + if (channel == CAN_TXQUEUE_CH0) return -100; + + // Read Interrupt Flags + REG_CiFIFOSTA ciFifoSta; + ciFifoSta.word = 0; + a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciFifoSta.byte[0] &= ~(CAN_RX_FIFO_OVERFLOW_EVENT); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoSta.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Transmit Event FIFO Events + +int8_t DRV_CANFDSPI_TefEventGet(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_EVENT* flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt flags + REG_CiTEFSTA ciTefSta; + ciTefSta.word = 0; + a = cREGADDR_CiTEFSTA; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Update data + *flags = (CAN_TEF_FIFO_EVENT) (ciTefSta.byte[0] & CAN_TEF_FIFO_ALL_EVENTS); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefEventEnable(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Enables + a = cREGADDR_CiTEFCON; + REG_CiTEFCON ciTefCon; + ciTefCon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefCon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciTefCon.byte[0] |= (flags & CAN_TEF_FIFO_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefEventDisable(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Enables + a = cREGADDR_CiTEFCON; + REG_CiTEFCON ciTefCon; + ciTefCon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefCon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciTefCon.byte[0] &= ~(flags & CAN_TEF_FIFO_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TefEventOverflowClear(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt Flags + REG_CiTEFSTA ciTefSta; + ciTefSta.word = 0; + a = cREGADDR_CiTEFSTA; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefSta.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + ciTefSta.byte[0] &= ~(CAN_TEF_FIFO_OVERFLOW_EVENT); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefSta.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Error Handling + +int8_t DRV_CANFDSPI_ErrorCountTransmitGet(CANFDSPI_MODULE_ID index, + uint8_t* tec) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Error count + a = cREGADDR_CiTREC + 1; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, tec); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ErrorCountReceiveGet(CANFDSPI_MODULE_ID index, + uint8_t* rec) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Error count + a = cREGADDR_CiTREC; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, rec); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ErrorStateGet(CANFDSPI_MODULE_ID index, + CAN_ERROR_STATE* flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Error state + a = cREGADDR_CiTREC + 2; + uint8_t f = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &f); + if (spiTransferError) { + return -1; + } + + // Update data + *flags = (CAN_ERROR_STATE) (f & CAN_ERROR_ALL); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_ErrorCountStateGet(CANFDSPI_MODULE_ID index, + uint8_t* tec, uint8_t* rec, CAN_ERROR_STATE* flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Error + a = cREGADDR_CiTREC; + REG_CiTREC ciTrec; + ciTrec.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadWord(index, a, &ciTrec.word); + if (spiTransferError) { + return -1; + } + + // Update data + *tec = ciTrec.byte[1]; + *rec = ciTrec.byte[0]; + *flags = (CAN_ERROR_STATE) (ciTrec.byte[2] & CAN_ERROR_ALL); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BusDiagnosticsGet(CANFDSPI_MODULE_ID index, + CAN_BUS_DIAGNOSTIC* bd) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read diagnostic registers all in one shot + a = cREGADDR_CiBDIAG0; + uint32_t w[2]; + + spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, w, 2); + if (spiTransferError) { + return -1; + } + + // Update data + CAN_BUS_DIAGNOSTIC b; + b.word[0] = w[0]; + b.word[1] = w[1] & 0x0000ffff; + b.word[2] = (w[1] >> 16) & 0x0000ffff; + *bd = b; + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BusDiagnosticsClear(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t a = 0; + + // Clear diagnostic registers all in one shot + a = cREGADDR_CiBDIAG0; + uint32_t w[2]; + w[0] = 0; + w[1] = 0; + + spiTransferError = DRV_CANFDSPI_WriteWordArray(index, a, w, 2); + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: ECC + +int8_t DRV_CANFDSPI_EccEnable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_ECCCON, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d |= 0x01; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_ECCCON, d); + if (spiTransferError) { + return -2; + } + + return 0; +} + +int8_t DRV_CANFDSPI_EccDisable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_ECCCON, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= ~0x01; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_ECCCON, d); + if (spiTransferError) { + return -2; + } + + return 0; +} + +int8_t DRV_CANFDSPI_EccEventGet(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT* flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Interrupt flags + uint8_t eccStatus = 0; + a = cREGADDR_ECCSTA; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccStatus); + if (spiTransferError) { + return -1; + } + + // Update data + *flags = (CAN_ECC_EVENT) (eccStatus & CAN_ECC_ALL_EVENTS); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_EccParitySet(CANFDSPI_MODULE_ID index, + uint8_t parity) +{ + int8_t spiTransferError = 0; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_ECCCON + 1, parity); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_EccParityGet(CANFDSPI_MODULE_ID index, + uint8_t* parity) +{ + int8_t spiTransferError = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_ECCCON + 1, parity); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_EccErrorAddressGet(CANFDSPI_MODULE_ID index, + uint16_t* a) +{ + int8_t spiTransferError = 0; + REG_ECCSTA reg; + + // Read + spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_ECCSTA, ®.word); + if (spiTransferError) { + return -1; + } + + // Update data + *a = reg.bF.ErrorAddress; + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_EccEventEnable(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_ECCCON; + uint8_t eccInterrupts = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccInterrupts); + if (spiTransferError) { + return -1; + } + + // Modify + eccInterrupts |= (flags & CAN_ECC_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, eccInterrupts); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_EccEventDisable(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_ECCCON; + uint8_t eccInterrupts = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccInterrupts); + if (spiTransferError) { + return -1; + } + + // Modify + eccInterrupts &= ~(flags & CAN_ECC_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, eccInterrupts); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_EccEventClear(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_ECCSTA; + uint8_t eccStat = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccStat); + if (spiTransferError) { + return -1; + } + + // Modify + eccStat &= ~(flags & CAN_ECC_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, eccStat); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: CRC + +int8_t DRV_CANFDSPI_CrcEventEnable(CANFDSPI_MODULE_ID index, + CAN_CRC_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read interrupt control bits of CRC Register + a = cREGADDR_CRC + 3; + uint8_t crc; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); + if (spiTransferError) { + return -1; + } + + // Modify + crc |= (flags & CAN_CRC_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, crc); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_CrcEventDisable(CANFDSPI_MODULE_ID index, + CAN_CRC_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read interrupt control bits of CRC Register + a = cREGADDR_CRC + 3; + uint8_t crc; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); + if (spiTransferError) { + return -1; + } + + // Modify + crc &= ~(flags & CAN_CRC_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, crc); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_CrcEventClear(CANFDSPI_MODULE_ID index, + CAN_CRC_EVENT flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read interrupt flags of CRC Register + a = cREGADDR_CRC + 2; + uint8_t crc; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); + if (spiTransferError) { + return -1; + } + + // Modify + crc &= ~(flags & CAN_CRC_ALL_EVENTS); + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, crc); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_CrcEventGet(CANFDSPI_MODULE_ID index, CAN_CRC_EVENT* flags) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read interrupt flags of CRC Register + a = cREGADDR_CRC + 2; + uint8_t crc; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); + if (spiTransferError) { + return -1; + } + + // Update data + *flags = (CAN_CRC_EVENT) (crc & CAN_CRC_ALL_EVENTS); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_CrcValueGet(CANFDSPI_MODULE_ID index, uint16_t* crc) +{ + int8_t spiTransferError = 0; + + // Read CRC value from CRC Register + spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, cREGADDR_CRC, crc); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_RamInit(CANFDSPI_MODULE_ID index, uint8_t d) +{ + uint8_t txd[SPI_DEFAULT_BUFFER_LENGTH]; + uint32_t k; + int8_t spiTransferError = 0; + + // Prepare data + for (k = 0; k < SPI_DEFAULT_BUFFER_LENGTH; k++) { + txd[k] = d; + } + + uint16_t a = cRAMADDR_START; + + for (k = 0; k < (cRAM_SIZE / SPI_DEFAULT_BUFFER_LENGTH); k++) { + spiTransferError = DRV_CANFDSPI_WriteByteArray(index, a, txd, SPI_DEFAULT_BUFFER_LENGTH); + if (spiTransferError) { + return -1; + } + a += SPI_DEFAULT_BUFFER_LENGTH; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Time Stamp + +int8_t DRV_CANFDSPI_TimeStampEnable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiTSCON + 2, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d |= 0x01; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiTSCON + 2, d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TimeStampDisable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiTSCON + 2, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= 0x06; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiTSCON + 2, d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TimeStampGet(CANFDSPI_MODULE_ID index, uint32_t* ts) +{ + int8_t spiTransferError = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTBC, ts); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TimeStampSet(CANFDSPI_MODULE_ID index, uint32_t ts) +{ + int8_t spiTransferError = 0; + + // Write + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTBC, ts); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TimeStampModeConfigure(CANFDSPI_MODULE_ID index, + CAN_TS_MODE mode) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiTSCON + 2, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= 0x01; + d |= mode << 1; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiTSCON + 2, d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_TimeStampPrescalerSet(CANFDSPI_MODULE_ID index, + uint16_t ps) +{ + int8_t spiTransferError = 0; + + // Write + spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, cREGADDR_CiTSCON, ps); + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Oscillator and Bit Time + +int8_t DRV_CANFDSPI_OscillatorEnable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint8_t d = 0; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC, &d); + if (spiTransferError) { + return -1; + } + + // Modify + d &= ~0x4; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, d); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_OscillatorControlSet(CANFDSPI_MODULE_ID index, + CAN_OSC_CTRL ctrl) +{ + int8_t spiTransferError = 0; + + REG_OSC osc; + osc.word = 0; + + osc.bF.PllEnable = ctrl.PllEnable; + osc.bF.OscDisable = ctrl.OscDisable; + osc.bF.SCLKDIV = ctrl.SclkDivide; + osc.bF.CLKODIV = ctrl.ClkOutDivide; +#ifndef MCP2517FD + osc.bF.LowPowerModeEnable = ctrl.LowPowerModeEnable; +#endif + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, osc.byte[0]); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_OscillatorControlObjectReset(CAN_OSC_CTRL* ctrl) +{ + REG_OSC osc; + osc.word = mcp25xxfdControlResetValues[0]; + + ctrl->PllEnable = osc.bF.PllEnable; + ctrl->OscDisable = osc.bF.OscDisable; + ctrl->SclkDivide = osc.bF.SCLKDIV; + ctrl->ClkOutDivide = osc.bF.CLKODIV; + + return 0; +} + +int8_t DRV_CANFDSPI_OscillatorStatusGet(CANFDSPI_MODULE_ID index, + CAN_OSC_STATUS* status) +{ + int8_t spiTransferError = 0; + + REG_OSC osc; + osc.word = 0; + CAN_OSC_STATUS stat; + + // Read + spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC + 1, &osc.byte[1]); + if (spiTransferError) { + return -1; + } + + stat.PllReady = osc.bF.PllReady; + stat.OscReady = osc.bF.OscReady; + stat.SclkReady = osc.bF.SclkReady; + + *status = stat; + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BitTimeConfigure(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode, + CAN_SYSCLK_SPEED clk) +{ + int8_t spiTransferError = 0; + + // Decode clk + switch (clk) { + case CAN_SYSCLK_40M: + spiTransferError = DRV_CANFDSPI_BitTimeConfigureNominal40MHz(index, bitTime); + if (spiTransferError) return spiTransferError; + + spiTransferError = DRV_CANFDSPI_BitTimeConfigureData40MHz(index, bitTime, sspMode); + break; + case CAN_SYSCLK_20M: + spiTransferError = DRV_CANFDSPI_BitTimeConfigureNominal20MHz(index, bitTime); + if (spiTransferError) return spiTransferError; + + spiTransferError = DRV_CANFDSPI_BitTimeConfigureData20MHz(index, bitTime, sspMode); + break; + case CAN_SYSCLK_10M: + spiTransferError = DRV_CANFDSPI_BitTimeConfigureNominal10MHz(index, bitTime); + if (spiTransferError) return spiTransferError; + + spiTransferError = DRV_CANFDSPI_BitTimeConfigureData10MHz(index, bitTime, sspMode); + break; + default: + spiTransferError = -1; + break; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BitTimeConfigureNominal40MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime) +{ + int8_t spiTransferError = 0; + REG_CiNBTCFG ciNbtcfg; + + ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4]; + + // Arbitration Bit rate + switch (bitTime) { + // All 500K + case CAN_500K_1M: + case CAN_500K_2M: + case CAN_500K_3M: + case CAN_500K_4M: + case CAN_500K_5M: + case CAN_500K_6M7: + case CAN_500K_8M: + case CAN_500K_10M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 62; + ciNbtcfg.bF.TSEG2 = 15; + ciNbtcfg.bF.SJW = 15; + break; + + // All 250K + case CAN_250K_500K: + case CAN_250K_833K: + case CAN_250K_1M: + case CAN_250K_1M5: + case CAN_250K_2M: + case CAN_250K_3M: + case CAN_250K_4M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 126; + ciNbtcfg.bF.TSEG2 = 31; + ciNbtcfg.bF.SJW = 31; + break; + + case CAN_1000K_4M: + case CAN_1000K_8M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 30; + ciNbtcfg.bF.TSEG2 = 7; + ciNbtcfg.bF.SJW = 7; + break; + + case CAN_125K_500K: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 254; + ciNbtcfg.bF.TSEG2 = 63; + ciNbtcfg.bF.SJW = 63; + break; + + default: + return -1; + break; + } + + // Write Bit time registers + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiNBTCFG, ciNbtcfg.word); + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BitTimeConfigureData40MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode) +{ + int8_t spiTransferError = 0; + REG_CiDBTCFG ciDbtcfg; + REG_CiTDC ciTdc; + // sspMode; + + ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4]; + ciTdc.word = 0; + + // Configure Bit time and sample point + ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO; + uint32_t tdcValue = 0; + + // Data Bit rate and SSP + switch (bitTime) { + case CAN_500K_1M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 30; + ciDbtcfg.bF.TSEG2 = 7; + ciDbtcfg.bF.SJW = 7; + // SSP + ciTdc.bF.TDCOffset = 31; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_2M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 14; + ciDbtcfg.bF.TSEG2 = 3; + ciDbtcfg.bF.SJW = 3; + // SSP + ciTdc.bF.TDCOffset = 15; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_3M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 8; + ciDbtcfg.bF.TSEG2 = 2; + ciDbtcfg.bF.SJW = 2; + // SSP + ciTdc.bF.TDCOffset = 9; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_4M: + case CAN_1000K_4M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 6; + ciDbtcfg.bF.TSEG2 = 1; + ciDbtcfg.bF.SJW = 1; + // SSP + ciTdc.bF.TDCOffset = 7; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_5M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 4; + ciDbtcfg.bF.TSEG2 = 1; + ciDbtcfg.bF.SJW = 1; + // SSP + ciTdc.bF.TDCOffset = 5; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_6M7: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 3; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 4; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_8M: + case CAN_1000K_8M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 2; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 3; + ciTdc.bF.TDCValue = 1; + break; + case CAN_500K_10M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 1; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 2; + ciTdc.bF.TDCValue = 0; + break; + + case CAN_250K_500K: + case CAN_125K_500K: + ciDbtcfg.bF.BRP = 1; + ciDbtcfg.bF.TSEG1 = 30; + ciDbtcfg.bF.TSEG2 = 7; + ciDbtcfg.bF.SJW = 7; + // SSP + ciTdc.bF.TDCOffset = 31; + ciTdc.bF.TDCValue = tdcValue; + ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; + break; + case CAN_250K_833K: + ciDbtcfg.bF.BRP = 1; + ciDbtcfg.bF.TSEG1 = 17; + ciDbtcfg.bF.TSEG2 = 4; + ciDbtcfg.bF.SJW = 4; + // SSP + ciTdc.bF.TDCOffset = 18; + ciTdc.bF.TDCValue = tdcValue; + ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; + break; + case CAN_250K_1M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 30; + ciDbtcfg.bF.TSEG2 = 7; + ciDbtcfg.bF.SJW = 7; + // SSP + ciTdc.bF.TDCOffset = 31; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_1M5: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 18; + ciDbtcfg.bF.TSEG2 = 5; + ciDbtcfg.bF.SJW = 5; + // SSP + ciTdc.bF.TDCOffset = 19; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_2M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 14; + ciDbtcfg.bF.TSEG2 = 3; + ciDbtcfg.bF.SJW = 3; + // SSP + ciTdc.bF.TDCOffset = 15; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_3M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 8; + ciDbtcfg.bF.TSEG2 = 2; + ciDbtcfg.bF.SJW = 2; + // SSP + ciTdc.bF.TDCOffset = 9; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_4M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 6; + ciDbtcfg.bF.TSEG2 = 1; + ciDbtcfg.bF.SJW = 1; + // SSP + ciTdc.bF.TDCOffset = 7; + ciTdc.bF.TDCValue = tdcValue; + break; + + default: + return -1; + break; + } + + // Write Bit time registers + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiDBTCFG, ciDbtcfg.word); + if (spiTransferError) { + return -2; + } + + // Write Transmitter Delay Compensation +#ifdef REV_A + ciTdc.bF.TDCOffset = 0; + ciTdc.bF.TDCValue = 0; +#endif + + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTDC, ciTdc.word); + if (spiTransferError) { + return -3; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BitTimeConfigureNominal20MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime) +{ + int8_t spiTransferError = 0; + REG_CiNBTCFG ciNbtcfg; + + ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4]; + + // Arbitration Bit rate + switch (bitTime) { + // All 500K + case CAN_500K_1M: + case CAN_500K_2M: + case CAN_500K_4M: + case CAN_500K_5M: + case CAN_500K_6M7: + case CAN_500K_8M: + case CAN_500K_10M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 30; + ciNbtcfg.bF.TSEG2 = 7; + ciNbtcfg.bF.SJW = 7; + break; + + // All 250K + case CAN_250K_500K: + case CAN_250K_833K: + case CAN_250K_1M: + case CAN_250K_1M5: + case CAN_250K_2M: + case CAN_250K_3M: + case CAN_250K_4M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 62; + ciNbtcfg.bF.TSEG2 = 15; + ciNbtcfg.bF.SJW = 15; + break; + + case CAN_1000K_4M: + case CAN_1000K_8M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 14; + ciNbtcfg.bF.TSEG2 = 3; + ciNbtcfg.bF.SJW = 3; + break; + + case CAN_125K_500K: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 126; + ciNbtcfg.bF.TSEG2 = 31; + ciNbtcfg.bF.SJW = 31; + break; + + default: + return -1; + break; + } + + // Write Bit time registers + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiNBTCFG, ciNbtcfg.word); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BitTimeConfigureData20MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode) +{ + int8_t spiTransferError = 0; + REG_CiDBTCFG ciDbtcfg; + REG_CiTDC ciTdc; + // sspMode; + + ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4]; + ciTdc.word = 0; + + // Configure Bit time and sample point + ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO; + uint32_t tdcValue = 0; + + // Data Bit rate and SSP + switch (bitTime) { + case CAN_500K_1M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 14; + ciDbtcfg.bF.TSEG2 = 3; + ciDbtcfg.bF.SJW = 3; + // SSP + ciTdc.bF.TDCOffset = 15; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_2M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 6; + ciDbtcfg.bF.TSEG2 = 1; + ciDbtcfg.bF.SJW = 1; + // SSP + ciTdc.bF.TDCOffset = 7; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_4M: + case CAN_1000K_4M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 2; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 3; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_5M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 1; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 2; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_6M7: + case CAN_500K_8M: + case CAN_500K_10M: + case CAN_1000K_8M: + //qDebug("Data Bitrate not feasible with this clock!"); + return -1; + break; + + case CAN_250K_500K: + case CAN_125K_500K: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 30; + ciDbtcfg.bF.TSEG2 = 7; + ciDbtcfg.bF.SJW = 7; + // SSP + ciTdc.bF.TDCOffset = 31; + ciTdc.bF.TDCValue = tdcValue; + ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; + break; + case CAN_250K_833K: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 17; + ciDbtcfg.bF.TSEG2 = 4; + ciDbtcfg.bF.SJW = 4; + // SSP + ciTdc.bF.TDCOffset = 18; + ciTdc.bF.TDCValue = tdcValue; + ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; + break; + case CAN_250K_1M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 14; + ciDbtcfg.bF.TSEG2 = 3; + ciDbtcfg.bF.SJW = 3; + // SSP + ciTdc.bF.TDCOffset = 15; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_1M5: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 8; + ciDbtcfg.bF.TSEG2 = 2; + ciDbtcfg.bF.SJW = 2; + // SSP + ciTdc.bF.TDCOffset = 9; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_2M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 6; + ciDbtcfg.bF.TSEG2 = 1; + ciDbtcfg.bF.SJW = 1; + // SSP + ciTdc.bF.TDCOffset = 7; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_3M: + //qDebug("Data Bitrate not feasible with this clock!"); + return -1; + break; + case CAN_250K_4M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 2; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 3; + ciTdc.bF.TDCValue = tdcValue; + break; + + default: + return -1; + break; + } + + // Write Bit time registers + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiDBTCFG, ciDbtcfg.word); + if (spiTransferError) { + return -2; + } + + // Write Transmitter Delay Compensation +#ifdef REV_A + ciTdc.bF.TDCOffset = 0; + ciTdc.bF.TDCValue = 0; +#endif + + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTDC, ciTdc.word); + if (spiTransferError) { + return -3; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BitTimeConfigureNominal10MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime) +{ + int8_t spiTransferError = 0; + REG_CiNBTCFG ciNbtcfg; + + ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4]; + + // Arbitration Bit rate + switch (bitTime) { + // All 500K + case CAN_500K_1M: + case CAN_500K_2M: + case CAN_500K_4M: + case CAN_500K_5M: + case CAN_500K_6M7: + case CAN_500K_8M: + case CAN_500K_10M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 14; + ciNbtcfg.bF.TSEG2 = 3; + ciNbtcfg.bF.SJW = 3; + break; + + // All 250K + case CAN_250K_500K: + case CAN_250K_833K: + case CAN_250K_1M: + case CAN_250K_1M5: + case CAN_250K_2M: + case CAN_250K_3M: + case CAN_250K_4M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 30; + ciNbtcfg.bF.TSEG2 = 7; + ciNbtcfg.bF.SJW = 7; + break; + + case CAN_1000K_4M: + case CAN_1000K_8M: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 7; + ciNbtcfg.bF.TSEG2 = 2; + ciNbtcfg.bF.SJW = 2; + break; + + case CAN_125K_500K: + ciNbtcfg.bF.BRP = 0; + ciNbtcfg.bF.TSEG1 = 62; + ciNbtcfg.bF.TSEG2 = 15; + ciNbtcfg.bF.SJW = 15; + break; + + default: + return -1; + break; + } + + // Write Bit time registers + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiNBTCFG, ciNbtcfg.word); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_BitTimeConfigureData10MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode) +{ + int8_t spiTransferError = 0; + REG_CiDBTCFG ciDbtcfg; + REG_CiTDC ciTdc; + // sspMode; + + ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4]; + ciTdc.word = 0; + + // Configure Bit time and sample point + ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO; + uint32_t tdcValue = 0; + + // Data Bit rate and SSP + switch (bitTime) { + case CAN_500K_1M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 6; + ciDbtcfg.bF.TSEG2 = 1; + ciDbtcfg.bF.SJW = 1; + // SSP + ciTdc.bF.TDCOffset = 7; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_2M: + // Data BR + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 2; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 3; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_500K_4M: + case CAN_500K_5M: + case CAN_500K_6M7: + case CAN_500K_8M: + case CAN_500K_10M: + case CAN_1000K_4M: + case CAN_1000K_8M: + //qDebug("Data Bitrate not feasible with this clock!"); + return -1; + break; + + case CAN_250K_500K: + case CAN_125K_500K: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 14; + ciDbtcfg.bF.TSEG2 = 3; + ciDbtcfg.bF.SJW = 3; + // SSP + ciTdc.bF.TDCOffset = 15; + ciTdc.bF.TDCValue = tdcValue; + ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; + break; + case CAN_250K_833K: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 7; + ciDbtcfg.bF.TSEG2 = 2; + ciDbtcfg.bF.SJW = 2; + // SSP + ciTdc.bF.TDCOffset = 8; + ciTdc.bF.TDCValue = tdcValue; + ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; + break; + case CAN_250K_1M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 6; + ciDbtcfg.bF.TSEG2 = 1; + ciDbtcfg.bF.SJW = 1; + // SSP + ciTdc.bF.TDCOffset = 7; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_1M5: + //qDebug("Data Bitrate not feasible with this clock!"); + return -1; + break; + case CAN_250K_2M: + ciDbtcfg.bF.BRP = 0; + ciDbtcfg.bF.TSEG1 = 2; + ciDbtcfg.bF.TSEG2 = 0; + ciDbtcfg.bF.SJW = 0; + // SSP + ciTdc.bF.TDCOffset = 3; + ciTdc.bF.TDCValue = tdcValue; + break; + case CAN_250K_3M: + case CAN_250K_4M: + //qDebug("Data Bitrate not feasible with this clock!"); + return -1; + break; + + default: + return -1; + break; + } + + // Write Bit time registers + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiDBTCFG, ciDbtcfg.word); + if (spiTransferError) { + return -2; + } + + // Write Transmitter Delay Compensation +#ifdef REV_A + ciTdc.bF.TDCOffset = 0; + ciTdc.bF.TDCValue = 0; +#endif + + spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTDC, ciTdc.word); + if (spiTransferError) { + return -3; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: GPIO + +int8_t DRV_CANFDSPI_GpioModeConfigure(CANFDSPI_MODULE_ID index, + GPIO_PIN_MODE gpio0, GPIO_PIN_MODE gpio1) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON + 3; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); + if (spiTransferError) { + return -1; + } + + // Modify + iocon.bF.PinMode0 = gpio0; + iocon.bF.PinMode1 = gpio1; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioDirectionConfigure(CANFDSPI_MODULE_ID index, + GPIO_PIN_DIRECTION gpio0, GPIO_PIN_DIRECTION gpio1) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + iocon.bF.TRIS0 = gpio0; + iocon.bF.TRIS1 = gpio1; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioStandbyControlEnable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + iocon.bF.XcrSTBYEnable = 1; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioStandbyControlDisable(CANFDSPI_MODULE_ID index) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[0]); + if (spiTransferError) { + return -1; + } + + // Modify + iocon.bF.XcrSTBYEnable = 0; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[0]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioInterruptPinsOpenDrainConfigure(CANFDSPI_MODULE_ID index, + GPIO_OPEN_DRAIN_MODE mode) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON + 3; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); + if (spiTransferError) { + return -1; + } + + // Modify + iocon.bF.INTPinOpenDrain = mode; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioTransmitPinOpenDrainConfigure(CANFDSPI_MODULE_ID index, + GPIO_OPEN_DRAIN_MODE mode) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON + 3; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); + if (spiTransferError) { + return -1; + } + + // Modify + iocon.bF.TXCANOpenDrain = mode; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioPinSet(CANFDSPI_MODULE_ID index, + GPIO_PIN_POS pos, GPIO_PIN_STATE latch) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON + 1; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[1]); + if (spiTransferError) { + return -1; + } + + // Modify + switch (pos) { + case GPIO_PIN_0: + iocon.bF.LAT0 = latch; + break; + case GPIO_PIN_1: + iocon.bF.LAT1 = latch; + break; + default: + return -1; + break; + } + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[1]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioPinRead(CANFDSPI_MODULE_ID index, + GPIO_PIN_POS pos, GPIO_PIN_STATE* state) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON + 2; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[2]); + if (spiTransferError) { + return -1; + } + + // Update data + switch (pos) { + case GPIO_PIN_0: + *state = (GPIO_PIN_STATE) iocon.bF.GPIO0; + break; + case GPIO_PIN_1: + *state = (GPIO_PIN_STATE) iocon.bF.GPIO1; + break; + default: + return -1; + break; + } + + return spiTransferError; +} + +int8_t DRV_CANFDSPI_GpioClockOutputConfigure(CANFDSPI_MODULE_ID index, + GPIO_CLKO_MODE mode) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read + a = cREGADDR_IOCON + 3; + REG_IOCON iocon; + iocon.word = 0; + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); + if (spiTransferError) { + return -1; + } + + // Modify + iocon.bF.SOFOutputEnable = mode; + + // Write + spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); + if (spiTransferError) { + return -2; + } + + return spiTransferError; +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Miscellaneous + +uint32_t DRV_CANFDSPI_DlcToDataBytes(CAN_DLC dlc) +{ + uint32_t dataBytesInObject = 0; + + Nop(); + Nop(); + + if (dlc < CAN_DLC_12) { + dataBytesInObject = dlc; + } else { + switch (dlc) { + case CAN_DLC_12: + dataBytesInObject = 12; + break; + case CAN_DLC_16: + dataBytesInObject = 16; + break; + case CAN_DLC_20: + dataBytesInObject = 20; + break; + case CAN_DLC_24: + dataBytesInObject = 24; + break; + case CAN_DLC_32: + dataBytesInObject = 32; + break; + case CAN_DLC_48: + dataBytesInObject = 48; + break; + case CAN_DLC_64: + dataBytesInObject = 64; + break; + default: + break; + } + } + + return dataBytesInObject; +} + +int8_t DRV_CANFDSPI_FifoIndexGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, uint8_t* mi) +{ + int8_t spiTransferError = 0; + uint16_t a = 0; + + // Read Status register + uint8_t b = 0; + a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); + a += 1; // byte[1] + + spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &b); + if (spiTransferError) { + return -1; + } + + // Update data + *mi = b & 0x1f; + + return spiTransferError; +} + +uint16_t DRV_CANFDSPI_CalculateCRC16(uint8_t* data, uint16_t size) +{ + uint16_t init = CRCBASE; + uint8_t index; + + while (size-- != 0) { + index = ((uint8_t*) & init)[CRCUPPER] ^ *data++; + init = (init << 8) ^ crc16_table[index]; + } + + return init; +} + +CAN_DLC DRV_CANFDSPI_DataBytesToDlc(uint8_t n) +{ + CAN_DLC dlc = CAN_DLC_0; + + if (n <= 4) { + dlc = CAN_DLC_4; + } else if (n <= 8) { + dlc = CAN_DLC_8; + } else if (n <= 12) { + dlc = CAN_DLC_12; + } else if (n <= 16) { + dlc = CAN_DLC_16; + } else if (n <= 20) { + dlc = CAN_DLC_20; + } else if (n <= 24) { + dlc = CAN_DLC_24; + } else if (n <= 32) { + dlc = CAN_DLC_32; + } else if (n <= 48) { + dlc = CAN_DLC_48; + } else if (n <= 64) { + dlc = CAN_DLC_64; + } + + return dlc; +} diff --git a/mcp2518fd_canfdspi_api.h b/mcp2518fd_canfdspi_api.h new file mode 100644 index 0000000..b850f3b --- /dev/null +++ b/mcp2518fd_canfdspi_api.h @@ -0,0 +1,1120 @@ +/******************************************************************************* + CAN FD SPI Driver: API Functions Header File + + Company: + Microchip Technology Inc. + + File Name: + drv_canfdspi_api.h + + Summary: + This header file provides the API function prototypes for the CAN FD SPI + controller. + + Description: + API function prototypes for the CAN FD SPI controller family: + MCP2517FD, and MCP2518FD. + *******************************************************************************/ + +//DOM-IGNORE-BEGIN +/******************************************************************************* +Copyright (c) 2018 Microchip Technology Inc. and its subsidiaries. + +Subject to your compliance with these terms, you may use Microchip software and +any derivatives exclusively with Microchip products. It is your responsibility +to comply with third party license terms applicable to your use of third party +software (including open source software) that may accompany Microchip software. + +THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, +IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES +OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. + +IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, +INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER +RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF +THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED +BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO +THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID +DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + *******************************************************************************/ +//DOM-IGNORE-END + +#ifndef _DRV_CANFDSPI_API_H +#define _DRV_CANFDSPI_API_H + +// ***************************************************************************** +// ***************************************************************************** +// Section: Included Files + +#include +#include +#include +#include +#include "drv_canfdspi_defines.h" +#include "drv_canfdspi_register.h" + +// DOM-IGNORE-BEGIN +#ifdef __cplusplus // Provide C++ Compatibility +extern "C" { +#endif +// DOM-IGNORE-END + +typedef uint8_t CANFDSPI_MODULE_ID; + +// ***************************************************************************** +// ***************************************************************************** +//! Reset DUT + +int8_t DRV_CANFDSPI_Reset(CANFDSPI_MODULE_ID index); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: SPI Access Functions + +// ***************************************************************************** +//! SPI Read Byte + +int8_t DRV_CANFDSPI_ReadByte(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *rxd); + +// ***************************************************************************** +//! SPI Write Byte + +int8_t DRV_CANFDSPI_WriteByte(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t txd); + +// ***************************************************************************** +//! SPI Read Word + +int8_t DRV_CANFDSPI_ReadWord(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t *rxd); + +// ***************************************************************************** +//! SPI Write Word + +int8_t DRV_CANFDSPI_WriteWord(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t txd); + +/// ***************************************************************************** +//! SPI Read Word + +int8_t DRV_CANFDSPI_ReadHalfWord(CANFDSPI_MODULE_ID index, uint16_t address, + uint16_t *rxd); + +// ***************************************************************************** +//! SPI Write Word + +int8_t DRV_CANFDSPI_WriteHalfWord(CANFDSPI_MODULE_ID index, uint16_t address, + uint16_t txd); + +// ***************************************************************************** +//! SPI Read Byte Array + +int8_t DRV_CANFDSPI_ReadByteArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *rxd, uint16_t nBytes); + +// ***************************************************************************** +//! SPI Write Byte Array + +int8_t DRV_CANFDSPI_WriteByteArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *txd, uint16_t nBytes); + +// ***************************************************************************** +//! SPI SFR Write Byte Safe +/*! + * Writes Byte to SFR at address using SPI CRC. Byte gets only written if CRC matches. + * + * Remark: The function doesn't check if the address is an SFR address. + */ + +int8_t DRV_CANFDSPI_WriteByteSafe(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t txd); + +// ***************************************************************************** +//! SPI RAM Write Word Safe +/*! + * Writes Word to RAM at address using SPI CRC. Word gets only written if CRC matches. + * + * Remark: The function doesn't check if the address is a RAM address. + */ + +int8_t DRV_CANFDSPI_WriteWordSafe(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t txd); + +// ***************************************************************************** +//! SPI Read Byte Array with CRC + +int8_t DRV_CANFDSPI_ReadByteArrayWithCRC(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *rxd, uint16_t nBytes, bool fromRam, bool* crcIsCorrect); + +// ***************************************************************************** +//! SPI Write Byte Array with CRC + +int8_t DRV_CANFDSPI_WriteByteArrayWithCRC(CANFDSPI_MODULE_ID index, uint16_t address, + uint8_t *txd, uint16_t nBytes, bool fromRam); + +// ***************************************************************************** +//! SPI Read Word Array + +int8_t DRV_CANFDSPI_ReadWordArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t *rxd, uint16_t nWords); + +// ***************************************************************************** +//! SPI Write Word Array + +int8_t DRV_CANFDSPI_WriteWordArray(CANFDSPI_MODULE_ID index, uint16_t address, + uint32_t *txd, uint16_t nWords); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Configuration + +// ***************************************************************************** +//! CAN Control register configuration + +int8_t DRV_CANFDSPI_Configure(CANFDSPI_MODULE_ID index, CAN_CONFIG* config); + +// ***************************************************************************** +//! Reset Configure object to reset values +int8_t DRV_CANFDSPI_ConfigureObjectReset(CAN_CONFIG* config); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Operating mode + +// ***************************************************************************** +//! Select Operation Mode + +int8_t DRV_CANFDSPI_OperationModeSelect(CANFDSPI_MODULE_ID index, + CAN_OPERATION_MODE opMode); + +// ***************************************************************************** +//! Get Operation Mode + +CAN_OPERATION_MODE DRV_CANFDSPI_OperationModeGet(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Enable Low Power Mode + +int8_t DRV_CANFDSPI_LowPowerModeEnable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Disable Low Power Mode + +int8_t DRV_CANFDSPI_LowPowerModeDisable(CANFDSPI_MODULE_ID index); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: CAN Transmit + +// ***************************************************************************** +//! Configure Transmit FIFO + +int8_t DRV_CANFDSPI_TransmitChannelConfigure(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_CONFIG* config); + +// ***************************************************************************** +//! Reset TransmitChannelConfigure object to reset values + +int8_t DRV_CANFDSPI_TransmitChannelConfigureObjectReset(CAN_TX_FIFO_CONFIG* config); + +// ***************************************************************************** +//! Configure Transmit Queue + +int8_t DRV_CANFDSPI_TransmitQueueConfigure(CANFDSPI_MODULE_ID index, + CAN_TX_QUEUE_CONFIG* config); + +// ***************************************************************************** +//! Reset TransmitQueueConfigure object to reset values + +int8_t DRV_CANFDSPI_TransmitQueueConfigureObjectReset(CAN_TX_QUEUE_CONFIG* config); + +// ***************************************************************************** +//! TX Channel Load +/*! + * Loads data into Transmit channel + * Requests transmission, if flush==true + */ + +int8_t DRV_CANFDSPI_TransmitChannelLoad(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_MSGOBJ* txObj, + uint8_t *txd, uint32_t txdNumBytes, bool flush); + +// ***************************************************************************** +//! TX Queue Load + +/*! + * Loads data into Transmit Queue + * Requests transmission, if flush==true + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueLoad(CANFDSPI_MODULE_ID index, + CAN_TX_MSGOBJ* txObj, + uint8_t *txd, uint32_t txdNumBytes, bool flush) +{ + return DRV_CANFDSPI_TransmitChannelLoad(index, CAN_TXQUEUE_CH0, txObj, txd, txdNumBytes, flush); +} + +// ***************************************************************************** +//! TX Channel Flush +/*! + * Set TXREG of one channel + */ + +int8_t DRV_CANFDSPI_TransmitChannelFlush(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel); + +// ***************************************************************************** +//! Transmit Channel Status Get + +int8_t DRV_CANFDSPI_TransmitChannelStatusGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_STATUS* status); + +// ***************************************************************************** +//! Transmit FIFO Reset + +int8_t DRV_CANFDSPI_TransmitChannelReset(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel); + +// ***************************************************************************** +//! Transmit FIFO Update +/*! + * Sets UINC of the transmit channel. + * Requests transmission, if flush==true + */ + +int8_t DRV_CANFDSPI_TransmitChannelUpdate(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, bool flush); + +// ***************************************************************************** +//! TX Queue Flush + +/*! + * Set TXREG of one channel + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueFlush(CANFDSPI_MODULE_ID index) +{ + return DRV_CANFDSPI_TransmitChannelFlush(index, CAN_TXQUEUE_CH0); +} + +// ***************************************************************************** +//! Transmit Queue Status Get + +inline int8_t DRV_CANFDSPI_TransmitQueueStatusGet(CANFDSPI_MODULE_ID index, + CAN_TX_FIFO_STATUS* status) +{ + return DRV_CANFDSPI_TransmitChannelStatusGet(index, CAN_TXQUEUE_CH0, status); +} + +// ***************************************************************************** +//! Transmit Queue Reset + +inline int8_t DRV_CANFDSPI_TransmitQueueReset(CANFDSPI_MODULE_ID index) +{ + return DRV_CANFDSPI_TransmitChannelReset(index, CAN_TXQUEUE_CH0); +} + +// ***************************************************************************** +//! Transmit Queue Update + +/*! + * Sets UINC of the transmit channel. + * Requests transmission, if flush==true + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueUpdate(CANFDSPI_MODULE_ID index, bool flush) +{ + return DRV_CANFDSPI_TransmitChannelUpdate(index, CAN_TXQUEUE_CH0, flush); +} + +// ***************************************************************************** +//! Request transmissions using TXREQ register + +int8_t DRV_CANFDSPI_TransmitRequestSet(CANFDSPI_MODULE_ID index, + CAN_TXREQ_CHANNEL txreq); + +// ***************************************************************************** +//! Get TXREQ register + +int8_t DRV_CANFDSPI_TransmitRequestGet(CANFDSPI_MODULE_ID index, + uint32_t* txreq); + +// ***************************************************************************** +//! Abort transmission of single FIFO + +int8_t DRV_CANFDSPI_TransmitChannelAbort(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel); + +// ***************************************************************************** +//! Abort transmission of TXQ + +inline int8_t DRV_CANFDSPI_TransmitQueueAbort(CANFDSPI_MODULE_ID index) +{ + return DRV_CANFDSPI_TransmitChannelAbort(index, CAN_TXQUEUE_CH0); +} + +// ***************************************************************************** +//! Abort All transmissions + +int8_t DRV_CANFDSPI_TransmitAbortAll(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Set Transmit Bandwidth Sharing Delay +int8_t DRV_CANFDSPI_TransmitBandWidthSharingSet(CANFDSPI_MODULE_ID index, + CAN_TX_BANDWITH_SHARING txbws); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: CAN Receive + +// ***************************************************************************** +//! Filter Object Configuration +/*! + * Configures ID of filter object + */ + +int8_t DRV_CANFDSPI_FilterObjectConfigure(CANFDSPI_MODULE_ID index, + CAN_FILTER filter, CAN_FILTEROBJ_ID* id); + +// ***************************************************************************** +//! Filter Mask Configuration +/*! + * Configures Mask of filter object + */ + +int8_t DRV_CANFDSPI_FilterMaskConfigure(CANFDSPI_MODULE_ID index, + CAN_FILTER filter, CAN_MASKOBJ_ID* mask); + +// ***************************************************************************** +//! Link Filter to FIFO +/*! + * Initializes the Pointer from Filter to FIFO + * Enables or disables the Filter + */ + +int8_t DRV_CANFDSPI_FilterToFifoLink(CANFDSPI_MODULE_ID index, + CAN_FILTER filter, CAN_FIFO_CHANNEL channel, bool enable); + +// ***************************************************************************** +//! Filter Enable + +int8_t DRV_CANFDSPI_FilterEnable(CANFDSPI_MODULE_ID index, CAN_FILTER filter); + +// ***************************************************************************** +//! Filter Disable + +int8_t DRV_CANFDSPI_FilterDisable(CANFDSPI_MODULE_ID index, CAN_FILTER filter); + +// ***************************************************************************** +//! Set Device Net Filter Count +int8_t DRV_CANFDSPI_DeviceNetFilterCountSet(CANFDSPI_MODULE_ID index, + CAN_DNET_FILTER_SIZE dnfc); + +// ***************************************************************************** +//! Configure Receive FIFO + +int8_t DRV_CANFDSPI_ReceiveChannelConfigure(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_CONFIG* config); + +// ***************************************************************************** +//! Reset ReceiveChannelConfigure object to reset value + +int8_t DRV_CANFDSPI_ReceiveChannelConfigureObjectReset(CAN_RX_FIFO_CONFIG* config); + +// ***************************************************************************** +//! Receive Channel Status Get + +int8_t DRV_CANFDSPI_ReceiveChannelStatusGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_STATUS* status); + +// ***************************************************************************** +//! Get Received Message +/*! + * Reads Received message from channel + */ + +int8_t DRV_CANFDSPI_ReceiveMessageGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_MSGOBJ* rxObj, + uint8_t *rxd, uint8_t nBytes); + +// ***************************************************************************** +//! Receive FIFO Reset + +int8_t DRV_CANFDSPI_ReceiveChannelReset(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel); + +// ***************************************************************************** +//! Receive FIFO Update +/*! + * Sets UINC of the receive channel. + */ + +int8_t DRV_CANFDSPI_ReceiveChannelUpdate(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Transmit Event FIFO + +// ***************************************************************************** +//! Transmit Event FIFO Status Get + +int8_t DRV_CANFDSPI_TefStatusGet(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_STATUS* status); + +// ***************************************************************************** +//! Get Transmit Event FIFO Message +/*! + * Reads Transmit Event FIFO message + */ + +int8_t DRV_CANFDSPI_TefMessageGet(CANFDSPI_MODULE_ID index, + CAN_TEF_MSGOBJ* tefObj); + +// ***************************************************************************** +//! Transmit Event FIFO Reset + +int8_t DRV_CANFDSPI_TefReset(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Transmit Event FIFO Update +/*! + * Sets UINC of the TEF. + */ + +int8_t DRV_CANFDSPI_TefUpdate(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Configure Transmit Event FIFO + +int8_t DRV_CANFDSPI_TefConfigure(CANFDSPI_MODULE_ID index, CAN_TEF_CONFIG* config); + +// ***************************************************************************** +//! Reset TefConfigure object to reset value + +int8_t DRV_CANFDSPI_TefConfigureObjectReset(CAN_TEF_CONFIG* config); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Module Events + +// ***************************************************************************** +//! Module Event Get +/*! + * Reads interrupt Flags + */ + +int8_t DRV_CANFDSPI_ModuleEventGet(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT* flags); + +// ***************************************************************************** +//! Module Event Enable +/*! + * Enables interrupts + */ + +int8_t DRV_CANFDSPI_ModuleEventEnable(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT flags); + +// ***************************************************************************** +//! Module Event Disable +/*! + * Disables interrupts + */ + +int8_t DRV_CANFDSPI_ModuleEventDisable(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT flags); + +// ***************************************************************************** +//! Module Event Clear +/*! + * Clears interrupt Flags + */ + +int8_t DRV_CANFDSPI_ModuleEventClear(CANFDSPI_MODULE_ID index, + CAN_MODULE_EVENT flags); + +// ***************************************************************************** +//! Get RX Code + +int8_t DRV_CANFDSPI_ModuleEventRxCodeGet(CANFDSPI_MODULE_ID index, + CAN_RXCODE* rxCode); + +// ***************************************************************************** +//! Get TX Code + +int8_t DRV_CANFDSPI_ModuleEventTxCodeGet(CANFDSPI_MODULE_ID index, + CAN_TXCODE* txCode); + +// ***************************************************************************** +//! Get Filter Hit + +int8_t DRV_CANFDSPI_ModuleEventFilterHitGet(CANFDSPI_MODULE_ID index, + CAN_FILTER* filterHit); + +// ***************************************************************************** +//! Get ICODE + +int8_t DRV_CANFDSPI_ModuleEventIcodeGet(CANFDSPI_MODULE_ID index, + CAN_ICODE* icode); + +// ***************************************************************************** +// ***************************************************************************** +// Section: Transmit FIFO Events + +// ***************************************************************************** +//! Transmit FIFO Event Get +/*! + * Reads Transmit FIFO interrupt Flags + */ + +int8_t DRV_CANFDSPI_TransmitChannelEventGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT* flags); + +// ***************************************************************************** +//! Transmit Queue Event Get + +/*! + * Reads Transmit Queue interrupt Flags + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueEventGet(CANFDSPI_MODULE_ID index, + CAN_TX_FIFO_EVENT* flags) +{ + return DRV_CANFDSPI_TransmitChannelEventGet(index, CAN_TXQUEUE_CH0, flags); +} + +// ***************************************************************************** +//! Get pending interrupts of all transmit FIFOs + +int8_t DRV_CANFDSPI_TransmitEventGet(CANFDSPI_MODULE_ID index, uint32_t* txif); + +// ***************************************************************************** +//! Get pending TXATIF of all transmit FIFOs + +int8_t DRV_CANFDSPI_TransmitEventAttemptGet(CANFDSPI_MODULE_ID index, + uint32_t* txatif); + +// ***************************************************************************** +//! Transmit FIFO Index Get +/*! + * Reads Transmit FIFO Index + */ + +int8_t DRV_CANFDSPI_TransmitChannelIndexGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, uint8_t* idx); + +// ***************************************************************************** +//! Transmit FIFO Event Enable +/*! + * Enables Transmit FIFO interrupts + */ + +int8_t DRV_CANFDSPI_TransmitChannelEventEnable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT flags); + +// ***************************************************************************** +//! Transmit FIFO Event Disable +/*! + * Disables Transmit FIFO interrupts + */ + +int8_t DRV_CANFDSPI_TransmitChannelEventDisable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT flags); + +// ***************************************************************************** +//! Transmit FIFO Event Clear +/*! + * Clears Transmit FIFO Attempts Exhausted interrupt Flag + */ + +int8_t DRV_CANFDSPI_TransmitChannelEventAttemptClear(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel); + + +// ***************************************************************************** +//! Transmit Queue Index Get + +/*! + * Reads Transmit Queue Index + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueIndexGet(CANFDSPI_MODULE_ID index, uint8_t* idx) +{ + return DRV_CANFDSPI_TransmitChannelIndexGet(index, CAN_TXQUEUE_CH0, idx); +} + +// ***************************************************************************** +//! Transmit Queue Event Enable + +/*! + * Enables Transmit Queue interrupts + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueEventEnable(CANFDSPI_MODULE_ID index, + CAN_TX_FIFO_EVENT flags) +{ + return DRV_CANFDSPI_TransmitChannelEventEnable(index, CAN_TXQUEUE_CH0, flags); +} + +// ***************************************************************************** +//! Transmit Queue Event Disable + +/*! + * Disables Transmit FIFO interrupts + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueEventDisable(CANFDSPI_MODULE_ID index, + CAN_TX_FIFO_EVENT flags) +{ + return DRV_CANFDSPI_TransmitChannelEventDisable(index, CAN_TXQUEUE_CH0, flags); +} + +// ***************************************************************************** +//! Transmit Queue Event Clear + +/*! + * Clears Transmit FIFO Attempts Exhausted interrupt Flag + */ + +inline int8_t DRV_CANFDSPI_TransmitQueueEventAttemptClear(CANFDSPI_MODULE_ID index) +{ + return DRV_CANFDSPI_TransmitChannelEventAttemptClear(index, CAN_TXQUEUE_CH0); +} + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Receive FIFO Events + +// ***************************************************************************** +//! Receive FIFO Event Get +/*! + * Reads Receive FIFO interrupt Flags + */ + +int8_t DRV_CANFDSPI_ReceiveChannelEventGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT* flags); + +// ***************************************************************************** +//! Get pending interrupts of all receive FIFOs + +int8_t DRV_CANFDSPI_ReceiveEventGet(CANFDSPI_MODULE_ID index, uint32_t* rxif); + +// ***************************************************************************** +//!Get pending RXOVIF of all receive FIFOs + +int8_t DRV_CANFDSPI_ReceiveEventOverflowGet(CANFDSPI_MODULE_ID index, uint32_t* rxovif); + +// ***************************************************************************** +//! Receive FIFO Index Get +/*! + * Reads Receive FIFO Index + */ + +int8_t DRV_CANFDSPI_ReceiveChannelIndexGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, uint8_t* idx); + +// ***************************************************************************** +//! Receive FIFO Event Enable +/*! + * Enables Receive FIFO interrupts + */ + +int8_t DRV_CANFDSPI_ReceiveChannelEventEnable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT flags); + +// ***************************************************************************** +//! Receive FIFO Event Disable +/*! + * Disables Receive FIFO interrupts + */ + +int8_t DRV_CANFDSPI_ReceiveChannelEventDisable(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT flags); + +// ***************************************************************************** +//! Receive FIFO Event Clear +/*! + * Clears Receive FIFO Overflow interrupt Flag + */ + +int8_t DRV_CANFDSPI_ReceiveChannelEventOverflowClear(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Transmit Event FIFO Events + +// ***************************************************************************** +//! Transmit Event FIFO Event Get +/*! + * Reads Transmit Event FIFO interrupt Flags + */ + +int8_t DRV_CANFDSPI_TefEventGet(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_EVENT* flags); + +// ***************************************************************************** +//! Transmit Event FIFO Event Enable +/*! + * Enables Transmit Event FIFO interrupts + */ + +int8_t DRV_CANFDSPI_TefEventEnable(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_EVENT flags); + +// ***************************************************************************** +//! Transmit Event FIFO Event Disable +/*! + * Disables Transmit Event FIFO interrupts + */ + +int8_t DRV_CANFDSPI_TefEventDisable(CANFDSPI_MODULE_ID index, + CAN_TEF_FIFO_EVENT flags); + +// ***************************************************************************** +//! Transmit Event FIFO Event Clear +/*! + * Clears Transmit Event FIFO Overflow interrupt Flag + */ + +int8_t DRV_CANFDSPI_TefEventOverflowClear(CANFDSPI_MODULE_ID index); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Error Handling + +// ***************************************************************************** +//! Transmit Error Count Get + +int8_t DRV_CANFDSPI_ErrorCountTransmitGet(CANFDSPI_MODULE_ID index, + uint8_t* tec); + +// ***************************************************************************** +//! Receive Error Count Get + +int8_t DRV_CANFDSPI_ErrorCountReceiveGet(CANFDSPI_MODULE_ID index, + uint8_t* rec); + +// ***************************************************************************** +//! Error State Get + +int8_t DRV_CANFDSPI_ErrorStateGet(CANFDSPI_MODULE_ID index, + CAN_ERROR_STATE* flags); + +// ***************************************************************************** +//! Error Counts and Error State Get +/*! + * Returns content of complete CiTREC + */ + +int8_t DRV_CANFDSPI_ErrorCountStateGet(CANFDSPI_MODULE_ID index, + uint8_t* tec, uint8_t* rec, CAN_ERROR_STATE* flags); + +// ***************************************************************************** +//! Get Bus Diagnostic Registers: all data at once, since we want to keep them in synch + +int8_t DRV_CANFDSPI_BusDiagnosticsGet(CANFDSPI_MODULE_ID index, + CAN_BUS_DIAGNOSTIC* bd); + +// ***************************************************************************** +//! Clear Bus Diagnostic Registers + +int8_t DRV_CANFDSPI_BusDiagnosticsClear(CANFDSPI_MODULE_ID index); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: ECC + +// ***************************************************************************** +//! Enable ECC + +int8_t DRV_CANFDSPI_EccEnable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Disable ECC + +int8_t DRV_CANFDSPI_EccDisable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! ECC Event Get + +int8_t DRV_CANFDSPI_EccEventGet(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT* flags); + +// ***************************************************************************** +//! Set ECC Parity + +int8_t DRV_CANFDSPI_EccParitySet(CANFDSPI_MODULE_ID index, + uint8_t parity); + +// ***************************************************************************** +//! Get ECC Parity + +int8_t DRV_CANFDSPI_EccParityGet(CANFDSPI_MODULE_ID index, + uint8_t* parity); + +// ***************************************************************************** +//! Get ECC Error Address + +int8_t DRV_CANFDSPI_EccErrorAddressGet(CANFDSPI_MODULE_ID index, + uint16_t* a); + +// ***************************************************************************** +//! ECC Event Enable + +int8_t DRV_CANFDSPI_EccEventEnable(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT flags); + +// ***************************************************************************** +//! ECC Event Disable + +int8_t DRV_CANFDSPI_EccEventDisable(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT flags); + +// ***************************************************************************** +//! ECC Event Clear + +int8_t DRV_CANFDSPI_EccEventClear(CANFDSPI_MODULE_ID index, + CAN_ECC_EVENT flags); + +// ***************************************************************************** +//! Initialize RAM + +int8_t DRV_CANFDSPI_RamInit(CANFDSPI_MODULE_ID index, uint8_t d); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: CRC + +// ***************************************************************************** +//! CRC Event Enable + +int8_t DRV_CANFDSPI_CrcEventEnable(CANFDSPI_MODULE_ID index, + CAN_CRC_EVENT flags); + +// ***************************************************************************** +//! CRC Event Disable + +int8_t DRV_CANFDSPI_CrcEventDisable(CANFDSPI_MODULE_ID index, + CAN_CRC_EVENT flags); + +// ***************************************************************************** +//! CRC Event Clear + +int8_t DRV_CANFDSPI_CrcEventClear(CANFDSPI_MODULE_ID index, + CAN_CRC_EVENT flags); + +// ***************************************************************************** +//! CRC Event Get + +int8_t DRV_CANFDSPI_CrcEventGet(CANFDSPI_MODULE_ID index, CAN_CRC_EVENT* flags); + +// ***************************************************************************** +//! Get CRC Value from device + +int8_t DRV_CANFDSPI_CrcValueGet(CANFDSPI_MODULE_ID index, uint16_t* crc); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Time Stamp + +// ***************************************************************************** +//! Time Stamp Enable + +int8_t DRV_CANFDSPI_TimeStampEnable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Time Stamp Disable + +int8_t DRV_CANFDSPI_TimeStampDisable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Time Stamp Get + +int8_t DRV_CANFDSPI_TimeStampGet(CANFDSPI_MODULE_ID index, uint32_t* ts); + +// ***************************************************************************** +//! Time Stamp Set + +int8_t DRV_CANFDSPI_TimeStampSet(CANFDSPI_MODULE_ID index, uint32_t ts); + +// ***************************************************************************** +//! Time Stamp Mode Configure + +int8_t DRV_CANFDSPI_TimeStampModeConfigure(CANFDSPI_MODULE_ID index, + CAN_TS_MODE mode); + +// ***************************************************************************** +//! Time Stamp Prescaler Set + +int8_t DRV_CANFDSPI_TimeStampPrescalerSet(CANFDSPI_MODULE_ID index, + uint16_t ps); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Oscillator and Bit Time + +// ***************************************************************************** +//! Enable oscillator to wake-up from sleep + +int8_t DRV_CANFDSPI_OscillatorEnable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Set Oscillator Control + +int8_t DRV_CANFDSPI_OscillatorControlSet(CANFDSPI_MODULE_ID index, + CAN_OSC_CTRL ctrl); + +int8_t DRV_CANFDSPI_OscillatorControlObjectReset(CAN_OSC_CTRL* ctrl); + + +// ***************************************************************************** +//! Get Oscillator Status + +int8_t DRV_CANFDSPI_OscillatorStatusGet(CANFDSPI_MODULE_ID index, + CAN_OSC_STATUS* status); + +// ***************************************************************************** +//! Configure Bit Time registers (based on CAN clock speed) + +int8_t DRV_CANFDSPI_BitTimeConfigure(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode, + CAN_SYSCLK_SPEED clk); + +// ***************************************************************************** +//! Configure Nominal bit time for 40MHz system clock + +int8_t DRV_CANFDSPI_BitTimeConfigureNominal40MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime); + +// ***************************************************************************** +//! Configure Data bit time for 40MHz system clock + +int8_t DRV_CANFDSPI_BitTimeConfigureData40MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode); + +// ***************************************************************************** +//! Configure Nominal bit time for 20MHz system clock + +int8_t DRV_CANFDSPI_BitTimeConfigureNominal20MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime); + +// ***************************************************************************** +//! Configure Data bit time for 20MHz system clock + +int8_t DRV_CANFDSPI_BitTimeConfigureData20MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode); + +// ***************************************************************************** +//! Configure Nominal bit time for 10MHz system clock + +int8_t DRV_CANFDSPI_BitTimeConfigureNominal10MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime); + +// ***************************************************************************** +//! Configure Data bit time for 10MHz system clock + +int8_t DRV_CANFDSPI_BitTimeConfigureData10MHz(CANFDSPI_MODULE_ID index, + CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: GPIO + +// ***************************************************************************** +//! Initialize GPIO Mode + +int8_t DRV_CANFDSPI_GpioModeConfigure(CANFDSPI_MODULE_ID index, + GPIO_PIN_MODE gpio0, GPIO_PIN_MODE gpio1); + +// ***************************************************************************** +//! Initialize GPIO Direction + +int8_t DRV_CANFDSPI_GpioDirectionConfigure(CANFDSPI_MODULE_ID index, + GPIO_PIN_DIRECTION gpio0, GPIO_PIN_DIRECTION gpio1); + +// ***************************************************************************** +//! Enable Transceiver Standby Control + +int8_t DRV_CANFDSPI_GpioStandbyControlEnable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Disable Transceiver Standby Control + +int8_t DRV_CANFDSPI_GpioStandbyControlDisable(CANFDSPI_MODULE_ID index); + +// ***************************************************************************** +//! Configure Open Drain Interrupts + +int8_t DRV_CANFDSPI_GpioInterruptPinsOpenDrainConfigure(CANFDSPI_MODULE_ID index, + GPIO_OPEN_DRAIN_MODE mode); + +// ***************************************************************************** +//! Configure Open Drain TXCAN + +int8_t DRV_CANFDSPI_GpioTransmitPinOpenDrainConfigure(CANFDSPI_MODULE_ID index, + GPIO_OPEN_DRAIN_MODE mode); + +// ***************************************************************************** +//! GPIO Output Pin Set + +int8_t DRV_CANFDSPI_GpioPinSet(CANFDSPI_MODULE_ID index, + GPIO_PIN_POS pos, GPIO_PIN_STATE latch); + +// ***************************************************************************** +//! GPIO Input Pin Read + +int8_t DRV_CANFDSPI_GpioPinRead(CANFDSPI_MODULE_ID index, + GPIO_PIN_POS pos, GPIO_PIN_STATE* state); + +// ***************************************************************************** +//! Configure CLKO Pin + +int8_t DRV_CANFDSPI_GpioClockOutputConfigure(CANFDSPI_MODULE_ID index, + GPIO_CLKO_MODE mode); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Miscellaneous + +// ***************************************************************************** +//! DLC to number of actual data bytes conversion + +uint32_t DRV_CANFDSPI_DlcToDataBytes(CAN_DLC dlc); + +// ***************************************************************************** +//! FIFO Index Get + +int8_t DRV_CANFDSPI_FifoIndexGet(CANFDSPI_MODULE_ID index, + CAN_FIFO_CHANNEL channel, uint8_t* mi); + +// ***************************************************************************** +//! Calculate CRC16 + +uint16_t DRV_CANFDSPI_CalculateCRC16(uint8_t* data, uint16_t size); + +// ***************************************************************************** +//! Data bytes to DLC conversion + +CAN_DLC DRV_CANFDSPI_DataBytesToDlc(uint8_t n); + + +#endif // _DRV_CANFDSPI_API_H