@@ -57,6 +57,62 @@ int can_internal_init(can_t *obj)
57
57
return 1 ;
58
58
}
59
59
60
+
61
+ /** Calculate the fdcan-core-clk value for accurate calculation of the quantum timing
62
+ *
63
+ * !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk
64
+ * does not work for the desired bitrate, change system_clock settings for PLLQ
65
+ *
66
+ * !Attention For now, PCLK is not supported (PLLQ is selected always anyways)
67
+ *
68
+ * @returns
69
+ * core_frequency when successful
70
+ * -1 when error / not supported
71
+ */
72
+ static int _can_get_core_frequency ( void )
73
+ {
74
+ int clk_sel = (RCC -> CCIPR & RCC_CCIPR_FDCANSEL_Msk ) >> RCC_CCIPR_FDCANSEL_Pos ;
75
+
76
+ switch (clk_sel ){
77
+ case 0 : //! HSE clock selected as FDCAN clock
78
+ {
79
+ return HSE_VALUE ;
80
+ }
81
+ case 1 : //! PLL "Q" clock selected as FDCAN clock
82
+ {
83
+ int pll_source_clk ;
84
+
85
+ int pll_source = (RCC -> PLLCFGR & RCC_PLLCFGR_PLLSRC_Msk );
86
+ if (pll_source == RCC_PLLCFGR_PLLSRC_HSE ){
87
+ pll_source_clk = HSE_VALUE ;
88
+ } else if (pll_source == RCC_PLLCFGR_PLLSRC_HSI ){
89
+ pll_source_clk = HSI_VALUE ;
90
+ } else {
91
+ MBED_ERROR (
92
+ MBED_MAKE_ERROR (MBED_MODULE_DRIVER_CAN , MBED_ERROR_CODE_CONFIG_UNSUPPORTED ),
93
+ "PLL source must be HSI or HSE" );
94
+ return -1 ;
95
+ }
96
+
97
+ int pllm = ((RCC -> PLLCFGR & RCC_PLLCFGR_PLLM_Msk ) >> RCC_PLLCFGR_PLLM_Pos ) + 1 ;
98
+ int plln = (RCC -> PLLCFGR & RCC_PLLCFGR_PLLN_Msk ) >> RCC_PLLCFGR_PLLN_Pos ;
99
+ int pllq = ((RCC -> PLLCFGR & RCC_PLLCFGR_PLLQ_Msk ) >> RCC_PLLCFGR_PLLQ_Pos ) + 1 ;
100
+ pllq = pllq * 2 ;
101
+ int fdcan_freq = ((pll_source_clk / pllm ) * plln ) / pllq ;
102
+
103
+ return fdcan_freq ;
104
+ }
105
+ case 2 : //! PCLK Clk selected as FDCAN clock
106
+ case 3 :
107
+ default :
108
+ MBED_ERROR (
109
+ MBED_MAKE_ERROR (MBED_MODULE_DRIVER_CAN , MBED_ERROR_CODE_CONFIG_UNSUPPORTED ),
110
+ "Wrong clk_source configuration" );
111
+ return -1 ;
112
+ }
113
+ }
114
+
115
+
60
116
#if STATIC_PINMAP_READY
61
117
#define CAN_INIT_FREQ_DIRECT can_init_freq_direct
62
118
void can_init_freq_direct (can_t * obj , const can_pinmap_t * pinmap , int hz )
@@ -123,7 +179,8 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
123
179
Phase_segment_2 | 30 tq | <nts2> = <n_tq> - 1 - <nts1>
124
180
Synchronization_Jump_width | 30 tq | <nsjw> = <nts2>
125
181
*/
126
- int ntq = 10000000 / hz ;
182
+
183
+ int ntq = _can_get_core_frequency () / hz ;
127
184
128
185
obj -> CanHandle .Init .FrameFormat = FDCAN_FRAME_CLASSIC ;
129
186
obj -> CanHandle .Init .Mode = FDCAN_MODE_NORMAL ;
@@ -254,7 +311,7 @@ int can_frequency(can_t *obj, int f)
254
311
}
255
312
256
313
/* See can_init_freq function for calculation details */
257
- int ntq = 10000000 / f ;
314
+ int ntq = _can_get_core_frequency () / f ;
258
315
obj -> CanHandle .Init .NominalTimeSeg1 = ntq * 0.75 ; // Phase_segment_1
259
316
obj -> CanHandle .Init .NominalTimeSeg2 = ntq - 1 - obj -> CanHandle .Init .NominalTimeSeg1 ; // Phase_segment_2
260
317
obj -> CanHandle .Init .NominalSyncJumpWidth = obj -> CanHandle .Init .NominalTimeSeg2 ; // Synchronization_Jump_width
0 commit comments