@@ -57,6 +57,62 @@ int can_internal_init(can_t *obj)
5757 return 1 ;
5858}
5959
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+
60116#if STATIC_PINMAP_READY
61117#define CAN_INIT_FREQ_DIRECT can_init_freq_direct
62118void 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
123179 Phase_segment_2 | 30 tq | <nts2> = <n_tq> - 1 - <nts1>
124180 Synchronization_Jump_width | 30 tq | <nsjw> = <nts2>
125181 */
126- int ntq = 10000000 / hz ;
182+
183+ int ntq = _can_get_core_frequency () / hz ;
127184
128185 obj -> CanHandle .Init .FrameFormat = FDCAN_FRAME_CLASSIC ;
129186 obj -> CanHandle .Init .Mode = FDCAN_MODE_NORMAL ;
@@ -254,7 +311,7 @@ int can_frequency(can_t *obj, int f)
254311 }
255312
256313 /* See can_init_freq function for calculation details */
257- int ntq = 10000000 / f ;
314+ int ntq = _can_get_core_frequency () / f ;
258315 obj -> CanHandle .Init .NominalTimeSeg1 = ntq * 0.75 ; // Phase_segment_1
259316 obj -> CanHandle .Init .NominalTimeSeg2 = ntq - 1 - obj -> CanHandle .Init .NominalTimeSeg1 ; // Phase_segment_2
260317 obj -> CanHandle .Init .NominalSyncJumpWidth = obj -> CanHandle .Init .NominalTimeSeg2 ; // Synchronization_Jump_width
0 commit comments