pcan_pro_x/Src/pcanpro_can.c

770 lines
18 KiB
C

#include <assert.h>
#include "io_macro.h"
#include "pcanpro_timestamp.h"
#include "pcanpro_can.h"
#define CAN1_RX B, 8, MODE_AF_PP, NOPULL, SPEED_FREQ_VERY_HIGH, AF9_CAN1
#define CAN1_TX B, 9, MODE_AF_PP, NOPULL, SPEED_FREQ_VERY_HIGH, AF9_CAN1
#define CAN2_RX B, 5, MODE_AF_PP, NOPULL, SPEED_FREQ_VERY_HIGH, AF9_CAN2
#define CAN2_TX B, 6, MODE_AF_PP, NOPULL, SPEED_FREQ_VERY_HIGH, AF9_CAN2
static CAN_HandleTypeDef hcan[CAN_BUS_TOTAL] =
{
[CAN_BUS_1].Instance = CAN1,
[CAN_BUS_2].Instance = CAN2
};
#define CAN_TX_FIFO_SIZE (256)
static struct t_can_dev
{
void *dev;
uint32_t tx_msgs;
uint32_t tx_errs;
uint32_t tx_ovfs;
uint32_t rx_msgs;
uint32_t rx_errs;
uint32_t rx_ovfs;
struct t_can_msg tx_fifo[CAN_TX_FIFO_SIZE];
uint32_t tx_head;
uint32_t tx_tail;
uint32_t esr_reg;
int (*rx_isr)( uint8_t, struct t_can_msg* );
int (*tx_isr)( uint8_t, struct t_can_msg* );
void (*err_handler)( int bus, uint32_t esr );
}
can_dev_array[CAN_BUS_TOTAL] =
{
[CAN_BUS_1] = { .dev = &hcan[CAN_BUS_1] },
[CAN_BUS_2] = { .dev = &hcan[CAN_BUS_2] },
};
#define INTERNAL_CAN_IT_FLAGS ( CAN_IT_TX_MAILBOX_EMPTY |\
CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING |\
CAN_IT_ERROR_WARNING |\
CAN_IT_ERROR_PASSIVE |\
CAN_IT_LAST_ERROR_CODE |\
CAN_IT_ERROR )
#define CAN2_FILTER_START (14u)
#define CAN_WITHOUT_ISR 1
uint32_t pcan_can_msg_time( const struct t_can_msg *pmsg, uint32_t nt, uint32_t dt )
{
const uint32_t data_bits = pmsg->size<<3;
const uint32_t control_bits = ( pmsg->flags & MSG_FLAG_EXT ) ? 67:47;
if( pmsg->flags & MSG_FLAG_BRS )
return (control_bits*nt) + (data_bits*dt);
else
return (control_bits+data_bits)*nt;
}
int pcan_can_set_filter_mask( int bus, int num, int format, uint32_t id, uint32_t mask )
{
CAN_FilterTypeDef filter = { 0 };
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
if( num >= CAN_INT_FILTER_MAX )
return -1;
/* CAN1 & CAN2 filter shared 28 filters, we use 14 for each one */
if( p_can->Instance == CAN2 )
{
num += CAN2_FILTER_START;
}
filter.FilterMode = CAN_FILTERMODE_IDMASK;
filter.FilterScale = CAN_FILTERSCALE_32BIT;
if( format == MSG_FLAG_EXT )
{
id &= 0x1FFFFFFF;
/* EXTID[28:13] */
filter.FilterIdHigh = id >> 13;
/* EXTID[12:0] + IDE */
filter.FilterIdLow = ((id << 3)&0xFFFF) | CAN_ID_EXT;
filter.FilterMaskIdHigh = mask >> 13;
filter.FilterMaskIdLow = ((mask << 3)&0xFFFF) | CAN_ID_EXT;
}
else
{
id &= 0x7FF;
filter.FilterIdHigh = id << 5;
filter.FilterIdLow = 0x0;
filter.FilterMaskIdHigh = mask << 5;
filter.FilterMaskIdLow = 0x0;
}
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
filter.FilterActivation = ENABLE;
filter.FilterBank = num;
filter.SlaveStartFilterBank = CAN2_FILTER_START;
if( HAL_CAN_ConfigFilter( p_can, &filter ) != HAL_OK )
return -1;
return 0;
}
int pcan_can_filter_init_stdid_list( int bus, const uint16_t *id_list, int id_len )
{
CAN_FilterTypeDef filter = { 0 };
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
int i, offset;
offset = ( p_can->Instance == CAN2 ) ? CAN2_FILTER_START: 0;
/* STDID[10:3] | STDID[2:0] RTR IDE EXID[17:15] */
/* IDE = 0, RTR = 0, EXID[17:15] = { 0 } */
filter.FilterMode = CAN_FILTERMODE_IDLIST;
filter.FilterScale = CAN_FILTERSCALE_16BIT;
i = 0;
while( i < id_len )
{
filter.FilterBank = ((i)>>2)+offset;
filter.SlaveStartFilterBank = CAN2_FILTER_START;
filter.FilterMaskIdLow = 0;
filter.FilterMaskIdHigh = 0;
filter.FilterIdLow = 0;
filter.FilterIdHigh = 0;
switch( (id_len-i) )
{
/* fallthrough */
default:
filter.FilterMaskIdLow = id_list[i++]<<5;
case 3:
filter.FilterMaskIdHigh = id_list[i++]<<5;
case 2:
filter.FilterIdLow = id_list[i++]<<5;
case 1:
filter.FilterIdHigh = id_list[i++]<<5;
}
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
filter.FilterActivation = ENABLE;
if( HAL_CAN_ConfigFilter( p_can, &filter ) != HAL_OK )
return -1;
}
return id_len;
}
static int _can_send( CAN_HandleTypeDef *p_can, struct t_can_msg *p_msg )
{
CAN_TxHeaderTypeDef msg = { .TransmitGlobalTime = DISABLE };
uint32_t txMailbox = 0;
if( HAL_CAN_IsTxMessagePending( p_can, CAN_TX_MAILBOX0 ) )
return -1;
if( p_msg->flags & MSG_FLAG_EXT )
{
msg.ExtId = p_msg->id & 0x1FFFFFFF;
msg.IDE = CAN_ID_EXT;
}
else
{
msg.StdId = p_msg->id & 0x7FF;
msg.IDE = CAN_ID_STD;
}
msg.DLC = p_msg->size;
msg.RTR = (p_msg->flags & MSG_FLAG_RTR)?CAN_RTR_REMOTE:CAN_RTR_DATA;
if( HAL_CAN_AddTxMessage( p_can, &msg, (void*)p_msg->data, &txMailbox ) != HAL_OK )
return -1;
return txMailbox;
}
static void pcan_can_flush_tx( int bus )
{
struct t_can_dev *p_dev = &can_dev_array[bus];
struct t_can_msg *p_msg;
/* empty fifo */
if( p_dev->tx_head == p_dev->tx_tail )
return;
p_msg = &p_dev->tx_fifo[p_dev->tx_tail];
if( _can_send( p_dev->dev, p_msg ) < 0 )
return;
if( p_dev->tx_isr )
{
(void)p_dev->tx_isr( bus, p_msg );
}
/* update fifo index */
p_dev->tx_tail = (p_dev->tx_tail+1)&(CAN_TX_FIFO_SIZE-1);
}
int pcan_can_write( int bus, struct t_can_msg *p_msg )
{
struct t_can_dev *p_dev = &can_dev_array[bus];
if( !p_msg )
return 0;
uint32_t tx_head_next = (p_dev->tx_head+1)&(CAN_TX_FIFO_SIZE-1);
/* overflow ? just skip it */
if( tx_head_next == p_dev->tx_tail )
{
++p_dev->tx_ovfs;
return -1;
}
p_dev->tx_fifo[p_dev->tx_head] = *p_msg;
p_dev->tx_head = tx_head_next;
return 0;
}
void pcan_can_install_rx_callback( int bus, int (*cb)( uint8_t, struct t_can_msg* ) )
{
struct t_can_dev *p_dev = &can_dev_array[bus];
p_dev->rx_isr = cb;
}
void pcan_can_install_tx_callback( int bus, int (*cb)( uint8_t, struct t_can_msg* ) )
{
struct t_can_dev *p_dev = &can_dev_array[bus];
p_dev->tx_isr = cb;
}
void pcan_can_install_err_callback( int bus, void (*cb)( int , uint32_t ) )
{
struct t_can_dev *p_dev = &can_dev_array[bus];
p_dev->err_handler = cb;
}
/* all internal CANs on APB1 */
static int _get_precalculated_bitrate( uint32_t bitrate, uint32_t *brp, uint32_t *tseg1, uint32_t *tseg2, uint32_t *sjw )
{
*sjw = CAN_SJW_1TQ;
switch( bitrate )
{
case 1000000u:
*brp = 3;
*tseg1 = CAN_BS1_6TQ;
*tseg2 = CAN_BS2_1TQ;
break;
case 800000u:
*brp = 2;
*tseg1 = CAN_BS1_12TQ;
*tseg2 = CAN_BS2_2TQ;
break;
default:
case 500000u:
*brp = 3;
*tseg1 = CAN_BS1_13TQ;
*tseg2 = CAN_BS2_2TQ;
break;
case 250000u:
*brp = 6;
*tseg1 = CAN_BS1_13TQ;
*tseg2 = CAN_BS2_2TQ;
break;
case 125000u:
*brp = 12;
*tseg1 = CAN_BS1_13TQ;
*tseg2 = CAN_BS2_2TQ;
break;
case 100000u:
*brp = 15;
*tseg1 = CAN_BS1_13TQ;
*tseg2 = CAN_BS2_2TQ;
break;
case 50000u:
*brp = 30;
*tseg1 = CAN_BS1_13TQ;
*tseg2 = CAN_BS2_2TQ;
break;
case 20000u:
*brp = 75;
*tseg1 = CAN_BS1_13TQ;
*tseg2 = CAN_BS2_2TQ;
break;
case 10000u:
*brp = 150;
*tseg1 = CAN_BS1_13TQ;
*tseg2 = CAN_BS2_2TQ;
break;
}
return 0;
}
int pcan_can_init_ex( int bus, uint32_t bitrate )
{
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
uint32_t brp;
uint32_t tseg1, tseg2, sjw;
p_can->Init.Mode = CAN_MODE_NORMAL;//CAN_MODE_NORMAL;// CAN_MODE_LOOPBACK;
p_can->Init.TimeTriggeredMode = DISABLE;
p_can->Init.AutoBusOff = ENABLE;
p_can->Init.AutoWakeUp = ENABLE;
p_can->Init.AutoRetransmission = DISABLE;
p_can->Init.ReceiveFifoLocked = DISABLE;
p_can->Init.TransmitFifoPriority = ENABLE;
/* APB1 bus ref clock = 24MHz, best sp is 87.5% */
_get_precalculated_bitrate( bitrate, &brp, &tseg1, &tseg2, &sjw );
p_can->Init.SyncJumpWidth = sjw;
p_can->Init.Prescaler = brp;
p_can->Init.TimeSeg1 = tseg1;
p_can->Init.TimeSeg2 = tseg2;
//(void)HAL_CAN_AbortTxRequest( p_can, CAN_TX_MAILBOX0 | CAN_TX_MAILBOX1 | CAN_TX_MAILBOX2 );
//(void)HAL_CAN_Stop( p_can );
//(void)HAL_CAN_DeInit( p_can );
if( HAL_CAN_Init( p_can ) != HAL_OK )
return -1;
if( HAL_CAN_ActivateNotification( p_can, INTERNAL_CAN_IT_FLAGS ) != HAL_OK )
return -1;
if( HAL_CAN_Start( p_can ) != HAL_OK )
return -1;
return 0;
}
void pcan_can_set_silent( int bus, uint8_t silent_mode )
{
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
p_can->Init.Mode = silent_mode ? CAN_MODE_SILENT: CAN_MODE_NORMAL;
if( HAL_CAN_Init( p_can ) != HAL_OK )
{
assert( 0 );
}
}
/* bxCAN does not support FDCAN ISO mode switch */
void pcan_can_set_iso_mode( int bus, uint8_t iso_mode )
{
(void)bus;
(void)iso_mode;
}
void pcan_can_set_loopback( int bus, uint8_t loopback )
{
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
p_can->Init.Mode = loopback ? CAN_MODE_LOOPBACK: CAN_MODE_NORMAL;
if( HAL_CAN_Init( p_can ) != HAL_OK )
{
assert( 0 );
}
}
void pcan_can_set_bus_active( int bus, uint16_t mode )
{
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
if( mode )
{
HAL_CAN_Start( p_can );
HAL_CAN_AbortTxRequest( p_can, CAN_TX_MAILBOX0 | CAN_TX_MAILBOX1 | CAN_TX_MAILBOX2 );
}
else
{
HAL_CAN_AbortTxRequest( p_can, CAN_TX_MAILBOX0 | CAN_TX_MAILBOX1 | CAN_TX_MAILBOX2 );
HAL_CAN_Stop( p_can );
}
}
/* set predefined best values */
void pcan_can_set_bitrate( int bus, uint32_t bitrate, int is_data_bitrate )
{
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
uint32_t brp;
uint32_t tseg1, tseg2, sjw;
_get_precalculated_bitrate( bitrate, &brp, &tseg1, &tseg2, &sjw );
if( is_data_bitrate )
{
return;
}
else
{
p_can->Init.Prescaler = brp;
p_can->Init.SyncJumpWidth = sjw;
p_can->Init.TimeSeg1 = tseg1;
p_can->Init.TimeSeg2 = tseg2;
}
if( HAL_CAN_Init( p_can ) != HAL_OK )
{
assert( 0 );
}
}
void pcan_can_set_bitrate_ex( int bus, uint16_t brp, uint8_t tseg1, uint8_t tseg2, uint8_t sjw )
{
static const uint32_t sjw_table[] =
{
CAN_SJW_1TQ, CAN_SJW_2TQ, CAN_SJW_3TQ, CAN_SJW_4TQ
};
static const uint32_t tseg1_table[] =
{
CAN_BS1_1TQ, CAN_BS1_2TQ, CAN_BS1_3TQ, CAN_BS1_4TQ,
CAN_BS1_5TQ, CAN_BS1_6TQ, CAN_BS1_7TQ, CAN_BS1_8TQ,
CAN_BS1_9TQ, CAN_BS1_10TQ, CAN_BS1_11TQ, CAN_BS1_12TQ,
CAN_BS1_13TQ, CAN_BS1_14TQ, CAN_BS1_15TQ, CAN_BS1_16TQ
};
static const uint32_t tseg2_table[] =
{
CAN_BS2_1TQ, CAN_BS2_2TQ, CAN_BS2_3TQ, CAN_BS2_4TQ,
CAN_BS2_5TQ, CAN_BS2_6TQ, CAN_BS2_7TQ, CAN_BS2_8TQ
};
if( sjw > 4 )
sjw = 4;
if( tseg1 > 16 )
tseg1 = 16;
if( tseg2 > 8 )
tseg2 = 8;
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
p_can->Init.Prescaler = brp;
p_can->Init.SyncJumpWidth = sjw_table[sjw - 1];
p_can->Init.TimeSeg1 = tseg1_table[tseg1 - 1];
p_can->Init.TimeSeg2 = tseg2_table[tseg2 - 1];
if( HAL_CAN_Init( p_can ) != HAL_OK )
{
assert( 0 );
}
}
static void pcan_can_tx_complete( int bus, int mail_box )
{
++can_dev_array[bus].tx_msgs;
}
static void pcan_can_tx_err( int bus, int mail_box )
{
++can_dev_array[bus].tx_errs;
}
int pcan_can_stats( int bus, struct t_can_stats *p_stats )
{
struct t_can_dev *p_dev = &can_dev_array[bus];
p_stats->tx_msgs = p_dev->tx_msgs;
p_stats->tx_errs = p_dev->tx_errs;
p_stats->rx_msgs = p_dev->rx_msgs;
p_stats->rx_errs = p_dev->rx_errs;
p_stats->rx_ovfs = p_dev->rx_ovfs;
return sizeof( struct t_can_stats );
}
void pcan_can_poll( void )
{
static uint32_t err_last_check = 0;
uint32_t ts_ms;
ts_ms = pcan_timestamp_millis();
#if ( CAN_WITHOUT_ISR == 1 )
HAL_CAN_IRQHandler( &hcan[CAN_BUS_1] );
HAL_CAN_IRQHandler( &hcan[CAN_BUS_2] );
#endif
pcan_can_flush_tx( CAN_BUS_1 );
pcan_can_flush_tx( CAN_BUS_2 );
if( (uint32_t)( err_last_check - ts_ms ) > 250 )
{
err_last_check = ts_ms;
for( int i = 0; i < CAN_BUS_TOTAL; i++ )
{
if( !can_dev_array[i].err_handler )
continue;
CAN_HandleTypeDef *pcan = can_dev_array[i].dev;
if( can_dev_array[i].esr_reg != pcan->Instance->ESR )
{
can_dev_array[i].esr_reg = pcan->Instance->ESR;
can_dev_array[i].err_handler( i, can_dev_array[i].esr_reg );
}
}
}
}
/* --------------- HAL PART ------------- */
static int _bus_from_int_dev( CAN_TypeDef *can )
{
if( can == CAN1 )
return CAN_BUS_1;
else if( can == CAN2 )
return CAN_BUS_2;
/* abnormal! */
return CAN_BUS_1;
}
static void pcan_can_isr_frame( CAN_HandleTypeDef *hcan, uint32_t fifo )
{
CAN_RxHeaderTypeDef hdr;
const int bus = _bus_from_int_dev( hcan->Instance );
struct t_can_dev * const p_dev = &can_dev_array[bus];
struct t_can_msg msg = { 0 };
if( HAL_CAN_GetRxMessage( hcan, fifo, &hdr, msg.data ) != HAL_OK )
return;
/* oversize frame ? */
if( hdr.DLC > CAN_PAYLOAD_MAX_SIZE )
return;
if( hdr.IDE == CAN_ID_STD )
{
msg.id = hdr.StdId;
}
else
{
msg.id = hdr.ExtId;
msg.flags |= MSG_FLAG_EXT;
}
if( hdr.RTR != CAN_RTR_DATA )
{
msg.flags |= MSG_FLAG_RTR;
}
msg.size = hdr.DLC;
msg.timestamp = pcan_timestamp_us();
if( p_dev->rx_isr )
{
if( p_dev->rx_isr( bus, &msg ) < 0 )
{
++p_dev->rx_ovfs;
return;
}
}
++p_dev->rx_msgs;
}
/* WARN: CAN1 & CAN2 use filter registers of CAN1 */
void HAL_CAN_MspInit( CAN_HandleTypeDef *hcan )
{
if( hcan->Instance == CAN1 )
{
if( !__HAL_RCC_CAN1_IS_CLK_ENABLED() )
{
__HAL_RCC_CAN1_CLK_ENABLE();
}
PORT_ENABLE_CLOCK( PIN_PORT( CAN1_RX ), PIN_PORT( CAN1_TX ) );
PIN_INIT( CAN1_RX );
PIN_INIT( CAN1_TX );
#if ( CAN_WITHOUT_ISR == 0 )
HAL_NVIC_SetPriority( CAN1_TX_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN1_TX_IRQn );
HAL_NVIC_SetPriority( CAN1_RX0_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN1_RX0_IRQn );
HAL_NVIC_SetPriority( CAN1_RX1_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN1_RX1_IRQn );
HAL_NVIC_SetPriority( CAN1_SCE_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN1_SCE_IRQn );
#endif
}
else if( hcan->Instance == CAN2 )
{
if( !__HAL_RCC_CAN1_IS_CLK_ENABLED() )
{
__HAL_RCC_CAN1_CLK_ENABLE();
}
if( !__HAL_RCC_CAN2_IS_CLK_ENABLED() )
{
__HAL_RCC_CAN2_CLK_ENABLE();
}
PORT_ENABLE_CLOCK( PIN_PORT( CAN2_RX ), PIN_PORT( CAN2_TX ) );
PIN_INIT( CAN2_RX );
PIN_INIT( CAN2_TX );
#if ( CAN_WITHOUT_ISR == 0 )
HAL_NVIC_SetPriority( CAN2_TX_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN2_TX_IRQn );
HAL_NVIC_SetPriority( CAN2_RX0_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN2_RX0_IRQn );
HAL_NVIC_SetPriority( CAN2_RX1_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN2_RX1_IRQn );
HAL_NVIC_SetPriority( CAN2_SCE_IRQn, 6, 0 );
HAL_NVIC_EnableIRQ( CAN2_SCE_IRQn );
#endif
}
}
void HAL_CAN_MspDeInit( CAN_HandleTypeDef *hcan )
{
if( hcan->Instance == CAN1 )
{
/* if CAN2 not used anymore */
if( !__HAL_RCC_CAN2_IS_CLK_ENABLED() )
{
__HAL_RCC_CAN1_CLK_DISABLE();
}
PIN_DEINIT( CAN1_RX );
PIN_DEINIT( CAN1_TX );
HAL_NVIC_DisableIRQ( CAN1_TX_IRQn );
HAL_NVIC_DisableIRQ( CAN1_RX0_IRQn );
HAL_NVIC_DisableIRQ( CAN1_RX1_IRQn );
HAL_NVIC_DisableIRQ( CAN1_SCE_IRQn );
}
else if( hcan->Instance == CAN2 )
{
__HAL_RCC_CAN2_CLK_DISABLE();
PIN_DEINIT( CAN2_RX );
PIN_DEINIT( CAN2_TX );
HAL_NVIC_DisableIRQ( CAN2_TX_IRQn );
HAL_NVIC_DisableIRQ( CAN2_RX0_IRQn );
HAL_NVIC_DisableIRQ( CAN2_RX1_IRQn );
HAL_NVIC_DisableIRQ( CAN2_SCE_IRQn );
}
}
/* CAN HAL subsystem callbacks */
void HAL_CAN_TxMailbox0CompleteCallback( CAN_HandleTypeDef *hcan )
{
pcan_can_tx_complete( _bus_from_int_dev( hcan->Instance ), 0 );
}
void HAL_CAN_TxMailbox1CompleteCallback( CAN_HandleTypeDef *hcan )
{
pcan_can_tx_complete( _bus_from_int_dev( hcan->Instance ), 1 );
}
void HAL_CAN_TxMailbox2CompleteCallback( CAN_HandleTypeDef *hcan )
{
pcan_can_tx_complete( _bus_from_int_dev( hcan->Instance ), 2 );
}
void HAL_CAN_TxMailbox0AbortCallback( CAN_HandleTypeDef *hcan ){}
void HAL_CAN_TxMailbox1AbortCallback( CAN_HandleTypeDef *hcan ){}
void HAL_CAN_TxMailbox2AbortCallback( CAN_HandleTypeDef *hcan ){}
void HAL_CAN_RxFifo0MsgPendingCallback( CAN_HandleTypeDef *hcan )
{
pcan_can_isr_frame( hcan, CAN_RX_FIFO0 );
}
void HAL_CAN_RxFifo1MsgPendingCallback( CAN_HandleTypeDef *hcan )
{
pcan_can_isr_frame( hcan, CAN_RX_FIFO1 );
}
void HAL_CAN_RxFifo0FullCallback( CAN_HandleTypeDef *hcan )
{
}
void HAL_CAN_RxFifo1FullCallback( CAN_HandleTypeDef *hcan )
{
}
void HAL_CAN_SleepCallback( CAN_HandleTypeDef *hcan ){}
void HAL_CAN_WakeUpFromRxMsgCallback( CAN_HandleTypeDef *hcan ){}
void HAL_CAN_ErrorCallback( CAN_HandleTypeDef *hcan )
{
/* handle errors */
uint32_t err = HAL_CAN_GetError( hcan );
int bus = _bus_from_int_dev( hcan->Instance );
if ( err & HAL_CAN_ERROR_TX_TERR0 )
{
pcan_can_tx_err( bus, 0 );
}
if ( err & HAL_CAN_ERROR_TX_TERR1 )
{
pcan_can_tx_err( bus, 1 );
}
if ( err & HAL_CAN_ERROR_TX_TERR2 )
{
pcan_can_tx_err( bus, 2 );
}
HAL_CAN_ResetError( hcan );
}
/* ISR handlers */
#if ( CAN_WITHOUT_ISR == 0 )
/* CAN1 */
void CAN1_TX_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_1] );
}
void CAN1_RX0_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_1] );
}
void CAN1_RX1_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_1] );
}
void CAN1_SCE_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_1] );
}
/* CAN2 */
void CAN2_TX_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_2] );
}
void CAN2_RX0_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_2] );
}
void CAN2_RX1_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_2] );
}
void CAN2_SCE_IRQHandler( void )
{
HAL_CAN_IRQHandler( &hcan[CAN_BUS_2] );
}
#endif