Libuavcan CubeMX FreeRTOS SystemWorkbenchForSTM32

Hello,

I am trying to implement libuavcan on stm32f103tb6 (36 pins) mcu using cubemx generated project with freertos on system workbench IDE.
Just for simplicity I am using generated project and IDE gives fast conversion to C++.
Similar project with the same mcu on chibios working properly, but with generated project and freertos it’s not working.

Maybe someone could help to solve issues ?

it stucks on can.init phase

    if (!waitMsrINakBitStateChange(false))
    {
        UAVCAN_STM32_LOG("MSR INAK not cleared");
        can_->MCR = bxcan::MCR_RESET;
        return -ErrMsrInakNotCleared;
    }

at uc_stm32_can.cpp

my main.cpp

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <uavcan/uavcan.hpp>
#include <uavcan_stm32/uavcan_stm32.hpp>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;

osThreadId defaultTaskHandle;
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
void StartDefaultTask(void const * argument);

/* USER CODE BEGIN PFP */
/*
#define DEBUG_BUFFER_SIZE    (256)
#define DEBUG_TIMEOUT        (1000)

osSemaphoreId DEBUG_TX_completeID;
osSemaphoreDef(DEBUG_TX_complete);

uint8_t DEBUG_TX_Buffer[DEBUG_BUFFER_SIZE] = {0};  //!< Debug buffer.
// Private functions ---------------------------------------------------------

bool DEBUG_Init(void)
{
    if ((DEBUG_TX_completeID = osSemaphoreCreate(osSemaphore(DEBUG_TX_complete), 1)) == NULL)
    {
        return false;
    }
    return true;
}

void DEBUG_Printf(const char *fmt, ...)
{
    uint16_t i = 0;
    va_list args;
    if (osSemaphoreWait(DEBUG_TX_completeID, 1000) == osOK)
    {
        va_start(args, fmt);
        i = vsnprintf((char*) DEBUG_TX_Buffer, DEBUG_BUFFER_SIZE - 1, fmt, args);
        DEBUG_TX_Buffer[i] = 0x00;

        uint16_t retry = 4096;

        while ((retry--)&&(HAL_UART_Transmit(&huart3, &DEBUG_TX_Buffer[0], strlen((char*)&DEBUG_TX_Buffer[0]), 0xFFF) != HAL_OK));

        va_end(args);
        osSemaphoreRelease(DEBUG_TX_completeID);
    }
    return;
}
*/
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
constexpr unsigned NodePoolSize = 2048;
uavcan_stm32::CanInitHelper<> can;

