STM32F446 Canbus with Core 2.0 Timing Issues

Post Reply
Tazzi
Posts: 20
Joined: Wed Jan 08, 2020 12:45 am

STM32F446 Canbus with Core 2.0 Timing Issues

Post by Tazzi »

I just updated to the latest v2.0 core from v1.9, and the exact same code now results in issues on the canbus.

As soon as the CAN is initiated, the entire bus starts freaking out, it appears almost if either the pins are not being set correctly or the frequency is out, although this works perfectly fine on v1.9

Has there been any changes relating to CANbus in v2.0 of the stm32 arduino core? Or something that affects pinout?
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: STM32F446 Canbus with Core 2.0 Timing Issues

Post by fpiSTM »

Which board you select in the menu?
Maybe clock config has changed.
Tazzi
Posts: 20
Joined: Wed Jan 08, 2020 12:45 am

Re: STM32F446 Canbus with Core 2.0 Timing Issues

Post by Tazzi »

I am selecting:
Board: Generic STM32F4 Series
Board Part Number: Generic F446RETX

I believe it could be clock related, Im trying to compare all changes from v1.9 to 2.0 in git but it is quite extensive.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: STM32F446 Canbus with Core 2.0 Timing Issues

Post by fpiSTM »

Change has been made in this commits
https://github.com/stm32duino/Arduino_C ... 17540678c6

All generic definitions have been unified and only uses the HSI.
Before generic clock config tries several config HSE bypass, HSE and finally HSI anyway we saw several issues using this method that's why it has been removed. You can try to redefine the system clock config:
https://github.com/stm32duino/wiki/wiki ... ock_config

anyway I saw no issue on the default one :(
Tazzi
Posts: 20
Joined: Wed Jan 08, 2020 12:45 am

Re: STM32F446 Canbus with Core 2.0 Timing Issues

Post by Tazzi »

Thankyou so much for that tip!

Right I understand. I have reimplemented the original clock timing functions and it is still not functioning correctly. I have copy/pasted directly from the variant.cpp file for the STM32F446 variant and its now working.

Something done in the new method doesnt seem to line up nicely with the timing.

This is the NEW method:

Code: Select all

/*
 *******************************************************************************
 * Copyright (c) 2020-2021, STMicroelectronics
 * All rights reserved.
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */
#if defined(ARDUINO_GENERIC_F446RCTX) || defined(ARDUINO_GENERIC_F446RETX)
#include "pins_arduino.h"

 /**
   * @brief  System Clock Configuration
   * @param  None
   * @retval None
   */
WEAK void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 180;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 8;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    Error_Handler();
  }
  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
    | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLRCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SDIO | RCC_PERIPHCLK_CLK48;
  PeriphClkInitStruct.PLLSAI.PLLSAIM = 16;
  PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
  PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2;
  PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4;
  PeriphClkInitStruct.PLLSAIDivQ = 1;
  PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLSAIP;
  PeriphClkInitStruct.SdioClockSelection = RCC_SDIOCLKSOURCE_CLK48;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
    Error_Handler();
  }
}

#endif /* ARDUINO_GENERIC_* */

And this is the old method which I now have in my main ino up top:

Code: Select all

/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
static uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
{
	RCC_OscInitTypeDef RCC_OscInitStruct;
	RCC_ClkInitTypeDef RCC_ClkInitStruct;
	RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

	/* The voltage scaling allows optimizing the power consumption when the device is
	clocked below the maximum system frequency, to update the voltage scaling value
	regarding system frequency refer to product datasheet. */
	__HAL_RCC_PWR_CLK_ENABLE();
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	// Enable HSE oscillator and activate PLL with HSE as source
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	if (bypass == 0) {
		RCC_OscInitStruct.HSEState = RCC_HSE_ON; // External 8 MHz xtal on OSC_IN/OSC_OUT
	}
	else {
		RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External 8 MHz clock on OSC_IN
	}

	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
	RCC_OscInitStruct.PLL.PLLM = HSE_VALUE / 1000000L; // Expects an 8 MHz external clock by default. Redefine HSE_VALUE if not
	RCC_OscInitStruct.PLL.PLLN = 360;                  // VCO output clock = 360 MHz (1 MHz * 360)
	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;        // PLLCLK = 180 MHz (360 MHz / 2)
	RCC_OscInitStruct.PLL.PLLQ = 7;
	RCC_OscInitStruct.PLL.PLLR = 2;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
		return 0; // FAIL
	}

	// Activate the OverDrive to reach the 180 MHz Frequency
	if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
		return 0; // FAIL
	}

	// Select PLLSAI output as USB clock source
	PeriphClkInitStruct.PLLSAI.PLLSAIM = HSE_VALUE / 1000000L;
	PeriphClkInitStruct.PLLSAI.PLLSAIN = 384;
	PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV8;
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48;
	PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLSAIP;
	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

	// Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;         // 180 MHz
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;           // 45 MHz
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;           // 90 MHz
	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
		return 0; // FAIL
	}

	/* Output clock on MCO1 pin(PA8) for debugging purpose */
	/*
	if (bypass == 0)
	  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); // 4 MHz
	else
	  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1); // 8 MHz
	*/

	return 1; // OK
}

