Files
Seeed_Arduino_CAN/mcp2518fd_canfdspi_api.cpp
T

4183 lines
106 KiB
C++

/*******************************************************************************
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 "mcp2518fd_canfdspi_api.h"
#include <SPI.h>
extern SPIClass* pSPI;
#define spi_readwrite pSPI->transfer
#define spi_read() spi_readwrite(0x00)
#define spi_write(spi_val) spi_readwrite(spi_val)
#define SPI_BEGIN() pSPI->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0))
#define SPI_END() pSPI->endTransaction();
// *****************************************************************************
// *****************************************************************************
// Section: Defines
#define CRCBASE 0xFFFF
#define CRCUPPER 1
// *****************************************************************************
// *****************************************************************************
// Section: Variables
//! SPI Transmit buffer
uint8_t spiTransmitBuffer[SPI_DEFAULT_BUFFER_LENGTH+2];
//! 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;
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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;
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spiReceiveBuffer[2] = spi_readwrite(0x00);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
Serial.printf("DRV_CANFDSPI_ReadByte = %d\n\r",spiReceiveBuffer[2]);
// 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;
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spi_readwrite(spiTransmitBuffer[2]);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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);
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
for (i = 2; i < 6; i++) {
spiReceiveBuffer[i] = spi_readwrite(0x00);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
// 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);
}
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spi_readwrite(spiTransmitBuffer[2]);
spi_readwrite(spiTransmitBuffer[3]);
spi_readwrite(spiTransmitBuffer[4]);
spi_readwrite(spiTransmitBuffer[5]);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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);
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
for (i = 2; i < 4; i++) {
spiReceiveBuffer[i] = spi_readwrite(0x00);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
// 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);
}
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spi_readwrite(spiTransmitBuffer[2]);
spi_readwrite(spiTransmitBuffer[3]);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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;
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spi_readwrite(spiTransmitBuffer[2]);
spi_readwrite(spiTransmitBuffer[3]);
spi_readwrite(spiTransmitBuffer[4]);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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;
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spi_readwrite(spiTransmitBuffer[2]);
spi_readwrite(spiTransmitBuffer[3]);
spi_readwrite(spiTransmitBuffer[4]);
spi_readwrite(spiTransmitBuffer[5]);
spi_readwrite(spiTransmitBuffer[6]);
spi_readwrite(spiTransmitBuffer[7]);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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;
}
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
for (i = 0; i < nBytes; i++) {
spiReceiveBuffer[i + 2] = spi_readwrite(0x00);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
// 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;
}
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spi_readwrite(spiTransmitBuffer[2]);
for (i = 3; i < spiTransferSize; i++) {
spiReceiveBuffer[i] = spi_readwrite(0x00);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
// 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];
}
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
for (i = 2; i < spiTransferSize; i++) {
spi_readwrite(spiTransmitBuffer[i]);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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);
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
spi_readwrite(spiTransmitBuffer[2]);
for (i = 0; i < nBytes; i++) {
spi_readwrite(spiTransmitBuffer[i + 3]);
}
spi_readwrite(spiTransmitBuffer[spiTransferSize - 2]);
spi_readwrite(spiTransmitBuffer[spiTransferSize - 1]);
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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;
}
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
for (i = 2; i < spiTransferSize; i++) {
//for (i = 2; i < 6; i++) {
spiReceiveBuffer[i] = spi_readwrite(0x00);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
// 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_ReadWordArray1(CANFDSPI_MODULE_ID index, uint16_t address,
uint32_t *rxd)
{
uint16_t i;
//REG_t w;
//uint16_t spiTransferSize = nWords * 4 + 2;
uint16_t spiTransferSize = 6;
int8_t spiTransferError = 0;
// Compose command
spiTransmitBuffer[0] = (cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF);
spiTransmitBuffer[1] = address & 0xFF;
// Clear data
// for (i = 2; i < 6; i++) {
// spiTransmitBuffer[i] = 0;
// }
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
for (i = 2; i < 6; i++) {
spiReceiveBuffer[i] = spi_readwrite(0x00);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
// Update data
uint32_t x;
*rxd = 0;
for (i = 2; i < 6; i++) {
x = (uint32_t) spiReceiveBuffer[i];
*rxd += x << ((i - 2)*8);
}
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];
}
}
#ifdef SPI_HAS_TRANSACTION
SPI_BEGIN();
#endif
MCP2518fd_SELECT();
spi_readwrite(spiTransmitBuffer[0]);
spi_readwrite(spiTransmitBuffer[1]);
for (i = 2; i < spiTransferSize; i++) {
spi_readwrite(spiTransmitBuffer[i]);
}
MCP2518fd_UNSELECT();
#ifdef SPI_HAS_TRANSACTION
SPI_END();
#endif
delay(10);
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;
Serial.printf("into DRV_CANFDSPI_TransmitChannelConfigure\n\r");
// 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]; //10010010100101010000
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)
{
Serial.printf("into DRV_CANFDSPI_TransmitChannelLoad\n\r");
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;
}
}
Serial.printf("txBuffer[8] = %d\n\r",txBuffer[8]);
Serial.printf("txBuffer[9] = %d\n\r",txBuffer[9]);
Serial.printf("txBuffer[10] = %d\n\r",txBuffer[10]);
Serial.printf("txBuffer[11] = %d\n\r",txBuffer[11]);
Serial.printf("txBuffer[12] = %d\n\r",txBuffer[12]);
Serial.printf("txBuffer[13] = %d\n\r",txBuffer[13]);
Serial.printf("txBuffer[14] = %d\n\r",txBuffer[14]);
Serial.printf("txBuffer[15] = %d\n\r",txBuffer[15]);
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;
}
Serial.printf("end DRV_CANFDSPI_TransmitChannelLoad\n\r");
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;
}
Serial.printf("ciFifoCon.txBF.TxEnable2 = %d\n\r",ciFifoCon.txBF.TxEnable);
// Check that it is a receive buffer
ciFifoCon.word = fifoReg[0];
Serial.printf("ciFifoCon.txBF.TxEnable3 = %d\n\r",fifoReg[0]);
ciFifoCon.txBF.TxEnable = 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;
}
Serial.printf("DRV_CANFDSPI_ReceiveMessageGet end\n\r");
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)
{
Serial.println("DRV_CANFDSPI_ReceiveChannelEventGet\n\r");
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;
Serial.printf("INTO DRV_CANFDSPI_EccEnable\n\r");
// 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, &reg.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 spi_test()
{
uint8_t txd[MAX_DATA_BYTES];
uint8_t rxd[MAX_DATA_BYTES];
uint8_t i;
uint8_t length;
for (length = 4;length <= MAX_DATA_BYTES; length += 4) {
for (i = 0; i < length; i++) {
txd[i] = rand() & 0xff;
rxd[i] = 0xff;
}
DRV_CANFDSPI_WriteByteArray(0,cRAMADDR_START,txd,length);
DRV_CANFDSPI_ReadByteArray(0,cRAMADDR_START,rxd,length);
bool good = false;
for (i = 0; i < length;i++) {
good = txd[i] == rxd[i];
if (!good) {
return 0;
}
}
return 1;
}
}
int8_t DRV_CANFDSPI_RamInit(CANFDSPI_MODULE_ID index, uint8_t d)
{
Serial.println("DRV_CANFDSPI_RamInit-------start\n\r");
int8_t b;
b = spi_test();
Serial.printf("DRV_CANFDSPI_RamInit spi_test() = %d\n\r",b);
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;
}