@@ -76,6 +76,11 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
76
76
else if (pinmap -> peripheral == CAN_2 ) {
77
77
obj -> index = 1 ;
78
78
}
79
+ #endif
80
+ #if defined(FDCAN3_BASE )
81
+ else if (pinmap -> peripheral == CAN_3 ) {
82
+ obj -> index = 2 ;
83
+ }
79
84
#endif
80
85
else {
81
86
error ("can_init wrong instance\n" );
@@ -118,24 +123,49 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
118
123
Phase_segment_2 | 30 tq | <nts2> = <n_tq> - 1 - <nts1>
119
124
Synchronization_Jump_width | 30 tq | <nsjw> = <nts2>
120
125
*/
126
+
127
+ // !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk
128
+ // does not work for the desired bitrate, change system_clock settings for FDCAN_CLK
129
+ // (default FDCAN_CLK is PLLQ)
130
+ #ifdef TARGET_STM32G4
131
+ int ntq = HAL_RCCEx_GetPeriphCLKFreq (RCC_PERIPHCLK_FDCAN ) / hz ;
132
+ #else
133
+ // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN
134
+ // Internal ST ticket 92465
121
135
int ntq = 10000000 / hz ;
136
+ #endif
137
+
138
+ int nominalPrescaler = 1 ;
139
+ // !When the sample point should be lower than 50%, this must be changed to
140
+ // !IS_FDCAN_NOMINAL_TSEG2(ntq/nominalPrescaler), since
141
+ // NTSEG2 and SJW max values are lower. For now the sample point is fix @75%
142
+ while (!IS_FDCAN_NOMINAL_TSEG1 (ntq /nominalPrescaler )){
143
+ nominalPrescaler ++ ;
144
+ if (!IS_FDCAN_NOMINAL_PRESCALER (nominalPrescaler )){
145
+ error ("Could not determine good nominalPrescaler. Bad clock value\n" );
146
+ }
147
+ }
148
+ ntq = ntq /nominalPrescaler ;
122
149
123
150
obj -> CanHandle .Init .FrameFormat = FDCAN_FRAME_CLASSIC ;
124
151
obj -> CanHandle .Init .Mode = FDCAN_MODE_NORMAL ;
125
152
obj -> CanHandle .Init .AutoRetransmission = ENABLE ;
126
153
obj -> CanHandle .Init .TransmitPause = DISABLE ;
127
154
obj -> CanHandle .Init .ProtocolException = ENABLE ;
128
- obj -> CanHandle .Init .NominalPrescaler = 1 ; // Prescaler
155
+ obj -> CanHandle .Init .NominalPrescaler = nominalPrescaler ; // Prescaler
129
156
obj -> CanHandle .Init .NominalTimeSeg1 = ntq * 0.75 ; // Phase_segment_1
130
157
obj -> CanHandle .Init .NominalTimeSeg2 = ntq - 1 - obj -> CanHandle .Init .NominalTimeSeg1 ; // Phase_segment_2
131
158
obj -> CanHandle .Init .NominalSyncJumpWidth = obj -> CanHandle .Init .NominalTimeSeg2 ; // Synchronization_Jump_width
132
159
obj -> CanHandle .Init .DataPrescaler = 0x1 ; // Not used - only in FDCAN
133
160
obj -> CanHandle .Init .DataSyncJumpWidth = 0x1 ; // Not used - only in FDCAN
134
161
obj -> CanHandle .Init .DataTimeSeg1 = 0x1 ; // Not used - only in FDCAN
135
162
obj -> CanHandle .Init .DataTimeSeg2 = 0x1 ; // Not used - only in FDCAN
163
+ #ifndef TARGET_STM32G4
136
164
obj -> CanHandle .Init .MessageRAMOffset = 0 ;
165
+ #endif
137
166
obj -> CanHandle .Init .StdFiltersNbr = 1 ; // to be aligned with the handle parameter in can_filter
138
167
obj -> CanHandle .Init .ExtFiltersNbr = 1 ; // to be aligned with the handle parameter in can_filter
168
+ #ifndef TARGET_STM32G4
139
169
obj -> CanHandle .Init .RxFifo0ElmtsNbr = 8 ;
140
170
obj -> CanHandle .Init .RxFifo0ElmtSize = FDCAN_DATA_BYTES_8 ;
141
171
obj -> CanHandle .Init .RxFifo1ElmtsNbr = 0 ;
@@ -145,9 +175,11 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
145
175
obj -> CanHandle .Init .TxEventsNbr = 3 ;
146
176
obj -> CanHandle .Init .TxBuffersNbr = 0 ;
147
177
obj -> CanHandle .Init .TxFifoQueueElmtsNbr = 3 ;
178
+ #endif
148
179
obj -> CanHandle .Init .TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION ;
180
+ #ifndef TARGET_STM32G4
149
181
obj -> CanHandle .Init .TxElmtSize = FDCAN_DATA_BYTES_8 ;
150
-
182
+ #endif
151
183
can_internal_init (obj );
152
184
}
153
185
@@ -194,11 +226,19 @@ void can_irq_free(can_t *obj)
194
226
HAL_NVIC_DisableIRQ (FDCAN2_IT0_IRQn );
195
227
HAL_NVIC_DisableIRQ (FDCAN2_IT1_IRQn );
196
228
}
229
+ #endif
230
+ #if defined(FDCAN3_BASE )
231
+ else if (can == CAN_3 ) {
232
+ HAL_NVIC_DisableIRQ (FDCAN3_IT0_IRQn );
233
+ HAL_NVIC_DisableIRQ (FDCAN3_IT1_IRQn );
234
+ }
197
235
#endif
198
236
else {
199
237
return ;
200
238
}
239
+ #ifndef TARGET_STM32G4
201
240
HAL_NVIC_DisableIRQ (FDCAN_CAL_IRQn );
241
+ #endif
202
242
can_irq_ids [obj -> index ] = 0 ;
203
243
}
204
244
@@ -235,8 +275,34 @@ int can_frequency(can_t *obj, int f)
235
275
error ("HAL_FDCAN_Stop error\n" );
236
276
}
237
277
238
- /* See can_init_freq function for calculation details */
278
+
279
+ /* See can_init_freq function for calculation details
280
+ *
281
+ * !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk
282
+ * does not work for the desired bitrate, change system_clock settings for FDCAN_CLK
283
+ * (default FDCAN_CLK is PLLQ)
284
+ */
285
+ #ifdef TARGET_STM32G4
286
+ int ntq = HAL_RCCEx_GetPeriphCLKFreq (RCC_PERIPHCLK_FDCAN ) / f ;
287
+ #else
288
+ // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN
289
+ // Internal ST ticket 92465
239
290
int ntq = 10000000 / f ;
291
+ #endif
292
+
293
+ int nominalPrescaler = 1 ;
294
+ // !When the sample point should be lower than 50%, this must be changed to
295
+ // !IS_FDCAN_DATA_TSEG2(ntq/nominalPrescaler), since
296
+ // NTSEG2 and SJW max values are lower. For now the sample point is fix @75%
297
+ while (!IS_FDCAN_DATA_TSEG1 (ntq /nominalPrescaler )){
298
+ nominalPrescaler ++ ;
299
+ if (!IS_FDCAN_NOMINAL_PRESCALER (nominalPrescaler )){
300
+ error ("Could not determine good nominalPrescaler. Bad clock value\n" );
301
+ }
302
+ }
303
+ ntq = ntq /nominalPrescaler ;
304
+
305
+ obj -> CanHandle .Init .NominalPrescaler = nominalPrescaler ;
240
306
obj -> CanHandle .Init .NominalTimeSeg1 = ntq * 0.75 ; // Phase_segment_1
241
307
obj -> CanHandle .Init .NominalTimeSeg2 = ntq - 1 - obj -> CanHandle .Init .NominalTimeSeg1 ; // Phase_segment_2
242
308
obj -> CanHandle .Init .NominalSyncJumpWidth = obj -> CanHandle .Init .NominalTimeSeg2 ; // Synchronization_Jump_width
@@ -339,7 +405,7 @@ int can_read(can_t *obj, CAN_Message *msg, int handle)
339
405
msg -> format = CANExtended ;
340
406
}
341
407
msg -> id = RxHeader .Identifier ;
342
- msg -> type = CANData ;
408
+ msg -> type = ( RxHeader . RxFrameType == FDCAN_DATA_FRAME ) ? CANData : CANRemote ;
343
409
msg -> len = RxHeader .DataLength >> 16 ; // see FDCAN_data_length_code value
344
410
345
411
return 1 ;
@@ -441,14 +507,21 @@ static void can_irq(CANName name, int id)
441
507
irq_handler (can_irq_ids [id ], IRQ_TX );
442
508
}
443
509
}
444
-
510
+ #ifndef TARGET_STM32G4
445
511
if (__HAL_FDCAN_GET_IT_SOURCE (& CanHandle , FDCAN_IT_RX_BUFFER_NEW_MESSAGE )) {
446
512
if (__HAL_FDCAN_GET_FLAG (& CanHandle , FDCAN_IT_RX_BUFFER_NEW_MESSAGE )) {
447
513
__HAL_FDCAN_CLEAR_FLAG (& CanHandle , FDCAN_IT_RX_BUFFER_NEW_MESSAGE );
448
514
irq_handler (can_irq_ids [id ], IRQ_RX );
449
515
}
450
516
}
451
-
517
+ #else
518
+ if (__HAL_FDCAN_GET_IT_SOURCE (& CanHandle , FDCAN_IT_RX_FIFO0_NEW_MESSAGE )) {
519
+ if (__HAL_FDCAN_GET_FLAG (& CanHandle , FDCAN_IT_RX_FIFO0_NEW_MESSAGE )) {
520
+ __HAL_FDCAN_CLEAR_FLAG (& CanHandle , FDCAN_IT_RX_FIFO0_NEW_MESSAGE );
521
+ irq_handler (can_irq_ids [id ], IRQ_RX );
522
+ }
523
+ }
524
+ #endif
452
525
if (__HAL_FDCAN_GET_IT_SOURCE (& CanHandle , FDCAN_IT_ERROR_WARNING )) {
453
526
if (__HAL_FDCAN_GET_FLAG (& CanHandle , FDCAN_FLAG_ERROR_WARNING )) {
454
527
__HAL_FDCAN_CLEAR_FLAG (& CanHandle , FDCAN_FLAG_ERROR_WARNING );
@@ -481,6 +554,7 @@ void FDCAN1_IT1_IRQHandler(void)
481
554
can_irq (CAN_1 , 0 );
482
555
}
483
556
557
+ #if defined(FDCAN2_BASE )
484
558
void FDCAN2_IT0_IRQHandler (void )
485
559
{
486
560
can_irq (CAN_2 , 1 );
@@ -490,6 +564,20 @@ void FDCAN2_IT1_IRQHandler(void)
490
564
{
491
565
can_irq (CAN_2 , 1 );
492
566
}
567
+ #endif //FDCAN2_BASE
568
+
569
+ #if defined(FDCAN3_BASE )
570
+ void FDCAN3_IT0_IRQHandler (void )
571
+ {
572
+ can_irq (CAN_3 , 2 );
573
+ }
574
+
575
+ void FDCAN3_IT1_IRQHandler (void )
576
+ {
577
+ can_irq (CAN_3 , 2 );
578
+ }
579
+ #endif //FDCAN3_BASE
580
+
493
581
494
582
// TODO Add other interrupts ?
495
583
void can_irq_set (can_t * obj , CanIrqType type , uint32_t enable )
@@ -501,7 +589,11 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
501
589
interrupts = FDCAN_IT_TX_COMPLETE ;
502
590
break ;
503
591
case IRQ_RX :
592
+ #ifndef TARGET_STM32G4
504
593
interrupts = FDCAN_IT_RX_BUFFER_NEW_MESSAGE ;
594
+ #else
595
+ interrupts = FDCAN_IT_RX_FIFO0_NEW_MESSAGE ;
596
+ #endif
505
597
break ;
506
598
case IRQ_ERROR :
507
599
interrupts = FDCAN_IT_ERROR_WARNING ;
@@ -531,6 +623,12 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
531
623
NVIC_SetVector (FDCAN2_IT1_IRQn , (uint32_t )& FDCAN2_IT1_IRQHandler );
532
624
NVIC_EnableIRQ (FDCAN2_IT1_IRQn );
533
625
#endif
626
+ #if defined(FDCAN3_BASE )
627
+ NVIC_SetVector (FDCAN3_IT0_IRQn , (uint32_t )& FDCAN3_IT0_IRQHandler );
628
+ NVIC_EnableIRQ (FDCAN3_IT0_IRQn );
629
+ NVIC_SetVector (FDCAN3_IT1_IRQn , (uint32_t )& FDCAN3_IT1_IRQHandler );
630
+ NVIC_EnableIRQ (FDCAN3_IT1_IRQn );
631
+ #endif
534
632
}
535
633
536
634
#else /* FDCAN1 */
0 commit comments