mirror of https://github.com/rusefi/pcan_pro_x.git
+can driver add empty stubs for future porting to FDCAN hardware
+can driver add frame bit length calculator for bus load statistics *can driver reorganize CAN baudrate setup *pro protocol update for new CAN API *pro fd protocol update for new CAN API +pro fd protocol add bus load calculation +pro fd protocol add full FDCAN processing, ISO mode switching
This commit is contained in:
parent
9b240ce2e4
commit
b1a91185d6
|
@ -52,6 +52,17 @@ can_dev_array[CAN_BUS_TOTAL] =
|
|||
|
||||
#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 };
|
||||
|
@ -237,103 +248,71 @@ void pcan_can_install_err_callback( int bus, void (*cb)( int , uint32_t ) )
|
|||
}
|
||||
|
||||
/* all internal CANs on APB1 */
|
||||
int pcan_can_init( int bus )
|
||||
static int _get_precalculated_bitrate( uint32_t bitrate, uint32_t *brp, uint32_t *tseg1, uint32_t *tseg2, uint32_t *sjw )
|
||||
{
|
||||
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
|
||||
|
||||
HAL_CAN_DeInit( p_can );
|
||||
|
||||
p_can->Init.Mode = CAN_MODE_NORMAL;
|
||||
p_can->Init.SyncJumpWidth = CAN_SJW_1TQ;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
p_can->Init.Prescaler = 3;
|
||||
p_can->Init.TimeTriggeredMode = DISABLE;
|
||||
p_can->Init.AutoBusOff = ENABLE;
|
||||
p_can->Init.AutoWakeUp = DISABLE;
|
||||
p_can->Init.AutoRetransmission = ENABLE;
|
||||
p_can->Init.ReceiveFifoLocked = DISABLE;
|
||||
p_can->Init.TransmitFifoPriority = DISABLE;
|
||||
|
||||
if( HAL_CAN_Init( p_can ) != HAL_OK )
|
||||
{
|
||||
assert( 0 );
|
||||
}
|
||||
|
||||
pcan_can_set_filter_mask( bus, 0, 0, 0, 0 );
|
||||
pcan_can_set_bus_active( bus, 1 );
|
||||
|
||||
if( HAL_CAN_ActivateNotification( p_can, INTERNAL_CAN_IT_FLAGS ) != HAL_OK )
|
||||
{
|
||||
assert( 0 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _set_default_bitrate_settings( int bus, uint32_t bitrate )
|
||||
{
|
||||
CAN_HandleTypeDef *p_can = can_dev_array[bus].dev;
|
||||
*sjw = CAN_SJW_1TQ;
|
||||
|
||||
switch( bitrate )
|
||||
{
|
||||
case 1000000u:
|
||||
p_can->Init.Prescaler = 3;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_6TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_1TQ;
|
||||
*brp = 3;
|
||||
*tseg1 = CAN_BS1_6TQ;
|
||||
*tseg2 = CAN_BS2_1TQ;
|
||||
break;
|
||||
case 800000u:
|
||||
p_can->Init.Prescaler = 2;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_12TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*brp = 2;
|
||||
*tseg1 = CAN_BS1_12TQ;
|
||||
*tseg2 = CAN_BS2_2TQ;
|
||||
break;
|
||||
default:
|
||||
case 500000u:
|
||||
p_can->Init.Prescaler = 3;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*brp = 3;
|
||||
*tseg1 = CAN_BS1_13TQ;
|
||||
*tseg2 = CAN_BS2_2TQ;
|
||||
break;
|
||||
case 250000u:
|
||||
p_can->Init.Prescaler = 6;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*brp = 6;
|
||||
*tseg1 = CAN_BS1_13TQ;
|
||||
*tseg2 = CAN_BS2_2TQ;
|
||||
break;
|
||||
case 125000u:
|
||||
p_can->Init.Prescaler = 12;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*brp = 12;
|
||||
*tseg1 = CAN_BS1_13TQ;
|
||||
*tseg2 = CAN_BS2_2TQ;
|
||||
break;
|
||||
case 100000u:
|
||||
p_can->Init.Prescaler = 15;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*brp = 15;
|
||||
*tseg1 = CAN_BS1_13TQ;
|
||||
*tseg2 = CAN_BS2_2TQ;
|
||||
break;
|
||||
case 50000u:
|
||||
p_can->Init.Prescaler = 30;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*brp = 30;
|
||||
*tseg1 = CAN_BS1_13TQ;
|
||||
*tseg2 = CAN_BS2_2TQ;
|
||||
break;
|
||||
case 20000u:
|
||||
p_can->Init.Prescaler = 75;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*brp = 75;
|
||||
*tseg1 = CAN_BS1_13TQ;
|
||||
*tseg2 = CAN_BS2_2TQ;
|
||||
break;
|
||||
case 10000u:
|
||||
p_can->Init.Prescaler = 150;
|
||||
p_can->Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
p_can->Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
*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.SyncJumpWidth = CAN_SJW_1TQ;
|
||||
|
||||
|
||||
p_can->Init.TimeTriggeredMode = DISABLE;
|
||||
p_can->Init.AutoBusOff = ENABLE;
|
||||
p_can->Init.AutoWakeUp = ENABLE;
|
||||
|
@ -343,7 +322,12 @@ int pcan_can_init_ex( int bus, uint32_t bitrate )
|
|||
p_can->Init.TransmitFifoPriority = DISABLE;
|
||||
|
||||
/* APB1 bus ref clock = 24MHz, best sp is 87.5% */
|
||||
_set_default_bitrate_settings( bus, bitrate );
|
||||
_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 );
|
||||
|
@ -372,6 +356,13 @@ void pcan_can_set_silent( int bus, uint8_t silent_mode )
|
|||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
@ -397,14 +388,26 @@ void pcan_can_set_bus_active( int bus, uint16_t mode )
|
|||
}
|
||||
}
|
||||
|
||||
void pcan_can_set_bitrate( int bus, uint32_t bitrate )
|
||||
/* 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;
|
||||
|
||||
p_can->Init.SyncJumpWidth = CAN_SJW_1TQ;
|
||||
|
||||
/* APB1 bus ref clock = 24MHz, best sp is 87.5% */
|
||||
_set_default_bitrate_settings( bus, bitrate );
|
||||
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 )
|
||||
{
|
||||
|
|
|
@ -28,22 +28,35 @@ struct t_can_stats
|
|||
uint32_t rx_ovfs;
|
||||
};
|
||||
|
||||
struct t_can_bitrate
|
||||
{
|
||||
uint16_t brp;
|
||||
uint16_t tseg1;
|
||||
uint8_t tseg2;
|
||||
uint8_t sjw;
|
||||
};
|
||||
|
||||
#define MSG_FLAG_STD (0<<0)
|
||||
#define MSG_FLAG_EXT (1<<0)
|
||||
#define MSG_FLAG_RTR (1<<1)
|
||||
#define MSG_FLAG_ECHO (1<<3)
|
||||
/* FDCAN */
|
||||
#define MSG_FLAG_BRS (1<<4)
|
||||
#define MSG_FLAG_FD (1<<5)
|
||||
#define MSG_FLAG_ESI (1<<6)
|
||||
|
||||
#define CAN_INT_FILTER_MAX (14)
|
||||
#define CAN_EXT_FILTER_MAX (2)
|
||||
|
||||
void pcan_can_poll( void );
|
||||
uint32_t pcan_can_msg_time( const struct t_can_msg *pmsg, uint32_t nt, uint32_t dt );
|
||||
int pcan_can_stats( int bus, struct t_can_stats *p_stats );
|
||||
int pcan_can_init( int bus );
|
||||
int pcan_can_init_ex( int bus, uint32_t bitrate );
|
||||
void pcan_can_set_silent( int bus, uint8_t silent_mode );
|
||||
void pcan_can_set_iso_mode( int bus, uint8_t iso_mode );
|
||||
void pcan_can_set_loopback( int bus, uint8_t loopback );
|
||||
void pcan_can_set_bus_active( int bus, uint16_t mode );
|
||||
void pcan_can_set_bitrate( int bus, uint32_t bitrate );
|
||||
void pcan_can_set_bitrate( int bus, uint32_t bitrate, int is_data_bitrate );
|
||||
void pcan_can_set_bitrate_ex( int bus, uint16_t brp, uint8_t tseg1, uint8_t tseg2, uint8_t sjw );
|
||||
int pcan_can_write( int bus, struct t_can_msg *p_msg );
|
||||
void pcan_can_install_rx_callback( int bus, int (*rx_isr)( uint8_t, struct t_can_msg* ));
|
||||
|
|
|
@ -30,7 +30,9 @@ struct pcan_usbfd_fw_info
|
|||
static struct
|
||||
{
|
||||
uint32_t device_nr;
|
||||
uint32_t last_bus_load_update;
|
||||
uint32_t last_time_sync;
|
||||
uint32_t last_time_flush;
|
||||
uint8_t can_drv_loaded;
|
||||
uint8_t lin_drv_loaded;
|
||||
|
||||
|
@ -41,7 +43,8 @@ static struct
|
|||
uint8_t bus_active;
|
||||
uint8_t loopback;
|
||||
uint8_t err_mask;
|
||||
uint32_t channel_nr;
|
||||
uint32_t channel_nr;
|
||||
uint16_t opt_mask;
|
||||
|
||||
uint8_t led_is_busy;
|
||||
|
||||
|
@ -49,8 +52,16 @@ static struct
|
|||
struct ucan_timing_slow slow_br;
|
||||
/* can fd , data fast speed */
|
||||
struct ucan_timing_fast fast_br;
|
||||
|
||||
/* clock */
|
||||
uint32_t can_clock;
|
||||
|
||||
uint32_t nominal_qt;
|
||||
uint32_t data_qt;
|
||||
uint32_t tx_time_ns;
|
||||
uint32_t rx_time_ns;
|
||||
|
||||
uint32_t bus_load;
|
||||
}
|
||||
can[CAN_CHANNEL_MAX];
|
||||
}
|
||||
|
@ -70,7 +81,7 @@ pcan_device =
|
|||
},
|
||||
};
|
||||
|
||||
#define PCAN_USB_DATA_BUFFER_SIZE 1024
|
||||
#define PCAN_USB_DATA_BUFFER_SIZE 2048
|
||||
static uint8_t resp_buffer[2][PCAN_USB_DATA_BUFFER_SIZE];
|
||||
static uint8_t drv_load_packet[16];
|
||||
|
||||
|
@ -178,6 +189,7 @@ void pcan_ep0_receive( void )
|
|||
pcan_flush_ep( PCAN_USB_EP_MSGIN_CH1 );
|
||||
pcan_flush_ep( PCAN_USB_EP_CMDIN );
|
||||
pcan_device.can_drv_loaded = drv_load_packet[1];
|
||||
pcan_led_set_mode( LED_STAT, LED_MODE_ON, 0 );
|
||||
}
|
||||
else
|
||||
pcan_device.lin_drv_loaded = drv_load_packet[1];
|
||||
|
@ -185,16 +197,37 @@ void pcan_ep0_receive( void )
|
|||
|
||||
int pcan_protocol_rx_frame( uint8_t channel, struct t_can_msg *pmsg )
|
||||
{
|
||||
static const uint8_t pcan_fd_len2dlc[] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
|
||||
9, 9, 9, 9, /* 9 - 12 */
|
||||
10, 10, 10, 10, /* 13 - 16 */
|
||||
11, 11, 11, 11, /* 17 - 20 */
|
||||
12, 12, 12, 12, /* 21 - 24 */
|
||||
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15 /* 57 - 64 */
|
||||
};
|
||||
struct ucan_rx_msg *pcan_msg = pcan_data_alloc_buffer( UCAN_MSG_CAN_RX, sizeof(struct ucan_rx_msg) + pmsg->size );
|
||||
if( !pcan_msg )
|
||||
return -1;
|
||||
|
||||
if( !pcan_device.can[channel].led_is_busy && !(pmsg->flags & MSG_FLAG_ECHO) )
|
||||
if( !(pmsg->flags & MSG_FLAG_ECHO) )
|
||||
{
|
||||
pcan_led_set_mode( channel ? LED_CH1_RX:LED_CH0_RX, LED_MODE_BLINK_FAST, 237 );
|
||||
uint32_t nqt = pcan_device.can[channel].nominal_qt;
|
||||
uint32_t dqt = pcan_device.can[channel].data_qt;
|
||||
pcan_device.can[channel].rx_time_ns += pcan_can_msg_time( pmsg, nqt, dqt );
|
||||
if( !pcan_device.can[channel].led_is_busy )
|
||||
{
|
||||
pcan_led_set_mode( channel ? LED_CH1_RX:LED_CH0_RX, LED_MODE_BLINK_FAST, 237 );
|
||||
}
|
||||
}
|
||||
|
||||
pcan_msg->channel_dlc = UCAN_MSG_CHANNEL_DLC( channel, pmsg->size );
|
||||
if( pmsg->size > CAN_PAYLOAD_MAX_SIZE )
|
||||
pmsg->size = CAN_PAYLOAD_MAX_SIZE;
|
||||
pcan_msg->channel_dlc = UCAN_MSG_CHANNEL_DLC( channel, pcan_fd_len2dlc[pmsg->size] );
|
||||
pcan_msg->client = pmsg->dummy;
|
||||
pcan_msg->flags = 0;
|
||||
pcan_msg->tag_low = 0;
|
||||
|
@ -205,9 +238,18 @@ int pcan_protocol_rx_frame( uint8_t channel, struct t_can_msg *pmsg )
|
|||
pcan_msg->flags |= UCAN_MSG_RTR;
|
||||
if( pmsg->flags & MSG_FLAG_EXT )
|
||||
pcan_msg->flags |= UCAN_MSG_EXT_ID;
|
||||
if( pmsg->flags & MSG_FLAG_FD )
|
||||
{
|
||||
pcan_msg->flags |= UCAN_MSG_EXT_DATA_LEN;
|
||||
if( pmsg->flags & MSG_FLAG_BRS )
|
||||
pcan_msg->flags |= UCAN_MSG_BITRATE_SWITCH;
|
||||
if( pmsg->flags & MSG_FLAG_ESI )
|
||||
pcan_msg->flags |= UCAN_MSG_ERROR_STATE_IND;
|
||||
}
|
||||
if( pmsg->flags & MSG_FLAG_ECHO )
|
||||
{
|
||||
pcan_msg->flags |= UCAN_MSG_API_SRR | UCAN_MSG_HW_SRR;
|
||||
pcan_msg->ts_low = pcan_timestamp_us();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -230,11 +272,21 @@ int pcan_protocol_tx_frame_cb( uint8_t channel, struct t_can_msg *pmsg )
|
|||
{
|
||||
pcan_led_set_mode( channel ? LED_CH1_TX:LED_CH0_TX, LED_MODE_BLINK_FAST, 237 );
|
||||
}
|
||||
|
||||
uint32_t nqt = pcan_device.can[channel].nominal_qt;
|
||||
uint32_t dqt = pcan_device.can[channel].data_qt;
|
||||
pcan_device.can[channel].tx_time_ns += pcan_can_msg_time( pmsg, nqt, dqt );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcan_protocol_tx_frame( struct ucan_tx_msg *pmsg )
|
||||
{
|
||||
static const uint8_t pcan_fd_dlc2len[] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 12, 16, 20, 24, 32, 48, 64
|
||||
};
|
||||
|
||||
struct t_can_msg msg = { 0 };
|
||||
uint8_t channel;
|
||||
|
||||
|
@ -248,8 +300,13 @@ int pcan_protocol_tx_frame( struct ucan_tx_msg *pmsg )
|
|||
/* CAN-FD frame */
|
||||
if( pmsg->flags & UCAN_MSG_EXT_DATA_LEN )
|
||||
{
|
||||
/* TODO: .... */
|
||||
return -1;
|
||||
msg.flags |= MSG_FLAG_FD;
|
||||
if( pmsg->flags & UCAN_MSG_BITRATE_SWITCH )
|
||||
msg.flags |= MSG_FLAG_BRS;
|
||||
if( pmsg->flags & UCAN_MSG_ERROR_STATE_IND )
|
||||
msg.flags |= MSG_FLAG_ESI;
|
||||
|
||||
msg.size = pcan_fd_dlc2len[UCAN_MSG_DLC(pmsg)];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -293,30 +350,40 @@ static int pcan_protocol_send_status( uint8_t channel, uint8_t status )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pcan_protocol_set_baudrate( uint8_t channel, uint16_t brp, uint8_t tseg1, uint8_t tseg2, uint8_t sjw, uint8_t tsam )
|
||||
int pcan_protocol_set_baudrate( uint8_t channel, struct t_can_bitrate *pbitrate, struct t_can_bitrate *pdata_bitrate )
|
||||
{
|
||||
#define PCAN_STM32_SYSCLK_HZ (24000000u)
|
||||
|
||||
uint32_t bitrate, pcan_bitrate, pcan_brp;
|
||||
struct t_can_bitrate *pcur;
|
||||
|
||||
if( pbitrate )
|
||||
pcur = pbitrate;
|
||||
else if( pdata_bitrate )
|
||||
pcur = pdata_bitrate;
|
||||
else
|
||||
return -1;
|
||||
|
||||
pcan_brp = ((PCAN_STM32_SYSCLK_HZ/1000000u)*brp)/(pcan_device.can[channel].can_clock/1000000u);
|
||||
pcan_brp = ((PCAN_STM32_SYSCLK_HZ/1000000u)*pcur->brp)/(pcan_device.can[channel].can_clock/1000000u);
|
||||
pcan_bitrate = (((PCAN_STM32_SYSCLK_HZ)/pcan_brp)/(1/*tq*/ + pcur->tseg1 + pcur->tseg2 ));
|
||||
bitrate = (((pcan_device.can[channel].can_clock)/pcur->brp)/(1/*tq*/ + pcur->tseg1 + pcur->tseg2 ));
|
||||
|
||||
bitrate = (((pcan_device.can[channel].can_clock)/brp)/(1/*tq*/ + tseg1 + tseg2 ));
|
||||
pcan_bitrate = (((PCAN_STM32_SYSCLK_HZ)/pcan_brp)/(1/*tq*/ + tseg1 + tseg2 ));
|
||||
(void)pcan_bitrate;
|
||||
(void)pcan_brp;
|
||||
|
||||
if( bitrate != pcan_bitrate )
|
||||
pcan_can_set_bitrate( channel, bitrate, ( pcur == pdata_bitrate ) );
|
||||
|
||||
if( pcur == pdata_bitrate )
|
||||
{
|
||||
pcan_can_set_bitrate( channel, bitrate );
|
||||
pcan_device.can[channel].data_qt = 1000000000u/bitrate;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcan_can_set_bitrate_ex( channel, pcan_brp, tseg1, tseg2, sjw );
|
||||
pcan_device.can[channel].nominal_qt = 1000000000u/bitrate;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void pcan_protocol_process_cmd( uint8_t *ptr, uint16_t size )
|
||||
{
|
||||
struct ucan_command *pcmd = (void*)ptr;
|
||||
|
@ -333,6 +400,10 @@ static void pcan_protocol_process_cmd( uint8_t *ptr, uint16_t size )
|
|||
{
|
||||
pcan_can_set_bus_active( UCAN_CMD_CHANNEL(pcmd) , 0 );
|
||||
pcan_device.can[UCAN_CMD_CHANNEL(pcmd)].bus_active = 0;
|
||||
|
||||
/* update ISO mode only on inactive bus */
|
||||
uint8_t bus_iso_mode = ( pcan_device.can[UCAN_CMD_CHANNEL(pcmd)].opt_mask & UCAN_OPTION_ISO_MODE ) != 0;
|
||||
pcan_can_set_iso_mode( UCAN_CMD_CHANNEL(pcmd), bus_iso_mode );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -366,22 +437,33 @@ static void pcan_protocol_process_cmd( uint8_t *ptr, uint16_t size )
|
|||
case UCAN_CMD_TIMING_SLOW:
|
||||
if( UCAN_CMD_CHANNEL(pcmd) < CAN_CHANNEL_MAX )
|
||||
{
|
||||
struct t_can_bitrate br;
|
||||
struct ucan_timing_slow *ptiming = (void*)pcmd;
|
||||
pcan_device.can[UCAN_CMD_CHANNEL(pcmd)].slow_br = *ptiming;
|
||||
pcan_protocol_set_baudrate( UCAN_CMD_CHANNEL(pcmd),
|
||||
ptiming->brp + 1,
|
||||
ptiming->tseg1 + 1,
|
||||
ptiming->tseg2 + 1,
|
||||
(ptiming->sjw_t & 0x0f)+1,
|
||||
(ptiming->sjw_t&0x80) != 0 );
|
||||
|
||||
br.brp = ptiming->brp + 1;
|
||||
br.tseg1 = ptiming->tseg1 + 1;
|
||||
br.tseg2 = ptiming->tseg2 + 1;
|
||||
br.sjw = (ptiming->sjw_t & 0x0f)+1;
|
||||
(void)((ptiming->sjw_t&0x80) != 0);
|
||||
|
||||
pcan_protocol_set_baudrate( UCAN_CMD_CHANNEL(pcmd), &br, 0 );
|
||||
}
|
||||
break;
|
||||
/* only for CAN-FD */
|
||||
case UCAN_CMD_TIMING_FAST:
|
||||
if( UCAN_CMD_CHANNEL(pcmd) < CAN_CHANNEL_MAX )
|
||||
{
|
||||
struct t_can_bitrate br;
|
||||
struct ucan_timing_fast *ptiming = (void*)pcmd;
|
||||
pcan_device.can[UCAN_CMD_CHANNEL(pcmd)].fast_br = *ptiming;
|
||||
|
||||
br.brp = ptiming->brp + 1;
|
||||
br.tseg1 = ptiming->tseg1 + 1;
|
||||
br.tseg2 = ptiming->tseg2 + 1;
|
||||
br.sjw = (ptiming->sjw & 0x0f)+1;
|
||||
|
||||
pcan_protocol_set_baudrate( UCAN_CMD_CHANNEL(pcmd), 0, &br );
|
||||
}
|
||||
break;
|
||||
case UCAN_CMD_SET_STD_FILTER:
|
||||
|
@ -401,8 +483,18 @@ static void pcan_protocol_process_cmd( uint8_t *ptr, uint16_t size )
|
|||
case UCAN_CMD_WR_ERR_CNT:
|
||||
break;
|
||||
case UCAN_CMD_SET_EN_OPTION:
|
||||
if( UCAN_CMD_CHANNEL(pcmd) < CAN_CHANNEL_MAX )
|
||||
{
|
||||
struct ucan_option *popt = (void*)pcmd;
|
||||
pcan_device.can[UCAN_CMD_CHANNEL(pcmd)].opt_mask |= popt->mask;
|
||||
}
|
||||
break;
|
||||
case UCAN_CMD_CLR_DIS_OPTION:
|
||||
if( UCAN_CMD_CHANNEL(pcmd) < CAN_CHANNEL_MAX )
|
||||
{
|
||||
struct ucan_option *popt = (void*)pcmd;
|
||||
pcan_device.can[UCAN_CMD_CHANNEL(pcmd)].opt_mask &= ~popt->mask;
|
||||
}
|
||||
break;
|
||||
case UCAN_CMD_SET_ERR_GEN1:
|
||||
break;
|
||||
|
@ -457,10 +549,13 @@ static void pcan_protocol_process_cmd( uint8_t *ptr, uint16_t size )
|
|||
{
|
||||
pcan_device.can[UCAN_CMD_CHANNEL(pcmd)].channel_nr = pdevid->device_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x87: /* CAN FD ISO MODE, 0xff - enable, 0x55 - disable */
|
||||
{
|
||||
/* do nothing here */
|
||||
break;
|
||||
case 0x87: /* CAN FD ISO MODE */
|
||||
break;
|
||||
}
|
||||
case UCAN_CMD_END_OF_COLLECTION:
|
||||
return;
|
||||
default:
|
||||
|
@ -523,6 +618,9 @@ void pcan_protocol_init( void )
|
|||
pcan_can_init_ex( CAN_BUS_2, 500000 );
|
||||
pcan_can_set_filter_mask( CAN_BUS_2, 0, 0, 0, 0 );
|
||||
|
||||
pcan_can_set_iso_mode( CAN_BUS_1, 0 );
|
||||
pcan_can_set_iso_mode( CAN_BUS_2, 0 );
|
||||
|
||||
pcan_can_install_rx_callback( CAN_BUS_1, pcan_protocol_rx_frame );
|
||||
pcan_can_install_rx_callback( CAN_BUS_2, pcan_protocol_rx_frame );
|
||||
|
||||
|
@ -533,6 +631,7 @@ void pcan_protocol_init( void )
|
|||
void pcan_protocol_poll( void )
|
||||
{
|
||||
uint32_t ts_ms = pcan_timestamp_millis();
|
||||
uint32_t ts_us = pcan_timestamp_us();
|
||||
|
||||
pcan_can_poll();
|
||||
|
||||
|
@ -545,16 +644,47 @@ void pcan_protocol_poll( void )
|
|||
/* align to 64 */
|
||||
flush_size += (64-1);
|
||||
flush_size &= ~(64-1);
|
||||
int res = pcan_flush_data( &resp_fsm[1], data_buffer, flush_size);
|
||||
int res = pcan_flush_data( &resp_fsm[1], data_buffer, flush_size );
|
||||
if( res )
|
||||
{
|
||||
data_pos = 0;
|
||||
pcan_device.last_time_flush = ts_us;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
ts_us -= pcan_device.last_time_flush;
|
||||
if( pcan_device.last_time_flush && ( ts_us > 800 ) )
|
||||
{
|
||||
int res = pcan_flush_data( &resp_fsm[1], 0, 0 );
|
||||
if( res )
|
||||
{
|
||||
pcan_device.last_time_flush = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* timesync part */
|
||||
if( !pcan_device.can_drv_loaded )
|
||||
return;
|
||||
|
||||
/* update bus load each 250ms */
|
||||
if( ( ts_ms - pcan_device.last_bus_load_update ) >= 250u )
|
||||
{
|
||||
pcan_device.last_bus_load_update = ts_ms;
|
||||
for( int i = 0; i < CAN_CHANNEL_MAX; i++ )
|
||||
{
|
||||
uint32_t total_ns = pcan_device.can[i].tx_time_ns + pcan_device.can[i].rx_time_ns;
|
||||
/* get bus in percents 0 - 100% */
|
||||
pcan_device.can[i].bus_load = total_ns / (250000000u/100u);
|
||||
|
||||
pcan_device.can[i].tx_time_ns = 0;
|
||||
pcan_device.can[i].rx_time_ns = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( ts_ms - pcan_device.last_time_sync ) < 1000u )
|
||||
return;
|
||||
struct ucan_usb_ts_msg *pts = pcan_data_alloc_buffer( UCAN_USB_MSG_CALIBRATION, sizeof( struct ucan_usb_ts_msg ) );
|
||||
|
@ -564,4 +694,20 @@ void pcan_protocol_poll( void )
|
|||
pts->usb_frame_index = pcan_usb_frame_number();
|
||||
pts->unused = 0;
|
||||
pcan_device.last_time_sync = ts_ms;
|
||||
|
||||
for( int i = 0; i < CAN_CHANNEL_MAX; i++ )
|
||||
{
|
||||
if( !(pcan_device.can[i].opt_mask & UCAN_OPTION_BUSLOAD) )
|
||||
continue;
|
||||
if( !pcan_device.can[i].bus_active )
|
||||
continue;
|
||||
struct ucan_bus_load_msg *pbs = pcan_data_alloc_buffer( UCAN_MSG_BUSLOAD, sizeof( struct ucan_bus_load_msg ) );
|
||||
if( !pbs )
|
||||
return;
|
||||
|
||||
pbs->channel = i;
|
||||
/* 0 ... 100% => 0 ... 4095 */
|
||||
pbs->bus_load = (pcan_device.can[i].bus_load*4095u)/100u;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -662,7 +662,7 @@ int pcan_protocol_set_baudrate( uint8_t channel, uint32_t ccbt )
|
|||
|
||||
if( bitrate != pcan_bitrate )
|
||||
{
|
||||
pcan_can_set_bitrate( channel, bitrate );
|
||||
pcan_can_set_bitrate( channel, bitrate, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue