FDCAN1 support for stm32g4 and stm32h7

Post here first, or if you can't find a relevant section!
Post Reply
owennewo
Posts: 6
Joined: Thu Dec 03, 2020 1:17 pm
Answers: 1

FDCAN1 support for stm32g4 and stm32h7

Post by owennewo »

TLDR: Any advice, links to getting FDCAN1 working on stm32g431 using stm32duino appreciated. I'm coding in PlatformIO but use Cube IDE as a reference.

Some of the newer stm32 chips come with FDCAN instead of CAN. I suspect I'm not interested with additional benefits of FDCAN for my modest robotics project so will probably be aiming to be CAN 2.0 compatible - unfortunately FDCAN has different API and there are less resources online.

Initially I'll have two stm32g431CBU in the form of the b-g431b-esc1 Discovery Kit for Drones communicating. This board has a CAN Tranceiver (TCAN330DCNT) soldered to CAN_TX (PB9) and CAN_RX (PA11) - looks like the CAN_TX will need remapping from PA12.

I can see that the CMSIS driver in stm32g431xx.h has FDCAN1 + loads of FDCAN control/status registers but I was hoping for some higher level API and tutorials/examples ;)

Any suggestions on how to dig into FDCAN? I was thinking on seeing if I can get stm32CubeIDE to autogenerate some code but I've not really used cube and haven't used CAN before so I'm feeling a bit blind. I don't really know the difference between LL_ and HAL_ and what should be supported on stm32duino.

Owen
by owennewo » Tue Jan 26, 2021 4:24 pm
Solved my issue. Not sure what my initial problem was. For those with similar issues - here is a basic example of canfd with g4:

https://github.com/owennewo/youtube_can ... c/main.cpp
https://github.com/owennewo/youtube_can ... pleCan.cpp
Go to full post
owennewo
Posts: 6
Joined: Thu Dec 03, 2020 1:17 pm
Answers: 1

Re: FDCAN1 support for stm32g4 and stm32h7

Post by owennewo »

I've made a first attempt at getting a "hello world" send/receive. The `HAL_FDCAN_AddMessageToTxFifoQ()` returns HAL_OK but I don't see the CAN_H and CAN_L lines moving from midpoint (2V) on the scope and the polling receive also finds no message. I've tried `FDCAN_MODE_NORMAL` and `FDCAN_MODE_INTERNAL_LOOPBACK`. No joy.

Here is the code I've uploaded to both discovery kit boards.

Code: Select all

// THIS DOESN'T WORK.  
// Discussed here https://www.stm32duino.com/viewtopic.php?f=7&t=832

#include <Arduino.h>
#include "fdcan.h"

FDCAN_HandleTypeDef hfdcan1;
FDCAN_TxHeaderTypeDef tx_header;

void sendCanMessage() {

  uint8_t TxData[2];
  TxData[0] = 1;
  TxData[1] = 0xAD;

  if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &tx_header, TxData) != HAL_OK)
  {
    Serial.println("Error add");
    Error_Handler();
  } else {
    Serial.println("Added");
  }
}

void pollCanMessage() {
  
  uint8_t receiveData[8];
  FDCAN_RxHeaderTypeDef* receiveHeader = {};

  HAL_StatusTypeDef status = HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, receiveHeader, receiveData); 
  
  if ( status != HAL_OK) {
    Serial.print("no data: "); Serial.println(status);
    
  } else {
    //we have data
    Serial.println(receiveData[1]);
    
  }
  
}