uavcan::Node<NodePoolSize>& getNode() {
    static uavcan::Node<NodePoolSize> node(can.driver, uavcan_stm32::SystemClock::instance());
    return node;
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint32_t value = 1000000;
	int res = 0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN_Init();
  /* USER CODE BEGIN 2 */
  //DEBUG_Init();

  res = can.init(value);

/*
  getNode().setName("org.kmti.gmm_controler");
  getNode().setNodeID(1);

   if (getNode().start() < 0) {
	  //DEBUG_Printf("UAVCAN init fail\r\n");
	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
	  while(1);
   }

   getNode().setModeOperational();
*/
  /* USER CODE END 2 */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* Start scheduler */
  osKernelStart();
  
  /* We should never get here as control is now taken by the scheduler */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

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

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV2;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief CAN Initialization Function
  * @param None
  * @retval None
  */
static void MX_CAN_Init(void)
{

  /* USER CODE BEGIN CAN_Init 0 */

  /* USER CODE END CAN_Init 0 */

  /* USER CODE BEGIN CAN_Init 1 */

  /* USER CODE END CAN_Init 1 */
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 2;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_12TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_5TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = DISABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN_Init 2 */

  /* USER CODE END CAN_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);

  /*Configure GPIO pins : PB6 PB7 */
  GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used 
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{

  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
	  /*
	  if (getNode().spin(uavcan::MonotonicDuration::fromMSec(500)) < 0) {
		  //DEBUG_Printf("UAVCAN spin fail\r\n");
		  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
		  //while(1);
	  }
	  */
    //osDelay(1);
  }
  /* USER CODE END 5 */ 
}

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM1 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

chip.h

#ifndef CHIP_H
#define CHIP_H

#include <stm32f1xx.h>

#define STM32F1XX

#define STM32_PCLK1           (36000000ul)          // 32 MHz
#define STM32_TIMCLK1         (72000000ul)          // 64 MHz
//#define CAN1_TX_IRQHandler    CAN1_TX_IRQHandler          //redefined
//#define CAN1_RX0_IRQHandler   CAN1_RX0_IRQHandler      //redefined
#define CAN1_RX1_IRQHandler   CAN1_RX1_IRQHandler

#endif

For new user I can’t upload whole project, so if are need some more info ask for it

1 Like

Looks like you might have forgotten to initialize the GPIO pins properly. Please check that.

OK. So GPIO pins in CubeMX is defined like below

and stm32f1xx_hal_msp.c with CAN1 pins configuration looks like this

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : stm32f1xx_hal_msp.c
  * Description        : This file provides code for the MSP Initialization 
  *                      and de-Initialization codes.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */

/* USER CODE END TD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
 
/* USER CODE END Define */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */

/* USER CODE END Macro */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */

/* USER CODE END ExternalFunctions */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */
/**
  * Initializes the Global MSP.
  */
void HAL_MspInit(void)
{
  /* USER CODE BEGIN MspInit 0 */

  /* USER CODE END MspInit 0 */

  __HAL_RCC_AFIO_CLK_ENABLE();
  __HAL_RCC_PWR_CLK_ENABLE();

  /* System interrupt init*/
  /* PendSV_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);

  /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled 
  */
  __HAL_AFIO_REMAP_SWJ_NOJTAG();

  /* USER CODE BEGIN MspInit 1 */

  /* USER CODE END MspInit 1 */
}

/**
* @brief CAN MSP Initialization
* This function configures the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hcan->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**CAN GPIO Configuration    
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }

}

/**
* @brief CAN MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
{
  if(hcan->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspDeInit 0 */

  /* USER CODE END CAN1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_CAN1_CLK_DISABLE();
  
    /**CAN GPIO Configuration    
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);

  /* USER CODE BEGIN CAN1_MspDeInit 1 */

  /* USER CODE END CAN1_MspDeInit 1 */
  }

}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

I think GPIO pins from main.cpp and file above are configured correctly, or I am wrong ?
CAN speed calculated to be 1Mb/s. I am using Zubax Babel with 1 Mb/s and how I said before using ChibiOs gives me great results, but I need everything to do on different platform.

Per the Reference Manual, the macrocell enters the Normal state once it has observed 11 consecutive recessive bits on the bus:

The request to enter Normal mode is issued by clearing the INRQ bit in the CAN_MCR register. The bxCAN enters Normal mode and is ready to take part in bus activities when it has synchronized with the data transfer on the CAN bus. This is done by waiting for the occurrence of a sequence of 11 consecutive recessive bits (Bus Idle state). The switch to Normal mode is confirmed by the hardware by clearing the INAK bit in the CAN_MSR register.

In your case, the pin is apparently stuck at the low level, making the controller wait for the inter-space frame (the eleven bits) forever. The GPIO config seems correct, so another possibility is that your hardware is malfunctioning. Are you sure the CAN transceiver is operating properly and is connected as it should be?

I have readed ref manual and understand an issue, but i don’t know how to solve it. Board is working and result are shown in picture below with ChibiOS implementation.

it is pure software issue. Maybe if I upload whole project someone could check it ?

I don’t think anybody would volunteer to debug your project for you, but you could try the Jobs section: https://forum.opencyphal.org/c/general/jobs

Clearly the problem resides somewhere in the GPIO configuration, so focus your search on that.

Few days I had brainstorming on this and found small solution.
I have added HAL_delay(1); mentioned before condition and I was luck. It passed succesfully.

