Commit 35c09780 authored by Peter Zumbruch's avatar Peter Zumbruch
Browse files

can.c / can.h

- refactoring
- renaming of error messages
- added canBusMode strings
- canSendMessage
  - implemented check on canBusMode (current status) before sending
    - in case of an error (disabled, bus off, error passive) subsequent transmit are ignored until bus mode has been reset to "undefined"
      - which happens automatically by the can timer mechanism 
	within canBusStateResetInterval_seconds with a granularity 
	of the calculated canTimerInterval given by CANTCON
- new: canSetCanTimer 
  - enables to set the can timer clock cycle either 
    - by setting the prescaler [0,0xff] Tclk = 1/F_CPU x 8 x (prescaler + 1)
    - or by
    - setting the time in seconds
- canInit
  - added canSetCanTimer
  - setting canBusStoreState 
- canIsGeneralStatusErrorAndAcknowledge
  moved as inline to can.h 
- canIsMObErrorAndAcknowledge
  moved as inline to can.h 
- ISR(CANIT_vect)
  - setting canBusStoreState for BOFFIT interrupt
- ISR(OVRIT_vect)
  - reset error canBusStoredStates every canBusStateResetInterval_seconds 
    with the granularity canBusStoredState of the calculated canTimerInterval given by CANTCON 
    to canBusStoredState to undefined to allow for recovery

  - defined macro CAN_BUS_STATE_RESET_INTERVAL_SECONDS = 60.
  - enum:
      - bus state 
      - timer units 
  - new inline canGetCurrentBusModeStatus 


