4242#if MICROPY_HW_ENABLE_FDCAN
4343
4444#define CAN_MAX_FILTER (64)
45+ #define CAN_MAX_DATA_FRAME (64)
4546
4647#define CAN_FIFO0 FDCAN_RX_FIFO0
4748#define CAN_FIFO1 FDCAN_RX_FIFO1
8990
9091// Both banks start at 0
9192STATIC uint8_t can2_start_bank = 0 ;
92-
93+ extern const uint8_t DLCtoBytes [ 16 ];
9394#else
9495
9596#define CAN_MAX_FILTER (28)
97+ #define CAN_MAX_DATA_FRAME (8)
9698
9799#define CAN_DEFAULT_PRESCALER (100)
98100#define CAN_DEFAULT_SJW (1)
@@ -180,19 +182,50 @@ STATIC uint32_t pyb_can_get_source_freq() {
180182 return can_kern_clk ;
181183}
182184
185+ STATIC void pyb_can_get_bit_timing (mp_uint_t baudrate , mp_uint_t sample_point ,
186+ mp_int_t * bs1_out , mp_int_t * bs2_out , mp_int_t * prescaler_out ) {
187+ uint32_t can_kern_clk = pyb_can_get_source_freq ();
188+
189+ // The following max values work on all MCUs for classical CAN.
190+ for (int brp = 1 ; brp < 512 ; brp ++ ) {
191+ for (int bs1 = 1 ; bs1 < 16 ; bs1 ++ ) {
192+ for (int bs2 = 1 ; bs2 < 8 ; bs2 ++ ) {
193+ if ((baudrate == (can_kern_clk / (brp * (1 + bs1 + bs2 )))) &&
194+ ((sample_point * 10 ) == (((1 + bs1 ) * 1000 ) / (1 + bs1 + bs2 )))) {
195+ * bs1_out = bs1 ;
196+ * bs2_out = bs2 ;
197+ * prescaler_out = brp ;
198+ return ;
199+ }
200+ }
201+ }
202+ }
203+
204+ mp_raise_msg (& mp_type_ValueError , MP_ERROR_TEXT ("couldn't match baudrate and sample point" ));
205+ }
206+
183207// init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8)
184208STATIC mp_obj_t pyb_can_init_helper (pyb_can_obj_t * self , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
185- enum { ARG_mode , ARG_extframe , ARG_prescaler , ARG_sjw , ARG_bs1 , ARG_bs2 , ARG_auto_restart , ARG_baudrate , ARG_sample_point };
209+ enum { ARG_mode , ARG_extframe , ARG_prescaler , ARG_sjw , ARG_bs1 , ARG_bs2 , ARG_auto_restart , ARG_baudrate , ARG_sample_point ,
210+ ARG_brs_prescaler , ARG_brs_sjw , ARG_brs_bs1 , ARG_brs_bs2 , ARG_brs_baudrate , ARG_brs_sample_point };
186211 static const mp_arg_t allowed_args [] = {
187- { MP_QSTR_mode , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = CAN_MODE_NORMAL } },
188- { MP_QSTR_extframe , MP_ARG_BOOL , {.u_bool = false} },
189- { MP_QSTR_prescaler , MP_ARG_INT , {.u_int = CAN_DEFAULT_PRESCALER } },
190- { MP_QSTR_sjw , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_SJW } },
191- { MP_QSTR_bs1 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_BS1 } },
192- { MP_QSTR_bs2 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_BS2 } },
193- { MP_QSTR_auto_restart , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
194- { MP_QSTR_baudrate , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
195- { MP_QSTR_sample_point , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 75 } }, // 75% sampling point
212+ { MP_QSTR_mode , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = CAN_MODE_NORMAL } },
213+ { MP_QSTR_extframe , MP_ARG_BOOL , {.u_bool = false} },
214+ { MP_QSTR_prescaler , MP_ARG_INT , {.u_int = CAN_DEFAULT_PRESCALER } },
215+ { MP_QSTR_sjw , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_SJW } },
216+ { MP_QSTR_bs1 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_BS1 } },
217+ { MP_QSTR_bs2 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_BS2 } },
218+ { MP_QSTR_auto_restart , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
219+ { MP_QSTR_baudrate , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
220+ { MP_QSTR_sample_point , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 75 } }, // 75% sampling point
221+ #if MICROPY_HW_ENABLE_FDCAN
222+ { MP_QSTR_brs_prescaler , MP_ARG_INT , {.u_int = CAN_DEFAULT_PRESCALER } },
223+ { MP_QSTR_brs_sjw , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_SJW } },
224+ { MP_QSTR_brs_bs1 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_BS1 } },
225+ { MP_QSTR_brs_bs2 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = CAN_DEFAULT_BS2 } },
226+ { MP_QSTR_brs_baudrate , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
227+ { MP_QSTR_brs_sample_point , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } }
228+ #endif
196229 };
197230
198231 // parse args
@@ -206,34 +239,30 @@ STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, size_t n_args, const mp
206239
207240 // Calculate CAN bit timing from baudrate if provided
208241 if (args [ARG_baudrate ].u_int != 0 ) {
209- uint32_t baudrate = args [ARG_baudrate ].u_int ;
210- uint32_t sampoint = args [ARG_sample_point ].u_int ;
211- uint32_t can_kern_clk = pyb_can_get_source_freq ();
212- bool timing_found = false;
213-
214- // The following max values work on all MCUs for classical CAN.
215- for (int brp = 1 ; brp < 512 && !timing_found ; brp ++ ) {
216- for (int bs1 = 1 ; bs1 < 16 && !timing_found ; bs1 ++ ) {
217- for (int bs2 = 1 ; bs2 < 8 && !timing_found ; bs2 ++ ) {
218- if ((baudrate == (can_kern_clk / (brp * (1 + bs1 + bs2 )))) &&
219- ((sampoint * 10 ) == (((1 + bs1 ) * 1000 ) / (1 + bs1 + bs2 )))) {
220- args [ARG_bs1 ].u_int = bs1 ;
221- args [ARG_bs2 ].u_int = bs2 ;
222- args [ARG_prescaler ].u_int = brp ;
223- timing_found = true;
224- }
225- }
226- }
227- }
228- if (!timing_found ) {
229- mp_raise_msg (& mp_type_ValueError , MP_ERROR_TEXT ("couldn't match baudrate and sample point" ));
230- }
242+ pyb_can_get_bit_timing (args [ARG_baudrate ].u_int , args [ARG_sample_point ].u_int ,
243+ & args [ARG_bs1 ].u_int , & args [ARG_bs2 ].u_int , & args [ARG_prescaler ].u_int );
231244 }
232245
233- // init CAN (if it fails, it's because the port doesn't exist)
246+ #if MICROPY_HW_ENABLE_FDCAN
247+ // If no sample point is provided for data bit timing, use the nominal sample point.
248+ if (args [ARG_brs_sample_point ].u_int == 0 ) {
249+ args [ARG_brs_sample_point ].u_int = args [ARG_sample_point ].u_int ;
250+ }
251+ // Calculate BRS CAN bit timing from baudrate if provided
252+ if (args [ARG_brs_baudrate ].u_int != 0 ) {
253+ pyb_can_get_bit_timing (args [ARG_brs_baudrate ].u_int , args [ARG_brs_sample_point ].u_int ,
254+ & args [ARG_brs_bs1 ].u_int , & args [ARG_brs_bs2 ].u_int , & args [ARG_brs_prescaler ].u_int );
255+ }
256+ // Set BRS bit timings.
257+ self -> can .Init .DataPrescaler = args [ARG_brs_prescaler ].u_int ;
258+ self -> can .Init .DataSyncJumpWidth = args [ARG_brs_sjw ].u_int ;
259+ self -> can .Init .DataTimeSeg1 = args [ARG_bs1 ].u_int ; // DataTimeSeg1 = Propagation_segment + Phase_segment_1
260+ self -> can .Init .DataTimeSeg2 = args [ARG_bs2 ].u_int ;
261+ #endif
262+
234263 if (!can_init (self , args [ARG_mode ].u_int , args [ARG_prescaler ].u_int , args [ARG_sjw ].u_int ,
235264 args [ARG_bs1 ].u_int , args [ARG_bs2 ].u_int , args [ARG_auto_restart ].u_bool )) {
236- mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("CAN(%d) doesn't exist " ), self -> can_id );
265+ mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("CAN(%d) init failure " ), self -> can_id );
237266 }
238267
239268 return mp_const_none ;
@@ -450,12 +479,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_any_obj, pyb_can_any);
450479
451480// send(send, addr, *, timeout=5000)
452481STATIC mp_obj_t pyb_can_send (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
453- enum { ARG_data , ARG_id , ARG_timeout , ARG_rtr };
482+ enum { ARG_data , ARG_id , ARG_timeout , ARG_rtr , ARG_fdf , ARG_brs };
454483 static const mp_arg_t allowed_args [] = {
455484 { MP_QSTR_data , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
456485 { MP_QSTR_id , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 0 } },
457486 { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
458487 { MP_QSTR_rtr , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
488+ #if MICROPY_HW_ENABLE_FDCAN
489+ { MP_QSTR_fdf , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
490+ { MP_QSTR_brs , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
491+ #endif
459492 };
460493
461494 // parse args
@@ -468,21 +501,20 @@ STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
468501 uint8_t data [1 ];
469502 pyb_buf_get_for_send (args [ARG_data ].u_obj , & bufinfo , data );
470503
471- if (bufinfo .len > 8 ) {
504+ if (bufinfo .len > CAN_MAX_DATA_FRAME ) {
472505 mp_raise_ValueError (MP_ERROR_TEXT ("CAN data field too long" ));
473506 }
474507
475508 // send the data
476509 CanTxMsgTypeDef tx_msg ;
477510
478511 #if MICROPY_HW_ENABLE_FDCAN
479- uint8_t tx_data [8 ];
512+ uint8_t tx_data [CAN_MAX_DATA_FRAME ];
513+ memset (tx_data , 0 , sizeof (tx_data ));
514+
480515 tx_msg .MessageMarker = 0 ;
481516 tx_msg .ErrorStateIndicator = FDCAN_ESI_ACTIVE ;
482- tx_msg .BitRateSwitch = FDCAN_BRS_OFF ;
483- tx_msg .FDFormat = FDCAN_CLASSIC_CAN ;
484517 tx_msg .TxEventFifoControl = FDCAN_NO_TX_EVENTS ;
485- tx_msg .DataLength = (bufinfo .len << 16 ); // TODO DLC for len > 8
486518
487519 if (self -> extframe ) {
488520 tx_msg .Identifier = args [ARG_id ].u_int & 0x1FFFFFFF ;
@@ -496,6 +528,23 @@ STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
496528 } else {
497529 tx_msg .TxFrameType = FDCAN_REMOTE_FRAME ;
498530 }
531+ if (args [ARG_fdf ].u_bool == false) {
532+ tx_msg .FDFormat = FDCAN_CLASSIC_CAN ;
533+ } else {
534+ tx_msg .FDFormat = FDCAN_FD_CAN ;
535+ }
536+ if (args [ARG_brs ].u_bool == false) {
537+ tx_msg .BitRateSwitch = FDCAN_BRS_OFF ;
538+ } else {
539+ tx_msg .BitRateSwitch = FDCAN_BRS_ON ;
540+ }
541+ // Roundup DataLength to next DLC size and encode to DLC.
542+ for (mp_uint_t i = 0 ; i < MP_ARRAY_SIZE (DLCtoBytes ); i ++ ) {
543+ if (bufinfo .len <= DLCtoBytes [i ]) {
544+ tx_msg .DataLength = (i << 16 );
545+ break ;
546+ }
547+ }
499548 #else
500549 tx_msg .DLC = bufinfo .len ;
501550 uint8_t * tx_data = tx_msg .Data ; // Data is uint32_t but holds only 1 byte
@@ -565,7 +614,7 @@ STATIC mp_obj_t pyb_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
565614 // receive the data
566615 CanRxMsgTypeDef rx_msg ;
567616 #if MICROPY_HW_ENABLE_FDCAN
568- uint8_t rx_data [8 ];
617+ uint8_t rx_data [CAN_MAX_DATA_FRAME ];
569618 #else
570619 uint8_t * rx_data = rx_msg .Data ;
571620 #endif
0 commit comments