diff options
author | Martin Aberg <maberg@gaisler.com> | 2017-04-03 13:27:49 +0200 |
---|---|---|
committer | Daniel Hellstrom <daniel@gaisler.com> | 2017-05-14 12:31:58 +0200 |
commit | 2d3d8f96b2f76eb03a7330aa039c303f4a3508f8 (patch) | |
tree | bd8ad7b1973762f23fc123a6ffa1cfb24c1cd964 /c/src/lib/libbsp/sparc/shared/include | |
parent | leon, grcan: updated device name and use it for ISR (diff) | |
download | rtems-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.h | 80 |
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); |