uc_stm32_can.cpp

    /*
     * Hardware initialization (the hardware has already confirmed initialization mode, see above)
     */
    can_->MCR = bxcan::MCR_ABOM | bxcan::MCR_AWUM | bxcan::MCR_INRQ;  // RM page 648

    can_->BTR = ((timings.sjw & 3U)  << 24) |
                ((timings.bs1 & 15U) << 16) |
                ((timings.bs2 & 7U)  << 20) |
                (timings.prescaler & 1023U) |
                ((mode == SilentMode) ? bxcan::BTR_SILM : 0);

    can_->IER = bxcan::IER_TMEIE |   // TX mailbox empty
                bxcan::IER_FMPIE0 |  // RX FIFO 0 is not empty
                bxcan::IER_FMPIE1;   // RX FIFO 1 is not empty

    can_->MCR &= ~bxcan::MCR_INRQ;   // Leave init mode

    HAL_Delay(1);

    if (!waitMsrINakBitStateChange(false))
    {
        UAVCAN_STM32_LOG("MSR INAK not cleared");
        can_->MCR = bxcan::MCR_RESET;
        return -ErrMsrInakNotCleared;
    }

Why it was needed I don’t know.

So next where I stuck is what it’s not geting in operational mode. I just got in Initialisation.

GetNodeInfo show {}

Where the problem could be ? Or some ideas where to search ?

main.cpp

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <uavcan/uavcan.hpp>
#include <uavcan_stm32/uavcan_stm32.hpp>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;

TIM_HandleTypeDef htim2;

osThreadId defaultTaskHandle;
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
static void MX_TIM2_Init(void);
void StartDefaultTask(void const * argument);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
constexpr unsigned NodePoolSize = 2048;
uavcan_stm32::CanInitHelper<> can;

uavcan::Node<NodePoolSize>& getNode() {
    static uavcan::Node<NodePoolSize> node(can.driver, uavcan_stm32::SystemClock::instance());
    return node;
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  uint32_t value = 1000000;

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  //DEBUG_Init();

  can.init(value);

  getNode().setName("org.controler");
  getNode().setNodeID(1);

  if (getNode().start() < 0) {
	  //DEBUG_Printf("UAVCAN init fail\r\n");
	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
	  while(1);
  }

  getNode().setModeOperational();

  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);

  /* USER CODE END 2 */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* Start scheduler */
  osKernelStart();
  
  /* We should never get here as control is now taken by the scheduler */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

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

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV2;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief CAN Initialization Function
  * @param None
  * @retval None
  */
