cancel
Showing results for 
Search instead for 
Did you mean: 

How does watermark for FDCAN work? - STM32H7

Yoschii97
Associate III

Thats a question that has bothered me for a while. When receiving FDCAN messages, I can specify a watermark on how many bytes the interrupt triggers.

How exactly does it work?

If I have a message of 8 bytes and I set the watermark to 1 byte, does the interrupt trigger 8 times?

And then do I always have 1Byte in the payload? Or the entire message.

Besides, what's the best way to check? Because currently, every time I debug and go to the message in the interrupt to see what is in RxData, I already see my complete message.

I actually want (especially with lower bit rates) that if the first part of a CAN message is already available, i can analyze its in order to send it out if necessary.

Heres Config FDCAN ->

void MX_FDCAN1_Init(void)
{
  /*
    Bit time parameter         | Nominal
    ---------------------------|--------------
    fdcan_ker_ck               | 20 MHz
    Time_quantum (tq)          | 50 ns
    Synchronization_segment    | 1 tq
    Propagation_segment        | 3 tq
    Phase_segment_1            | 8 tq
    Phase_segment_2            | 8 tq
    Synchronization_Jump_width | 8 tq
    Bit_length                 | 20 tq = 1 µs
    Bit_rate                   | 1.0 MBit/s
  */
  hfdcan1.Instance = FDCAN1;
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
  hfdcan1.Init.AutoRetransmission = ENABLE;
  hfdcan1.Init.TransmitPause = DISABLE;
  hfdcan1.Init.ProtocolException = ENABLE;
  /* Nominal Time Quanta */
  hfdcan1.Init.NominalPrescaler = round(1e6/CANBaudRate);	
  hfdcan1.Init.NominalSyncJumpWidth = 8;					
  hfdcan1.Init.NominalTimeSeg1 = 11;		
  hfdcan1.Init.NominalTimeSeg2 = 8;	
 
  /* Derzeit fest eingestellt für 2MBit/s */
  hfdcan1.Init.DataPrescaler = 1;
  hfdcan1.Init.DataSyncJumpWidth = 4;
  hfdcan1.Init.DataTimeSeg1 = 5;
  hfdcan1.Init.DataTimeSeg2 = 4;
 
  hfdcan1.Init.MessageRAMOffset = 0;
  hfdcan1.Init.StdFiltersNbr = 1;
  hfdcan1.Init.ExtFiltersNbr = 0;
  hfdcan1.Init.RxFifo0ElmtsNbr = 2;
  hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
  hfdcan1.Init.RxFifo1ElmtsNbr = 0;
  hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
  hfdcan1.Init.RxBuffersNbr = 0;
  hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
  hfdcan1.Init.TxEventsNbr = 0;
  hfdcan1.Init.TxBuffersNbr = 0;
  hfdcan1.Init.TxFifoQueueElmtsNbr = 2;
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
  hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN FDCAN1_Init 2 */
  HAL_StatusTypeDef Error;
  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 = 0x111;
  sFilterConfig.FilterID2 = 0x000; /* For acceptance, MessageID and FilterID1 must not match */
  Error = HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
  if(Error != HAL_OK) Error_Handler();
  /* Configure global filter to reject all non-matching frames */
  Error = HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
  if(Error != HAL_OK) Error_Handler();
  /* Configure Rx FIFO 0 watermark to 1 */
  Error = HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
  if(Error != HAL_OK) Error_Handler();
  /* Activate Rx FIFO 0 watermark notification */
  Error = HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
  if(Error != HAL_OK) Error_Handler();
  /* Start the FDCAN module */
  Error = HAL_FDCAN_Start(&hfdcan1);
  if(Error != HAL_OK) Error_Handler();
}

And of course the Interupt where the CAN Message is read ->

void FDCAN1_IT0_IRQHandler(void)
{
  FDCAN_RxHeaderTypeDef RxHeader;
  uint8_t RxData[8];
  HAL_FDCAN_IRQHandler(&hfdcan1);
  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
  HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &RxHeader, RxData);
  if((RxHeader->DataLength >> 16) == FDCAN_DLC_BYTES_0) return;	
  can_interpret(&RxHeader, RxData);
}

I am incredibly sorry if I am wrong with such questions here in the forum..

But thanks for everyone who takes the time to help me! :D

1 REPLY 1
Yoschii97
Associate III

Or have I completely misunderstood something and the interrupt only triggers when the CAN message has been fully received?

And the watermark only describes the size of the total number of databytes received?