@@ -76,6 +76,11 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
7676 else if (pinmap -> peripheral == CAN_2 ) {
7777 obj -> index = 1 ;
7878 }
79+ #endif
80+ #if defined(FDCAN3_BASE )
81+ else if (pinmap -> peripheral == CAN_3 ) {
82+ obj -> index = 2 ;
83+ }
7984#endif
8085 else {
8186 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
118123 Phase_segment_2 | 30 tq | <nts2> = <n_tq> - 1 - <nts1>
119124 Synchronization_Jump_width | 30 tq | <nsjw> = <nts2>
120125 */
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
121135 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 ;
122149
123150 obj -> CanHandle .Init .FrameFormat = FDCAN_FRAME_CLASSIC ;
124151 obj -> CanHandle .Init .Mode = FDCAN_MODE_NORMAL ;
125152 obj -> CanHandle .Init .AutoRetransmission = ENABLE ;
126153 obj -> CanHandle .Init .TransmitPause = DISABLE ;
127154 obj -> CanHandle .Init .ProtocolException = ENABLE ;
128- obj -> CanHandle .Init .NominalPrescaler = 1 ; // Prescaler
155+ obj -> CanHandle .Init .NominalPrescaler = nominalPrescaler ; // Prescaler
129156 obj -> CanHandle .Init .NominalTimeSeg1 = ntq * 0.75 ; // Phase_segment_1
130157 obj -> CanHandle .Init .NominalTimeSeg2 = ntq - 1 - obj -> CanHandle .Init .NominalTimeSeg1 ; // Phase_segment_2
131158 obj -> CanHandle .Init .NominalSyncJumpWidth = obj -> CanHandle .Init .NominalTimeSeg2 ; // Synchronization_Jump_width
132159 obj -> CanHandle .Init .DataPrescaler = 0x1 ; // Not used - only in FDCAN
133160 obj -> CanHandle .Init .DataSyncJumpWidth = 0x1 ; // Not used - only in FDCAN
134161 obj -> CanHandle .Init .DataTimeSeg1 = 0x1 ; // Not used - only in FDCAN
135162 obj -> CanHandle .Init .DataTimeSeg2 = 0x1 ; // Not used - only in FDCAN
163+ #ifndef TARGET_STM32G4
136164 obj -> CanHandle .Init .MessageRAMOffset = 0 ;
165+ #endif
137166 obj -> CanHandle .Init .StdFiltersNbr = 1 ; // to be aligned with the handle parameter in can_filter
138167 obj -> CanHandle .Init .ExtFiltersNbr = 1 ; // to be aligned with the handle parameter in can_filter
168+ #ifndef TARGET_STM32G4
139169 obj -> CanHandle .Init .RxFifo0ElmtsNbr = 8 ;
140170 obj -> CanHandle .Init .RxFifo0ElmtSize = FDCAN_DATA_BYTES_8 ;
141171 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
145175 obj -> CanHandle .Init .TxEventsNbr = 3 ;
146176 obj -> CanHandle .Init .TxBuffersNbr = 0 ;
147177 obj -> CanHandle .Init .TxFifoQueueElmtsNbr = 3 ;
178+ #endif
148179 obj -> CanHandle .Init .TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION ;
180+ #ifndef TARGET_STM32G4
149181 obj -> CanHandle .Init .TxElmtSize = FDCAN_DATA_BYTES_8 ;
150-
182+ #endif
151183 can_internal_init (obj );
152184}
153185
@@ -194,11 +226,19 @@ void can_irq_free(can_t *obj)
194226 HAL_NVIC_DisableIRQ (FDCAN2_IT0_IRQn );
195227 HAL_NVIC_DisableIRQ (FDCAN2_IT1_IRQn );
196228 }
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+ }
197235#endif
198236 else {
199237 return ;
200238 }
239+ #ifndef TARGET_STM32G4
201240 HAL_NVIC_DisableIRQ (FDCAN_CAL_IRQn );
241+ #endif
202242 can_irq_ids [obj -> index ] = 0 ;
203243}
204244
@@ -235,8 +275,34 @@ int can_frequency(can_t *obj, int f)
235275 error ("HAL_FDCAN_Stop error\n" );
236276 }
237277
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
239290 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 ;
240306 obj -> CanHandle .Init .NominalTimeSeg1 = ntq * 0.75 ; // Phase_segment_1
241307 obj -> CanHandle .Init .NominalTimeSeg2 = ntq - 1 - obj -> CanHandle .Init .NominalTimeSeg1 ; // Phase_segment_2
242308 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)
339405 msg -> format = CANExtended ;
340406 }
341407 msg -> id = RxHeader .Identifier ;
342- msg -> type = CANData ;
408+ msg -> type = ( RxHeader . RxFrameType == FDCAN_DATA_FRAME ) ? CANData : CANRemote ;
343409 msg -> len = RxHeader .DataLength >> 16 ; // see FDCAN_data_length_code value
344410
345411 return 1 ;
@@ -441,14 +507,21 @@ static void can_irq(CANName name, int id)
441507 irq_handler (can_irq_ids [id ], IRQ_TX );
442508 }
443509 }
444-
510+ #ifndef TARGET_STM32G4
445511 if (__HAL_FDCAN_GET_IT_SOURCE (& CanHandle , FDCAN_IT_RX_BUFFER_NEW_MESSAGE )) {
446512 if (__HAL_FDCAN_GET_FLAG (& CanHandle , FDCAN_IT_RX_BUFFER_NEW_MESSAGE )) {
447513 __HAL_FDCAN_CLEAR_FLAG (& CanHandle , FDCAN_IT_RX_BUFFER_NEW_MESSAGE );
448514 irq_handler (can_irq_ids [id ], IRQ_RX );
449515 }
450516 }
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
452525 if (__HAL_FDCAN_GET_IT_SOURCE (& CanHandle , FDCAN_IT_ERROR_WARNING )) {
453526 if (__HAL_FDCAN_GET_FLAG (& CanHandle , FDCAN_FLAG_ERROR_WARNING )) {
454527 __HAL_FDCAN_CLEAR_FLAG (& CanHandle , FDCAN_FLAG_ERROR_WARNING );
@@ -481,6 +554,7 @@ void FDCAN1_IT1_IRQHandler(void)
481554 can_irq (CAN_1 , 0 );
482555}
483556
557+ #if defined(FDCAN2_BASE )
484558void FDCAN2_IT0_IRQHandler (void )
485559{
486560 can_irq (CAN_2 , 1 );
@@ -490,6 +564,20 @@ void FDCAN2_IT1_IRQHandler(void)
490564{
491565 can_irq (CAN_2 , 1 );
492566}
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+
493581
494582// TODO Add other interrupts ?
495583void 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)
501589 interrupts = FDCAN_IT_TX_COMPLETE ;
502590 break ;
503591 case IRQ_RX :
592+ #ifndef TARGET_STM32G4
504593 interrupts = FDCAN_IT_RX_BUFFER_NEW_MESSAGE ;
594+ #else
595+ interrupts = FDCAN_IT_RX_FIFO0_NEW_MESSAGE ;
596+ #endif
505597 break ;
506598 case IRQ_ERROR :
507599 interrupts = FDCAN_IT_ERROR_WARNING ;
@@ -531,6 +623,12 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
531623 NVIC_SetVector (FDCAN2_IT1_IRQn , (uint32_t )& FDCAN2_IT1_IRQHandler );
532624 NVIC_EnableIRQ (FDCAN2_IT1_IRQn );
533625#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
534632}
535633
536634#else /* FDCAN1 */
0 commit comments