/******************************************************************************/
/*            PLL (clocked by HSI) used as System clock source                */
/******************************************************************************/
uint8_t SetSysClock_PLL_HSI(void)
{
	RCC_OscInitTypeDef RCC_OscInitStruct;
	RCC_ClkInitTypeDef RCC_ClkInitStruct;
	RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

	/* The voltage scaling allows optimizing the power consumption when the device is
	  clocked below the maximum system frequency, to update the voltage scaling value
	  regarding system frequency refer to product datasheet. */
	__HAL_RCC_PWR_CLK_ENABLE();
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	// Enable HSI oscillator and activate PLL with HSI as source
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
	RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
	RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
	RCC_OscInitStruct.PLL.PLLM = 16;            // VCO input clock = 1 MHz (16 MHz / 16)
	RCC_OscInitStruct.PLL.PLLN = 360;           // VCO output clock = 360 MHz (1 MHz * 360)
	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLLCLK = 180 MHz (360 MHz / 2)
	RCC_OscInitStruct.PLL.PLLQ = 7;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
		return 0; // FAIL
	}

	// Activate the OverDrive to reach the 180 MHz Frequency
	if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
		return 0; // FAIL
	}

	// Select PLLSAI output as USB clock source
	PeriphClkInitStruct.PLLSAI.PLLSAIM = 8;
	PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
	PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV8;
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48;
	PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLSAIP;
	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

	/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
	RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;         // 180 MHz
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;           // 45 MHz
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;           // 90 MHz
	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
		return 0; // FAIL
	}

	/* Output clock on MCO1 pin(PA8) for debugging purpose */
	//HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_1); // 16 MHz

	return 1; // OK
}

extern "C" void SystemClock_Config() {
	// new clock config
	 /* 1- If fail try to start with HSE and external xtal */
	if (SetSysClock_PLL_HSE(0) == 0) {
		/* 2- Try to start with HSE and external clock */
		if (SetSysClock_PLL_HSE(1) == 0) {
			/* 3- If fail start with HSI clock */
			if (SetSysClock_PLL_HSI() == 0) {
				Error_Handler();
			}
		}
	}
}
Tazzi
Posts: 20
Joined: Wed Jan 08, 2020 12:45 am

Re: STM32F446 Canbus with Core 2.0 Timing Issues

Post by Tazzi »

Comparing the two, it appears the new core only supports HSI? Instead of trying the external HSE first?

Might be something to add as a user configurable item as that really messed up CAN timing, and I noticed the timed based items like flashing LEDs appeared to be a touch faster which would explain also the CAN having problems.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: STM32F446 Canbus with Core 2.0 Timing Issues

Post by fpiSTM »

Tazzi wrote: Fri May 21, 2021 9:49 am Comparing the two, it appears the new core only supports HSI? Instead of trying the external HSE first?
Yes all generics use the internal clock by default as the goal of a generic is to work on all boards. If user wants use another clock source he have to redefine at sketch level the system clock config as explained in the wiki.
So in your case if your board has an HSE simply define it at sketch level.
The generic F446 has been tested with a Nucleo F446RE but not the CAN as the core has no dedicated development for this.
Post Reply

Return to “STM32F4 based boards”