summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/include
diff options
context:
space:
mode:
authorMartin Aberg <maberg@gaisler.com>2017-04-03 13:27:49 +0200
committerDaniel Hellstrom <daniel@gaisler.com>2017-05-14 12:31:58 +0200
commit2d3d8f96b2f76eb03a7330aa039c303f4a3508f8 (patch)
treebd8ad7b1973762f23fc123a6ffa1cfb24c1cd964 /c/src/lib/libbsp/sparc/shared/include
parentleon, grcan: updated device name and use it for ISR (diff)
downloadrtems-2d3d8f96b2f76eb03a7330aa039c303f4a3508f8.tar.bz2
leon, grcan: redesigned bus-off and AHB error handling
When bus-off condition is detected by the ISR, it sets the started flag to STATE_BUSOFF. This is monitored by the user functions grcan_read() and grcan_write() each time they want to enable DMA or update interrupt mask. If they detect that ISR has detected bus-off then they will return either with an error or with the number of CAN messages processed. Future calls to functions which require STARTED mode will be rejected and grcan_isstarted() will return 0. The next call to grcan_stop() will do the transition from BUSOFF->STOPPED and the device can then be started again with grcan_start(). Similar to a bus-off condition, the AHB error condition detected by the ISR will trigger the same shut-down logic of the driver. The difference is that the state entered is STATE_AHBERR and the routines will return a different value to indicate AHB error state. This commit also fixes an issue where ISR was not always unregistered on close. User functions can cause these transitions: STATE_STOPPED -> STATE_STARTED (grcan_start) STATE_STARTED -> STATE_STOPPED (grcan_stop) STATE_BUSOFF -> STATE_STOPPED (grcan_stop, grcan_close) STATE_AHBERR -> STATE_STOPPED (grcan_stop, grcan_close) ISR can cause these transition STATE_STARTED -> STATE_BUSOFF (grcan_interrupt) STATE_STARTED -> STATE_AHBERR (grcan_interrupt) STATE_BUSOFF/AHBERR is entered from ISR on bus-off condition. At transition the ISR disables DMA, masks all interrupts and flushes semaphores. Other related updates: * Statistics are updated from the ISR. Update is now spin-locked to ensure a consistent user view. * The debug output has been updated to include state changes. * For read/write/flush, return error (-4) if driver aborted the operation due to bus-off. Likewise if abourted due to AHB error -5 is returned. * Collect bus-off statistics Related to the new BUSOFF and AHBERR states the API has been updated to reflect the current SW driver state. The isstarted() function has been replaced with get_state().
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/include')
-rw-r--r--c/src/lib/libbsp/sparc/shared/include/grcan.h80
1 files changed, 65 insertions, 15 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/include/grcan.h b/c/src/lib/libbsp/sparc/shared/include/grcan.h
index 7de76a7286..5cdbad4b01 100644
--- a/c/src/lib/libbsp/sparc/shared/include/grcan.h
+++ b/c/src/lib/libbsp/sparc/shared/include/grcan.h
@@ -68,6 +68,7 @@ struct grcan_stats {
unsigned int txloss_cnt;
unsigned int ahberr_cnt;
unsigned int ints;
+ unsigned int busoff_cnt;
};
struct grcan_timing {
@@ -99,6 +100,39 @@ typedef struct {
unsigned int id;
} CANMsg;
+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
@@ -198,13 +232,14 @@ extern int grcan_close(void *d);
* count: Number of CAN messages to receive
*
* return:
- * >=0: Number of CAN messages received. This can be less than the
- * count parameter.
- * -1: count parameter less than size of struct grcan_msg or NULL msg.
- * -2: Device not in started mode
- * -3: Timeout in non-blocking mode
- * -4: A blocking read was interrupted by a Bus-off error. Device has
- * left started mode.
+ * >=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,
@@ -222,12 +257,14 @@ extern int grcan_read(
* count: Number of CAN messages to transmit
*
* return:
- * >=0: Number of CAN messages transmitted. This can be less than the
- * count parameter.
- * -1: count parameter less than size of struct grcan_msg
- * -2: Device not in started mode
- * -3: Timeout in non-blocking mode
- * -4: Bus-off error. Device has left started mode
+ * >=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,
@@ -235,6 +272,21 @@ extern int grcan_write(
size_t count
);
+/*
+ * 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
@@ -244,8 +296,6 @@ extern int grcan_write(
extern int grcan_start(void *d);
/* stop to change baud rate/config or closing down */
extern int grcan_stop(void *d);
-/* return 1 when started, othervise 0 */
-extern int grcan_isstarted(void *d);
/* Wait until all TX messages have been sent */
extern int grcan_flush(void *d);