Calculate FDCAN_clk instead of assuming fix 10MHz

- The FDCAN_clk is calculated on runtime from the according
RCC-registers
pull/13565/head
Martin Eckardt 2020-08-27 16:29:53 +02:00
parent f32efe4c28
commit 08ce2f2de8
1 changed files with 59 additions and 2 deletions

View File

@ -57,6 +57,62 @@ int can_internal_init(can_t *obj)
return 1;
}
/** Calculate the fdcan-core-clk value for accurate calculation of the quantum timing
*
* !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk
* does not work for the desired bitrate, change system_clock settings for PLLQ
*
* !Attention For now, PCLK is not supported (PLLQ is selected always anyways)
*
* @returns
* core_frequency when successful
* -1 when error / not supported
*/
static int _can_get_core_frequency( void )
{
int clk_sel = (RCC->CCIPR & RCC_CCIPR_FDCANSEL_Msk) >> RCC_CCIPR_FDCANSEL_Pos;
switch (clk_sel){
case 0: //! HSE clock selected as FDCAN clock
{
return HSE_VALUE;
}
case 1: //! PLL "Q" clock selected as FDCAN clock
{
int pll_source_clk;
int pll_source = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC_Msk);
if (pll_source == RCC_PLLCFGR_PLLSRC_HSE){
pll_source_clk = HSE_VALUE;
} else if (pll_source == RCC_PLLCFGR_PLLSRC_HSI){
pll_source_clk = HSI_VALUE;
} else {
MBED_ERROR(
MBED_MAKE_ERROR(MBED_MODULE_DRIVER_CAN, MBED_ERROR_CODE_CONFIG_UNSUPPORTED),
"PLL source must be HSI or HSE");
return -1;
}
int pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM_Msk) >> RCC_PLLCFGR_PLLM_Pos) + 1;
int plln = (RCC->PLLCFGR & RCC_PLLCFGR_PLLN_Msk) >> RCC_PLLCFGR_PLLN_Pos;
int pllq = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ_Msk) >> RCC_PLLCFGR_PLLQ_Pos) + 1;
pllq = pllq * 2;
int fdcan_freq = ((pll_source_clk / pllm) * plln) / pllq;
return fdcan_freq;
}
case 2: //! PCLK Clk selected as FDCAN clock
case 3:
default:
MBED_ERROR(
MBED_MAKE_ERROR(MBED_MODULE_DRIVER_CAN, MBED_ERROR_CODE_CONFIG_UNSUPPORTED),
"Wrong clk_source configuration");
return -1;
}
}
#if STATIC_PINMAP_READY
#define CAN_INIT_FREQ_DIRECT can_init_freq_direct
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
Phase_segment_2 | 30 tq | <nts2> = <n_tq> - 1 - <nts1>
Synchronization_Jump_width | 30 tq | <nsjw> = <nts2>
*/
int ntq = 10000000 / hz;
int ntq = _can_get_core_frequency() / hz;
obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL;
@ -254,7 +311,7 @@ int can_frequency(can_t *obj, int f)
}
/* See can_init_freq function for calculation details */
int ntq = 10000000 / f;
int ntq = _can_get_core_frequency() / f;
obj->CanHandle.Init.NominalTimeSeg1 = ntq * 0.75; // Phase_segment_1
obj->CanHandle.Init.NominalTimeSeg2 = ntq - 1 - obj->CanHandle.Init.NominalTimeSeg1; // Phase_segment_2
obj->CanHandle.Init.NominalSyncJumpWidth = obj->CanHandle.Init.NominalTimeSeg2; // Synchronization_Jump_width