void setup() {

  pinMode(CAN_TERM, OUTPUT);
  pinMode(CAN_TX, OUTPUT);
  pinMode(CAN_RX, INPUT);

  // this enables the 120ohm resistor
  digitalWrite(CAN_TERM, HIGH);

  // hold low to enable can tranceiver
  pinMode(CAN_SHDN, OUTPUT);
  digitalWrite(CAN_SHDN, LOW);

  Serial.begin(115200);
  delay(1000);

  Serial.println("setup start");

  tx_header.Identifier = 0x321;
  tx_header.IdType = FDCAN_STANDARD_ID;
  tx_header.TxFrameType = FDCAN_DATA_FRAME;
  tx_header.DataLength = FDCAN_DLC_BYTES_2;
  tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  tx_header.BitRateSwitch = FDCAN_BRS_OFF;
  tx_header.FDFormat = FDCAN_CLASSIC_CAN;
  tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
  tx_header.MessageMarker = 0;

  __HAL_RCC_GPIOB_CLK_ENABLE();

  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
  PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }

  pinmap_pinout(PB_9, PinMap_CAN_TD);
  pinmap_pinout(PA_11, PinMap_CAN_RD);
  
  hfdcan1.Instance = FDCAN1;
  hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; //FDCAN_FRAME_CLASSIC; // FDCAN_FRAME_FD_NO_BRS
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; // FDCAN_MODE_INTERNAL_LOOPBACK | FDCAN_MODE_NORMAL;
  hfdcan1.Init.AutoRetransmission = DISABLE;
  hfdcan1.Init.TransmitPause = DISABLE;
  hfdcan1.Init.ProtocolException = DISABLE;
  hfdcan1.Init.NominalPrescaler = 20;//1;
  hfdcan1.Init.NominalSyncJumpWidth = 1;
  hfdcan1.Init.NominalTimeSeg1 = 14; //2;
  hfdcan1.Init.NominalTimeSeg2 = 2;
  hfdcan1.Init.DataPrescaler = 1;
  hfdcan1.Init.DataSyncJumpWidth = 1;
  hfdcan1.Init.DataTimeSeg1 = 1;
  hfdcan1.Init.DataTimeSeg2 = 1;
  hfdcan1.Init.StdFiltersNbr = 1; //0;
  hfdcan1.Init.ExtFiltersNbr = 0;
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; // FDCAN_TX_QUEUE_OPERATION;

  Serial.println("setup before init");
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }

  Serial.println("setup after init");

  FDCAN_FilterTypeDef sFilterConfig;

  /* Configure Rx filter */
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_MASK;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x321;
  sFilterConfig.FilterID2 = 0x7FF;
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
  {
    Error_Handler();
  }

  /* Start the FDCAN module */
  if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
  {
    Error_Handler();
  }
  Serial.println("setup notifies");
}

void loop() {
  static long last_micros = 0;
  long now = micros();
  if (now-last_micros > 1000000) {
    sendCanMessage();
    last_micros = now;
    delay(50);
    pollCanMessage();
  }
}
It is possible that the issue lies in the variant/board definition for b-g431g-esc1 which I'm in the process of getting merged into stm32duino:
https://github.com/stm32duino/Arduino_C ... 1236/files
owennewo
Posts: 6
Joined: Thu Dec 03, 2020 1:17 pm
Answers: 1

Re: FDCAN1 support for stm32g4 and stm32h7

Post by owennewo »

There is something very wrong with FDCAN1 peripheral registers for my board. It is like they are unsettable (or badly mapped).
For instance if I call init HAL_FDCAN_Init with mode=FDCAN_MODE_INTERNAL_LOOPBACK:

Code: Select all

uint32_t cccr = READ_REG(FDCAN1->CCCR);
  Serial.print("cccr - before: "); Serial.println(cccr);

  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
    Serial.println("setup init error");
  }
  cccr = READ_REG(FDCAN1->CCCR);
  Serial.print("cccr - after: "); Serial.println(cccr);
Both cccr before/after return b00000001 indicating that the init bit is set. Yet when I step through code I can see it calling the following macros:

Code: Select all

SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);
SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)
{
   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
}

So I'd expect TEST and MON bits to be set on CCCR but they are not.

I see similar things during HAL_FDCAN_AddMessageToTxFifoQ. This function calls FDCAN_CopyMessageToRAM - but the message bytes don't seem to actually get written.

My suspicion is that the ldscript.ld for the board and/or stm32g431xx.h are incorrect - but this is not an area I understand to well.
noweare
Posts: 8
Joined: Mon Apr 20, 2020 2:14 pm

Re: FDCAN1 support for stm32g4 and stm32h7

Post by noweare »

Sorry can't help since I have not used can.
I can answer the LL vs HAL. The LL drivers are a self documenting interface to the register manipulation.
Unless you know the details of can the hal drivers will probably be more useful.
The hal is higher level and take care of some of the details for us.
owennewo
Posts: 6
Joined: Thu Dec 03, 2020 1:17 pm
Answers: 1

Re: FDCAN1 support for stm32g4 and stm32h7

Post by owennewo »

Solved my issue. Not sure what my initial problem was. For those with similar issues - here is a basic example of canfd with g4:

https://github.com/owennewo/youtube_can ... c/main.cpp
https://github.com/owennewo/youtube_can ... pleCan.cpp
Post Reply

Return to “General discussion”