static void MX_CAN_Init(void)
{

  /* USER CODE BEGIN CAN_Init 0 */

  /* USER CODE END CAN_Init 0 */

  /* USER CODE BEGIN CAN_Init 1 */

  /* USER CODE END CAN_Init 1 */
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 2;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_12TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_5TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = DISABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN_Init 2 */

  /* USER CODE END CAN_Init 2 */

}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 0;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);

  /*Configure GPIO pins : PB6 PB7 */
  GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used 
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{

  /* USER CODE BEGIN 5 */

  /* Infinite loop */
  for(;;)
  {
	  if (getNode().spin(uavcan::MonotonicDuration::fromMSec(500)) < 0) {
		  //DEBUG_Printf("UAVCAN spin fail\r\n");
		  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
	  //}
    //osDelay(500);
  }
  /* USER CODE END 5 */ 
}

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM1 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Also some warnings

Description	Resource	Path	Location	Type
Field 'hardware_version' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 155	Semantic Error
Field 'hardware_version' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 157	Semantic Error
Field 'health' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 124	Semantic Error
Field 'mode' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 129	Semantic Error
Field 'name' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 15	Semantic Error
Field 'name' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 139	Semantic Error
Field 'name' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 141	Semantic Error
Field 'software_version' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 147	Semantic Error
Field 'software_version' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 149	Semantic Error
Field 'status' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 22	Semantic Error
Field 'status' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 26	Semantic Error
Field 'status' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 124	Semantic Error
Field 'status' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 129	Semantic Error
Field 'status' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 134	Semantic Error
Field 'uptime_sec' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 22	Semantic Error
Field 'vendor_specific_status_code' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 134	Semantic Error
Invalid arguments '
Candidates are:
int log(const ? &)
int log(?, const char *, const char *, #0(...) ...)
'	node.hpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/include/uavcan/node	line 74	Semantic Error
Invalid arguments '
Candidates are:
void setHardwareVersion(const ? &)
'	node.hpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/include/uavcan/node	line 204	Semantic Error
Invalid arguments '
Candidates are:
void setName(const ? &)
'	main.cpp	/stm32f103TB/Src	line 115	Semantic Error
Invalid arguments '
Candidates are:
void setName(const ? &)
'	node.hpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/include/uavcan/node	line 167	Semantic Error
Invalid arguments '
Candidates are:
void setSoftwareVersion(const ? &)
'	node.hpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/include/uavcan/node	line 203	Semantic Error
Invalid arguments '
Candidates are:
void setVendorSpecificStatusCode(?)
'	node.hpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/include/uavcan/node	line 197	Semantic Error
Member declaration not found	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 50	Semantic Error
Member declaration not found	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 132	Semantic Error
Member declaration not found	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 137	Semantic Error
Member declaration not found	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 145	Semantic Error
Member declaration not found	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 153	Semantic Error
Method 'broadcast' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 26	Semantic Error
Method 'empty' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 15	Semantic Error
Method 'empty' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 139	Semantic Error
Method 'setPriority' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 68	Semantic Error
Method 'setTxTimeout' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 106	Semantic Error
Method 'start' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 79	Semantic Error
Method 'stop' could not be resolved	uc_node_status_provider.cpp	/stm32f103TB/Middlewares/libuavcan/libuavcan/src/protocol	line 91	Semantic Error

1 Like

You are supposed to invoke setModeOperational(), as you are attempting to do in the code you’ve posted. The code is clearly invalid, it won’t even compile because of numerous syntax errors.

Those are errors, not warnings. Your code does not compile, I don’t know what are you running.

Libuavcan might be a bit steep for a beginner, consider honing your C++ skills with simpler applications first.

I have found solution it was no CAN drivers. it was library :frowning: then debugging feature was fully solved. it happens what it stuck on AVLtree loop. So my colleague purposed to take older version. After “git checkout 36701b” everything began to work. A lot time was spent on finding so simple solution. I will push later to my git and provide link for examples, but I need to find additional solution and for this i will create next topic.

@Zarkopafilis would you be able to look into this, please?

Could you log a bug in GitHub against the AVL tree with details on what you observed? The code is very new and I’m excited to see we found an issue! Thanks so much.

mistake with working commit it’s 67da0aa. I just remember numbers 67.


I have pushed two working examples

https://github.com/raimapo/UAVCAN-examples

Is this related to the startup (before spinning)?

At first glance I can’t find anything wrong with the tree. The part of the code you pointed at is covered by TEST(AvlTree, MultipleEntriesPerKey) test. It should work properly. It’s ‘impossible’ for this to fail, unless you only add items for transfer in a while loop without spinning.

This condition may occur in a valid application on a limited time interval where multiple transfers are added between spins. Would this cause the tree to fail?

Not really. The point I wanted to make here is to double check for logical mistake in user-code. It’s designed to work specifically that way: schedule transfer, work to send on spin.

1 Like

Hi. I’ve got the same issue. There is a typo in the appendToEndOf method:

target = head->equal_keys;

should be

target = target->equal_keys;

The case happens when the driver is busy and all the frames produced from a single message are sent to a linked list.

2 Likes

Sorry for the delay on this. https://github.com/UAVCAN/libuavcan/pull/265 is in review. Will be fixed soon.

1 Like

Hello. I’m making a node on stm32 (Nucleo-F29ZI). Now I have a simple node code that broadcasts nodestatus. To initialize the kernel and clock, I used CubeMX. GPIO_CAN initialized on its own. I also assembled a slcan node and created a connection … And the UAVCAN gui tool does not see messages from my node. What could be the problem? My node functions exactly: I looked in the debugger and connected a logic analyzer to the bus. It constantly sends errors to the bus. I attach code without auto-generated:

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "chip.h"
#include "uavcan_stm32.hpp"
/* USER CODE END Includes */


/* USER CODE BEGIN PV */
const int RxQueueSize = 128;
static std::uint32_t BitRate = 1000000;
const unsigned NodeMemoryPoolSize = 16384;
/* USER CODE END PV */

/* USER CODE BEGIN PFP */
static void USER_AFIO_CAN1_Init(void); //init the CAN1 pins
uavcan::ISystemClock& getSystemClock();
uavcan::ICanDriver& getCanDriver();
static uavcan::Node<NodeMemoryPoolSize>& getNode();
/* USER CODE END PFP */


int main(void)
{
  

  USER_AFIO_CAN1_Init();
  static uavcan::Node<NodeMemoryPoolSize>& node = getNode();
  if (node.setNodeID(10) == 0){
	  while(1);
  }
  node.setName("uavcan.equipment.actuator");

  uavcan::protocol::SoftwareVersion sw_version;
  sw_version.major = 1;
  node.setSoftwareVersion(sw_version);

  uavcan::protocol::HardwareVersion hw_version;
  hw_version.major = 1;
  node.setHardwareVersion(hw_version);

  node.setHealthOk();

 
  if (node.start() < 0){	//uavcan::TransferPriority::Default
	  while(1);
  }





  node.setModeOperational();
  
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  
  while (1)
  {
	  if (node.spin(uavcan::MonotonicDuration::fromMSec(100)) < 0){
		  while(1);
	  }


    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */

static void USER_AFIO_CAN1_Init(void){
	//gpiod clock is enabled before, because should not
	GPIO_InitTypeDef CAN1_AFIO;
	//Configure CAN1_RX_Pin
	CAN1_AFIO.Pin = CAN1_RX_Pin;
	CAN1_AFIO.Mode = GPIO_MODE_AF_PP;
	CAN1_AFIO.Pull = GPIO_NOPULL;
	CAN1_AFIO.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	CAN1_AFIO.Alternate = GPIO_AF9_CAN1;
	HAL_GPIO_Init(CAN1_RX_GPIO, &CAN1_AFIO);

	//Configure CAN1_TX_Pin
	CAN1_AFIO.Pin = CAN1_TX_Pin;
	CAN1_AFIO.Mode = GPIO_MODE_AF_PP;
	CAN1_AFIO.Pull = GPIO_NOPULL;
	CAN1_AFIO.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	CAN1_AFIO.Alternate = GPIO_AF9_CAN1;
	HAL_GPIO_Init(CAN1_TX_GPIO, &CAN1_AFIO);
}

uavcan::ISystemClock& getSystemClock(){
	return uavcan_stm32::SystemClock::instance();
}

uavcan::ICanDriver& getCanDriver(){
	static uavcan_stm32::CanInitHelper<RxQueueSize> can;
	static bool initialized = false;
	if (!initialized){
		initialized = true;
		int res = can.init(BitRate);
		if(res <0){
			while(1);
		}
	}
	return can.driver;
}

static uavcan::Node<NodeMemoryPoolSize>& getNode(){
	static uavcan::Node<NodeMemoryPoolSize> node(getCanDriver(), getSystemClock());
	return node;
}

Sorry, I can`t attach the schedule screenshot of logic analyzer(

This could be caused by a misconfigured (different) CAN bit rate.

Our anti-spam policies might be a bit overly paranoid. I have manually confirmed your trust level so you should be able to post pics now.

Pavel Kirienko, as I understand, the variable

static std::uint32_t BitRate = 1000000

determines CAN bitrate. The bitrate of slcan is the same.
Thank you) This is schedule of logic analyzer

With attached slcan and my node the schedule is same: only my node is publishing