git-svn-id: https://subversion.gsi.de/epics/trunk/hadcon/API-Slave@408 50339f28-a4cd-11e1-ab1f-8360dde1fe65
parent 27140fe5
This diff is collapsed.
......@@ -26,6 +26,8 @@
#define CAN_USE_OLD_RECV_MESSAGE_FLAG TRUE;
#define CAN_USE_NEW_RECV_MESSAGE_FLAG TRUE;
#define CAN_BUS_STATE_RESET_INTERVAL_SECONDS 60.
struct canStruct
{
uint32_t id;
......@@ -38,6 +40,8 @@ extern struct canStruct canFrame;
extern struct canStruct *ptr_canStruct;
extern int32_t canDefaultBaudRate;
double canTimerInterval;
enum canState {
canState_IDLE = 0,
canState_RXOK = 1,
......@@ -52,10 +56,10 @@ enum canState {
extern const char *can_error[] PROGMEM;
enum ce_index
{
CAN_ERROR_Can_Bus_is_off = 0,
CAN_ERROR_Can_Bus_is_off_interrupt,
CAN_ERROR_Can_Bus_is_passive,
CAN_ERROR_Can_Bus_is_on,
CAN_ERROR_Bus_Off_Mode = 0,
CAN_ERROR_Bus_Off_Mode_interrupt,
CAN_ERROR_Error_Passive_Mode,
CAN_ERROR_Can_Controller_disabled,
CAN_ERROR_MOb_Bit_Error,
CAN_ERROR_MOb_Stuff_Error,
CAN_ERROR_MOb_CRC_Error,
......@@ -79,6 +83,25 @@ enum me_index
MOB_ERROR_MAXIMUM_INDEX
};
extern const char *canBusModes[] PROGMEM;
enum canChannelModes
{
canChannelMode_ERROR_ACTIVE = 0,
canChannelMode_ERROR_PASSIVE,
canChannelMode_BUS_OFF,
canChannelMode_CAN_DISABLED,
canChannelMode_UNDEFINED,
canChannelMode_MAXIMUM_INDEX
};
enum canTimerUnits
{
canTimerUnit_PRESCALER = 0,
canTimerUnit_SECONDS,
canTimerUnit_MAXIMUM_INDEX
};
/* implemented functions */
int8_t canInit( int32_t Baudrate ); /* initialize CAN communication*/
......@@ -87,12 +110,8 @@ void canEnableCan( void );
void canShowGeneralStatusError( void ); /* state on the CAN channel */
uint8_t canIsGeneralStatusErrorAndAcknowledge( void );
void canShowMObError( void ); /* can error for the communication */
uint8_t canIsMObErrorAndAcknowledge( void );
uint8_t canErrorHandling( uint8_t error );
void canSetMObCanIDandMask(uint32_t id, uint32_t mask, uint8_t enableRTRMaskBitComparison_flag, uint8_t enableIDExtensionMaskBitComparison_flag);
......@@ -132,4 +151,170 @@ uint8_t canBitTimingTQBasicBoundaryChecks(uint8_t propagationTimeSegment, uint8_
int8_t canCheckParameterCanFormat( struct uartStruct *ptr_uartStruct ); /* this function checks whether all the received parameters are valid*/
static inline uint8_t canGetCurrentBusModeStatus(void)
{
if ( ! (CANGSTA & (1 << ENFG )))
{
return canChannelMode_CAN_DISABLED;
}
else if ( CANGSTA & (1 << BOFF))
{
return canChannelMode_BUS_OFF;
}
else if ( CANGSTA & (1 << ERRP ))
{
return canChannelMode_ERROR_PASSIVE;
}
else
{
return canChannelMode_ERROR_ACTIVE;
}
}
static inline uint8_t canIsGeneralStatusErrorAndAcknowledge( void )
{
/*
To acknowledge a general interrupt, the corresponding bits of CANGIT register (BXOK, BOFFIT,...)
must be cleared by the software application. This operation is made writing a logical one
in these interrupt flags (writing a logical zero doesn’t change the interrupt flag value).
• Bit 7 – CANIT: General Interrupt Flag
This is a read only bit.
– 0 - no interrupt.
– 1 - CAN interrupt: image of all the CAN controller interrupts except for OVRTIM
interrupt. This bit can be used for polling method.
• Bit 6 – BOFFIT: Bus Off Interrupt Flag
Writing a logical one resets this interrupt flag. BOFFIT flag is only set when the CAN enters in
bus off mode (coming from error passive mode).
– 0 - no interrupt.
– 1 - bus off interrupt when the CAN enters in bus off mode.
• Bit 5 – OVRTIM: Overrun CAN Timer
Writing a logical one resets this interrupt flag. Entering in CAN timer overrun interrupt handler
also reset this interrupt flag
– 0 - no interrupt.
– 1 - CAN timer overrun interrupt: set when the CAN timer switches from 0xFFFF to 0.
• Bit 4 – BXOK: Frame Buffer Receive Interrupt
Writing a logical one resets this interrupt flag. BXOK flag can be cleared only if all CONMOB
fields of the MOb’s of the buffer have been re-written before.
– 0 - no interrupt.
– 1 - burst receive interrupt: set when the frame buffer receive is completed.
• Bit 3 – SERG: Stuff Error General
Writing a logical one resets this interrupt flag.
– 0 - no interrupt.
– 1 - stuff error interrupt: detection of more than 5 consecutive bits with the same
polarity.
• Bit 2 – CERG: CRC Error General
Writing a logical one resets this interrupt flag.
– 0 - no interrupt.
– 1 - CRC error interrupt: the CRC check on destuffed message does not fit with the
CRC field.
• Bit 1 – FERG: Form Error General
Writing a logical one resets this interrupt flag.
– 0 - no interrupt.
– 1 - form error interrupt: one or more violations of the fixed form in the CRC delimiter,
acknowledgment delimiter or EOF.
• Bit 0 – AERG: Acknowledgment Error General
Writing a logical one resets this interrupt flag.
– 0 - no interrupt.
– 1 - acknowledgment error interrupt: no detection of the dominant bit in acknowledge
slot.
*/
canCurrentGeneralStatus = CANGSTA;
canCurrentGeneralInterruptRegister = CANGIT;
canCurrentReceiveErrorCounter = CANREC;
canCurrentTransmitErrorCounter = CANTEC;
// reset all error Bits at once, leaving out read-only CANIT as well as BKOK and OVRTIM
CANGIT = (CANGIT & ( 0xFF & ~(1 << CANIT | 1 << BXOK | 1 << OVRTIM )));
return ((canCurrentGeneralInterruptRegister & ( 1 << BOFFIT | 1 << SERG | 1 << CERG | 1 << FERG | 1 << AERG )) ||
(canCurrentGeneralStatus & ( 1 << BOFF | 1 << ERRP )));
}//END of canIsGeneralStatusErrorAndAcknowledge
static inline uint8_t canIsMObErrorAndAcknowledge( void )
{
/* testing (and resetting) the following
* errors of CANSTMOB:
* BERR, SERR, CERR, FERR, AERR*/
static uint8_t errorBits = 0xFF & ( 1 << BERR | 1 << SERR | 1 << CERR | 1 << FERR | 1 << AERR );
// store current status
canCurrentMObStatus = CANSTMOB;
/*
To acknowledge a mob interrupt, the corresponding bits of CANSTMOB register (RXOK,
TXOK,...) must be cleared by the software application. This operation needs a read-modify-write
software routine.
from manual: chapter 19.8.2, p250
3.8.1 Interrupt Behavior
When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled.
The user software can write logic one to the I-bit to enable nested interrupts. All enabled
interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a
Return from Interrupt instruction – RETI – is executed.
There are basically two types of interrupts. The first type is triggered by an event that sets the
interrupt flag. For these interrupts, the Program Counter is vectored to the actual Interrupt Vector
in order to execute the interrupt handling routine, and hardware clears the corresponding interrupt
flag. Interrupt flags can also be cleared by writing a logic one to the flag bit position(s) to be
cleared. If an interrupt condition occurs while the corresponding interrupt enable bit is cleared,
the interrupt flag will be set and remembered until the interrupt is enabled, or the flag is cleared
by software. Similarly, if one or more interrupt conditions occur while the Global Interrupt Enable
bit is cleared, the corresponding interrupt flag(s) will be set and remembered until the Global
Interrupt Enable bit is set, and will then be executed by order of priority.
The second type of interrupts will trigger as long as the interrupt condition is present. These
interrupts do not necessarily have interrupt flags. If the interrupt condition disappears before the
interrupt is enabled, the interrupt will not be triggered.
When the AVR exits from an interrupt, it will always return to the main program and execute one
more instruction before any pending interrupt is served.
Note that the Status Register is not automatically stored when entering an interrupt routine, nor
restored when returning from an interrupt routine. This must be handled by software.
*/
// reset all error Bits at once, HTH
CANSTMOB &= (0xFF & ~(errorBits));
/*
• Bit 4 – BERR: Bit Error (Only in Transmission)
This flag can generate an interrupt. It must be cleared using a read-modify-write software routine
on the whole CANSTMOB register.
The bit value monitored is different from the bit value sent.
Exceptions: the monitored recessive bit sent as a dominant bit during the arbitration field and the
acknowledge slot detecting a dominant bit during the sending of an error frame.
The rising of this flag does not disable the MOb (the corresponding ENMOB-bit of CANEN registers
is not cleared). The next matching frame will update the BERR flag.
*/
return canCurrentMObStatus & errorBits;
}//END of canIsMObErrorAndAcknowledge
void canSetCanTimer( double value, uint8_t unit );
static inline void canPeriodicCanTimerCanBusStateReset(void)
{
/* reset every canBusStateResetInterval_seconds
* canBusStoredState to undefined
* to allow for recovery
*/
static double cumulatedIntervalTime = 0.;
if (canBusStateResetInterval_seconds < cumulatedIntervalTime)
{
canBusStoredState = canChannelMode_UNDEFINED;
cumulatedIntervalTime = 0.;
}
else
{
cumulatedIntervalTime += canTimerInterval;
}
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment