Files
rtems/bsps/include/grlib/grcan.h
Daniel Hellstrom c41e7bae9c leon,grcan: added support for GRCANFD
The new GRCAN_FD IP supports CAN FD standard and is mostly backwards
compatible with GRCAN SW interface. The GRCAN driver have been extended
to support the GRCANFD IP using the same driver.

Additional functions have been added that uses a new CAN FD frame
format and read/write/baud-rate functions that supports both GRCANFD
and GRCAN. To keep the SW API fully backwards compatible with GRCAN,
the old functions remain.

Update #4307.
2021-03-07 16:08:24 +01:00

476 lines
14 KiB
C

/**
* @file
* @ingroup can
* @brief Driver API for the GRLIB GRCAN and GRCANFD controllers
*/
/*
* COPYRIGHT (c) 2007.
* Cobham Gaisler AB.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifndef __GRCAN_H__
#define __GRCAN_H__
/**
* @defgroup can GRCAN
*
* @ingroup RTEMSBSPsSharedGRLIB
*
* @brief Macros used for grcan controller
*
* @{
*/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct grcan_regs {
volatile unsigned int conf; /* 0x00 */
volatile unsigned int stat; /* 0x04 */
volatile unsigned int ctrl; /* 0x08 */
volatile unsigned int dummy0[3]; /* 0x0C-0x014 */
volatile unsigned int smask; /* 0x18 */
volatile unsigned int scode; /* 0x1C */
volatile unsigned int dummy1[8]; /* 0x20-0x3C */
volatile unsigned int nbtr; /* 0x40 */
volatile unsigned int fdbtr; /* 0x44 */
volatile unsigned int tdelay; /* 0x48 */
volatile unsigned int dummy1b[45]; /* 0x4C-0xFC */
volatile unsigned int pimsr; /* 0x100 */
volatile unsigned int pimr; /* 0x104 */
volatile unsigned int pisr; /* 0x108 */
volatile unsigned int pir; /* 0x10C */
volatile unsigned int imr; /* 0x110 */
volatile unsigned int picr; /* 0x114 */
volatile unsigned int dummy2[58]; /* 0x118-0x1FC */
volatile unsigned int tx0ctrl; /* 0x200 */
volatile unsigned int tx0addr; /* 0x204 */
volatile unsigned int tx0size; /* 0x208 */
volatile unsigned int tx0wr; /* 0x20C */
volatile unsigned int tx0rd; /* 0x210 */
volatile unsigned int tx0irq; /* 0x214 */
volatile unsigned int dummy3[58]; /* 0x218-0x2FC */
volatile unsigned int rx0ctrl; /* 0x300 */
volatile unsigned int rx0addr; /* 0x304 */
volatile unsigned int rx0size; /* 0x308 */
volatile unsigned int rx0wr; /* 0x30C */
volatile unsigned int rx0rd; /* 0x310 */
volatile unsigned int rx0irq; /* 0x314 */
volatile unsigned int rx0mask; /* 0x318 */
volatile unsigned int rx0code; /* 0x31C */
};
struct grcan_stats {
unsigned int passive_cnt;
unsigned int overrun_cnt;
unsigned int rxsync_cnt;
unsigned int txsync_cnt;
unsigned int txloss_cnt;
unsigned int ahberr_cnt;
unsigned int ints;
unsigned int busoff_cnt;
};
struct grcan_timing {
unsigned char scaler;
unsigned char ps1;
unsigned char ps2;
unsigned char rsj;
unsigned char bpr;
};
struct grcanfd_timing {
unsigned char scaler;
unsigned char ps1;
unsigned char ps2;
unsigned char sjw;
unsigned char resv_zero;
};
struct grcan_selection {
int selection;
int enable0;
int enable1;
};
struct grcan_filter {
unsigned long long mask;
unsigned long long code;
};
#define GRCAN_FDOPT_NOM 0
#define GRCAN_FDOPT_FDBTR 0x01
#define GRCAN_FDOPT_FDFRM 0x02
#define GRCAN_FDMASK (GRCAN_FDOPT_FDBTR | GRCAN_FDOPT_FDFRM)
/* CAN MESSAGE */
typedef struct {
char extended; /* 1= Extended Frame (29-bit id), 0= STD Frame (11-bit id) */
char rtr; /* RTR - Remote Transmission Request */
char unused; /* Must be 0 to select classic CAN frame */
unsigned char len;
unsigned char data[8];
unsigned int id;
} CANMsg;
/* CAN-FD MESSAGE */
typedef struct {
uint8_t extended; /* 1= Extended Frame (29-bit id), 0= STD Frame (11-bit id) */
uint8_t rtr; /* RTR - Remote Transmission Request */
uint8_t fdopts; /* Bit1: 1=Switch bit rate. bit2: 1=FD frame. */
uint8_t len; /* 0-8, 12, 16, 20, 24, 32, 48 or 64 bytes */
uint32_t id;
union {
uint64_t dwords[8]; /* up to 64 bytes if FD=1 and len>8 */
uint8_t bytes[64]; /* up to 64 bytes if FD=1 and len>8 */
} data;
} CANFDMsg;
enum {
GRCAN_RET_OK = 0,
GRCAN_RET_INVARG = -1,
GRCAN_RET_NOTSTARTED = -2,
GRCAN_RET_TIMEOUT = -3,
/* Bus-off condition detected (request aborted by driver) */
GRCAN_RET_BUSOFF = -4,
/* AHB error condition detected (request aborted by driver) */
GRCAN_RET_AHBERR = -5,
};
/*
* User functions can cause these transitions:
* STATE_STOPPED -> STATE_STARTED
* STATE_STARTED -> STATE_STOPPED
* STATE_BUSOFF -> STATE_STOPPED
* STATE_AHBERR -> STATE_STOPPED
*
* ISR can cause these transition
* STATE_STARTED -> STATE_BUSOFF
* STATE_STARTED -> STATE_AHBERR
*
* STATE_BUSOFF is entered from ISR on bus-off condition. STATE_AHBERR is
* entered from ISR on AHB DMA errors on RX/TX operations. At transition the ISR
* disables DMA, masks all interrupts and releases semaphores.
*/
enum grcan_state {
STATE_STOPPED = 0,
STATE_STARTED = 1,
STATE_BUSOFF = 2,
STATE_AHBERR = 3,
};
#define GRCAN_CFG_ABORT 0x00000001
#define GRCAN_CFG_ENABLE0 0x00000002
#define GRCAN_CFG_ENABLE1 0x00000004
#define GRCAN_CFG_SELECTION 0x00000008
#define GRCAN_CFG_SILENT 0x00000010
#define GRCAN_CFG_BPR 0x00000300
#define GRCAN_CFG_RSJ 0x00007000
#define GRCAN_CFG_PS1 0x00f00000
#define GRCAN_CFG_PS2 0x000f0000
#define GRCAN_CFG_SCALER 0xff000000
#define GRCAN_CFG_BPR_BIT 8
#define GRCAN_CFG_RSJ_BIT 12
#define GRCAN_CFG_PS1_BIT 20
#define GRCAN_CFG_PS2_BIT 16
#define GRCAN_CFG_SCALER_BIT 24
#define GRCAN_CTRL_RESET 0x2
#define GRCAN_CTRL_ENABLE 0x1
#define GRCAN_TXCTRL_ENABLE 1
#define GRCAN_TXCTRL_ONGOING 1
#define GRCAN_RXCTRL_ENABLE 1
#define GRCAN_RXCTRL_ONGOING 1
#define GRCANFD_NBTR_SCALER 0x00ff0000
#define GRCANFD_NBTR_PS1 0x0000fc00
#define GRCANFD_NBTR_PS2 0x000003e0
#define GRCANFD_NBTR_SJW 0x0000001f
#define GRCANFD_NBTR_SCALER_BIT 16
#define GRCANFD_NBTR_PS1_BIT 10
#define GRCANFD_NBTR_PS2_BIT 5
#define GRCANFD_NBTR_SJW_BIT 0
#define GRCANFD_FDBTR_SCALER 0x00ff0000
#define GRCANFD_FDBTR_PS1 0x00003c00
#define GRCANFD_FDBTR_PS2 0x000001e0
#define GRCANFD_FDBTR_SJW 0x0000000f
#define GRCANFD_FDBTR_SCALER_BIT 16
#define GRCANFD_FDBTR_PS1_BIT 10
#define GRCANFD_FDBTR_PS2_BIT 5
#define GRCANFD_FDBTR_SJW_BIT 0
/* Relative offset of IRQ sources to AMBA Plug&Play */
#define GRCAN_IRQ_IRQ 0
#define GRCAN_IRQ_TXSYNC 1
#define GRCAN_IRQ_RXSYNC 2
#define GRCAN_ERR_IRQ 0x1
#define GRCAN_OFF_IRQ 0x2
#define GRCAN_OR_IRQ 0x4
#define GRCAN_RXAHBERR_IRQ 0x8
#define GRCAN_TXAHBERR_IRQ 0x10
#define GRCAN_RXIRQ_IRQ 0x20
#define GRCAN_TXIRQ_IRQ 0x40
#define GRCAN_RXFULL_IRQ 0x80
#define GRCAN_TXEMPTY_IRQ 0x100
#define GRCAN_RX_IRQ 0x200
#define GRCAN_TX_IRQ 0x400
#define GRCAN_RXSYNC_IRQ 0x800
#define GRCAN_TXSYNC_IRQ 0x1000
#define GRCAN_RXERR_IRQ 0x2000
#define GRCAN_TXERR_IRQ 0x4000
#define GRCAN_RXMISS_IRQ 0x8000
#define GRCAN_TXLOSS_IRQ 0x10000
#define GRCAN_STAT_PASS 0x1
#define GRCAN_STAT_OFF 0x2
#define GRCAN_STAT_OR 0x4
#define GRCAN_STAT_AHBERR 0x8
#define GRCAN_STAT_ACTIVE 0x10
#define GRCAN_STAT_RXERRCNT 0xff00
#define GRCAN_STAT_TXERRCNT 0xff0000
/*
* Return number of GRCAN devices available to driver
*/
extern int grcan_dev_count(void);
/*
* Open a GRCAN device
*
* dev_no: Device number to open
* return: Device handle to use with all other grcan_ API functions. The
* function returns NULL if device can not be opened.
*/
extern void *grcan_open(int dev_no);
/*
* Open a GRCAN device by name. Finds device index then calls
* grcan_open(index).
*
* name: Device name to open
* dev_no: Device number matching name. Will be set if device found.
* return: Device handle to use with all other grcan_ API functions. The
* function returns NULL if device can not be opened or not found.
*/
extern void *grcan_open_by_name(char *name, int *dev_no);
/*
* Close a GRCAN device
*
* return: This function always returns 0 (success)
*/
extern int grcan_close(void *d);
/*
* Returns if CAN hardware device is CANFD capable.
*
* dev_no: Device handle
* return: 0=Not FD capable, 1=FD capable.
* function returns NULL if device can not be opened.
*/
extern int grcan_canfd_capable(void *d);
/*
* Receive CAN messages
*
* Multiple CAN messages can be received in one call.
*
* d: Device handle
* msg: Pointer to receive messages
* count: Number of CAN messages to receive
*
* return:
* >=0: Number of CAN messages received. This can be
* less than the count parameter.
* GRCAN_RET_INVARG: count parameter less than one or NULL msg.
* GRCAN_RET_NOTSTARTED: Device not in started mode
* GRCAN_RET_TIMEOUT: Timeout in non-blocking mode
* GRCAN_RET_BUSOFF: A read was interrupted by a bus-off error.
* Device has left started mode.
* GRCAN_RET_AHBERR: Similar to BUSOFF, but was caused by AHB Error.
*/
extern int grcan_read(
void *d,
CANMsg *msg,
size_t count
);
/*
* Receive CAN messages (only GRCANFD)
*
* Multiple CAN messages can be received in one call.
*
* d: Device handle
* msg: Pointer to receive messages
* count: Number of CAN messages to receive
*
* return:
* >=0: Number of CAN messages received. This can be
* less than the count parameter.
* GRCAN_RET_INVARG: count parameter less than one or NULL msg.
* GRCAN_RET_NOTSTARTED: Device not in started mode
* GRCAN_RET_TIMEOUT: Timeout in non-blocking mode
* GRCAN_RET_BUSOFF: A read was interrupted by a bus-off error.
* Device has left started mode.
* GRCAN_RET_AHBERR: Similar to BUSOFF, but was caused by AHB Error.
*/
extern int grcanfd_read(
void *d,
CANFDMsg *msg,
size_t count
);
/*
* Transmit CAN messages
*
* Multiple CAN messages can be transmit in one call.
*
* d: Device handle
* msg: Pointer to messages to transmit
* count: Number of CAN messages to transmit
*
* return:
* >=0: Number of CAN messages transmitted. This can be
* less than the count parameter.
* GRCAN_RET_INVARG: count parameter less than one.
* GRCAN_RET_NOTSTARTED: Device not in started mode
* GRCAN_RET_TIMEOUT: Timeout in non-blocking mode
* GRCAN_RET_BUSOFF: A write was interrupted by a Bus-off error.
* Device has left started mode
* GRCAN_RET_AHBERR: Similar to BUSOFF, but was caused by AHB Error.
*/
extern int grcan_write(
void *d,
CANMsg *msg,
size_t count
);
/*
* Transmit CAN-FD complient messages (only GRCANFD)
*
* Multiple CAN messages can be transmit in one call.
*
* d: Device handle
* msg: Pointer to messages to transmit
* count: Number of CAN messages to transmit
*
* return:
* >=0: Number of CAN messages transmitted. This can be
* less than the count parameter.
* GRCAN_RET_INVARG: count parameter less than one.
* GRCAN_RET_NOTSTARTED: Device not in started mode
* GRCAN_RET_TIMEOUT: Timeout in non-blocking mode
* GRCAN_RET_BUSOFF: A write was interrupted by a Bus-off error.
* Device has left started mode
* GRCAN_RET_AHBERR: Similar to BUSOFF, but was caused by AHB Error.
*/
extern int grcanfd_write(
void *d,
CANFDMsg *msg,
size_t ucount
);
/*
* Returns current GRCAN software state
*
* If STATE_BUSOFF or STATE_AHBERR is returned then the function grcan_stop()
* shall be called before continue using the driver.
*
* d: Device handle
* return:
* STATE_STOPPED Stopped
* STATE_STARTED Started
* STATE_BUSOFF Bus-off has been detected
* STATE_AHBERR AHB error has been detected
*/
extern int grcan_get_state(void *d);
/* The remaining functions return 0 on success and non-zero on failure. */
/* Functions controlling operational
* mode
*/
/* Bring the link up after open or bus-off */
extern int grcan_start(void *d);
/* stop to change baud rate/config or closing down */
extern int grcan_stop(void *d);
/* Wait until all TX messages have been sent */
extern int grcan_flush(void *d);
/* Functions that require connection
* to be stopped
*/
/* enable silent mode read only state */
extern int grcan_set_silent(void *d, int silent);
/* enable/disable stopping link on AHB Error */
extern int grcan_set_abort(void *d, int abort);
/* Set Enable0,Enable1,Selection */
extern int grcan_set_selection(void *d, const struct grcan_selection *selection);
/* Set baudrate by using driver's baud rate timing calculation routines */
extern int grcan_set_speed(void *d, unsigned int hz);
/* Set baudrate by specifying the timing registers manually */
extern int grcan_set_btrs(void *d, const struct grcan_timing *timing);
/* Set the Nominal and FD baudrate by using driver's baud rate timing
* calculation routines
*/
extern int grcanfd_set_speed(void *d, unsigned int nomhz, unsigned int fdhz);
/* Set Nominal and FD baudrate by specifying the timing registers manually*/
extern int grcanfd_set_btrs(
void *d,
const struct grcanfd_timing *nominal,
const struct grcanfd_timing *fd);
/* Functions can be called whenever */
/* Enable/disable Blocking on reception (until at least one message has been received) */
int grcan_set_rxblock(void* d, int block);
/* Enable/disable Blocking on transmission (until at least one message has been transmitted) */
int grcan_set_txblock(void* d, int block);
/* Enable/disable Blocking until all requested messages has been sent */
int grcan_set_txcomplete(void* d, int complete);
/* Enable/disable Blocking until all requested has been received */
int grcan_set_rxcomplete(void* d, int complete);
/* Get statistics */
extern int grcan_get_stats(void *d, struct grcan_stats *stats);
/* Clear statistics */
extern int grcan_clr_stats(void *d);
/* Set Acceptance filters, provide pointer to "struct grcan_filter" or NULL to disable filtering (let all messages pass) */
extern int grcan_set_afilter(void *d, const struct grcan_filter *filter);
/* Set Sync Messages RX/TX filters, NULL disables the IRQ completely */
extern int grcan_set_sfilter(void *d, const struct grcan_filter *filter);
/* Get status register of GRCAN core */
extern int grcan_get_status(void *d, unsigned int *status);
void grcan_register_drv(void);
#ifdef __cplusplus
}
#endif
/** @} */
#endif