Skip to content

Commit 08ce2f2

Browse files
committed
Calculate FDCAN_clk instead of assuming fix 10MHz
- The FDCAN_clk is calculated on runtime from the according RCC-registers
1 parent f32efe4 commit 08ce2f2

File tree

1 file changed

+59
-2
lines changed

1 file changed

+59
-2
lines changed

targets/TARGET_STM/can_api.c

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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
62118
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
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

Comments
 (0)