+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:
moonglow 2021-01-11 14:50:08 +03:00
parent 9b240ce2e4
commit b1a91185d6
4 changed files with 264 additions and 102 deletions

View File

@ -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 )
{

View File

@ -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* ));

View File

@ -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;
}
}

View File

@ -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
{