mirror of https://github.com/rusefi/pcan_pro_x.git
770 lines
18 KiB
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 |