2022-12-18 05:16 AM
Hello,
In my project I need CPU frequency independent CANBUS and SAI2 Master clock output.
CANBUS is running out of PLL2P clock, while SAI2 MCLK is selected from PLL3P
If I only enable one or the other, they work great, but if I enable them all together desister ! My CANBUS traffic is just garbage and it hangs while the SAI2 clock is good. They are all on completely different PLL’s I don’t understand how it happens and how to fix it
Here is SAI2_MCLK enable:
void DCMI_Master_Clock_Config(void)
{
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_RCC_SetSAIClockSource(LL_RCC_SAI2_CLKSOURCE_PLL3);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SAI2);
LL_GPIO_SetPinMode(GPIOC,LL_GPIO_PIN_11,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetPinSpeed(GPIOC,LL_GPIO_PIN_11,LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetAFPin_8_15(GPIOC,LL_GPIO_PIN_11,LL_GPIO_AF_13);
LL_GPIO_SetPinOutputType(GPIOC,LL_GPIO_PIN_11,LL_GPIO_OUTPUT_PUSHPULL);
SAI2_Block_B->CR1 &=~SAI_xCR1_SAIEN;
SAI2_Block_B->CR1 |=SAI_xCR1_MCKEN;
}
CANBUS config (10MHz clock from PLL2)
#define FDCAN_RX_PIN LL_GPIO_PIN_11
#define FDCAN_TX_PIN LL_GPIO_PIN_12
#define FDCAN_PORT GPIOA
void FDCAN_Interface(void)
{
LL_RCC_SetFDCANClockSource(LL_RCC_FDCAN_CLKSOURCE_PLL2);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_FDCAN1);
LL_GPIO_SetPinMode (FDCAN_PORT,FDCAN_TX_PIN,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15 (FDCAN_PORT,FDCAN_TX_PIN,LL_GPIO_AF_9);
LL_GPIO_SetPinSpeed (FDCAN_PORT,FDCAN_TX_PIN,LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType(FDCAN_PORT,FDCAN_TX_PIN,LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinMode (FDCAN_PORT,FDCAN_RX_PIN,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15 (FDCAN_PORT,FDCAN_RX_PIN,LL_GPIO_AF_9);
LL_GPIO_SetPinSpeed (FDCAN_PORT,FDCAN_RX_PIN|FDCAN_TX_PIN,LL_GPIO_SPEED_FREQ_VERY_HIGH);
}
void FDCAN1_Init(void)
{
//10MHz
FDCAN.Instance = FDCAN1;
FDCAN.Init.ClockDivider = FDCAN_CLOCK_DIV1;
FDCAN.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
FDCAN.Init.Mode = FDCAN_MODE_NORMAL;
FDCAN.Init.AutoRetransmission = ENABLE;
FDCAN.Init.TransmitPause = ENABLE;
FDCAN.Init.ProtocolException = DISABLE;
FDCAN.Init.NominalPrescaler = 0x1;
FDCAN.Init.NominalSyncJumpWidth = 0x10;
FDCAN.Init.NominalTimeSeg1 = 17;
FDCAN.Init.NominalTimeSeg2 = 2;
FDCAN.Init.StdFiltersNbr = 1;
FDCAN.Init.ExtFiltersNbr = 1;
FDCAN.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&FDCAN) != HAL_OK)
{
ERROR_CANBUS();
}
}
And peripheral PLL2 and PLL3 configuration that is done before any SAI or FDCAN
void PeriphCommonClock_Config(void)
{
LL_RCC_PLL2_ConfigDomain_SAI(LL_RCC_PLL2SOURCE_HSE, 5, 40, 20); // 25 / 5 * 40 / 20 = 10MHz
LL_RCC_PLL2_EnableDomain_SAI();
LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_4_8);
LL_RCC_PLL2_Enable();
uint32_t timeout = 0xFFFFFF;
while(LL_RCC_PLL2_IsReady() != 1)
{
timeout--;
if(timeout==0)
{
break;
}
}
LL_RCC_PLL3_ConfigDomain_SAI(LL_RCC_PLL3SOURCE_HSE, 5, 40, 2); //100MHz
LL_RCC_PLL3_EnableDomain_SAI();
LL_RCC_PLL3_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_4_8);
LL_RCC_PLL3_Enable();
timeout = 0xFFFFFF;
while(LL_RCC_PLL3_IsReady() != 1)
{
timeout--;
if(timeout==0)
{
break;
}
}
}
I don't see any pin collisions , I don't see any PLL collisions, and both devices are located on different PLL's. What do I am missing ?
Clock system design
I also tried enabling one before the other, but it did not help.
Here is perfect FDCAN packet send and acknowledged by other node:
And here what happens if I try to Enable SAI2 MCLK
As you can see, my green waveform ( FDCAN) is jus garbadge. I can promise you where is no interference on PCB, they are located far far away from each other.
Any ideas?
2022-12-18 05:42 AM
Read out and check/post content of relevant RCC registers.
JW
2022-12-18 06:35 AM
Hello, Thank you for taking time on this:
Bits 25:24 FDCAN1SEL[1:0]: FDCAN1 kernel clock source selection
These bits are used to select the FDCAN1 kernel clock source.
00: HSE clock selected
01: PLL1“Q�? (pll1_q_ck) selected
10: PLL2 “P�? (pll2_p_ck) selected
11: reserved
CCIPR1 is set correctly in both cases:
AHB2NER are also looking ok
CCIPR2 looks to be correct also SAI2SEL bit.
And the rest looks to be same on all cases
2022-12-19 03:07 AM
> And the rest looks to be same on all cases
Well, then the problem is not in RCC/clocks setup, but the software as such.
For example if both SAI and CAN are handled in their respective interrupts, if SAI is of higher priority than the CAN interrupt and there are too many SAI events, it then can starve the CAN interrupt.
Debug as usually: form hypotheses, construct tests that prove/disprove them, rinse and repeat.
JW
2022-12-19 04:36 AM
SAI is nothing more than clock output to my DCMI camera. Where is no interrupts at the moment, while I do tested canbus and it is working as it should, if SAI is disabled.
WIll try to do some more debugging, errata is also clear about this by the looks of it.
2022-12-20 05:30 AM
It looks like only single bit is killing my CANBUS :relieved_face:
SAI2_Block_B->CR1 = SAI_xCR1_MCKEN;
SAI2 don't even need to be enabled for clock to be passed to GPIO pin (PC11), I get clock, but I don't get any canbus traffic to MCU.
If I pass this single bit flip, all is well,I can receive and transmit canbus, no problems....
2022-12-20 06:38 AM
And if I switch to PLL1, it works also with SAI2-MCLK...
2022-12-20 03:50 PM
Try not configuring the SAIx_MCLK pin to any alternate function and then enable the same clocks. That will show whether the problem is internal or external to the MCU.