candle-usb / candleLight_fw

gs_usb compatible firmware for candleLight, cantact and canable
Other
633 stars 282 forks source link

CandleLight FD at 8 Mbps #173

Open tomasjakubik opened 9 months ago

tomasjakubik commented 9 months ago

This issue is specifically with candleLight FD and fork topic/candleLightFD, but that doesn't allow issues.

We are starting a CAN FD project. We bought some candleLight FDs to debug and perhaps to manage the network from Linux. The issue is that this firmware doesn't compensate for transceiver delay and so it cannot transmit over about 2 Mbps. Receive works fine with 1 & 8 Mbps, but when you try transmitting, the FDCAN peripheral cannot verify the bits it sent, fails, repeats and fails again. Without Tx delay compensation, my code was behaving in a similar way. Here is some code that works for me on G4 nucleo clocked at 160 MHz:

        hfdcan2.Instance = FDCAN2;
        hfdcan2.Init.ClockDivider = UINT32_MAX; // Divider is not available for FDCAN2
        hfdcan2.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
        hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
        hfdcan2.Init.AutoRetransmission = ENABLE;
        hfdcan2.Init.TransmitPause = ENABLE;
        hfdcan2.Init.ProtocolException = ENABLE;
        hfdcan2.Init.NominalPrescaler = 1;
        hfdcan2.Init.NominalSyncJumpWidth = 32;
        hfdcan2.Init.NominalTimeSeg1 = 127;
        hfdcan2.Init.NominalTimeSeg2 = 32;
        hfdcan2.Init.DataPrescaler = 1;
        hfdcan2.Init.DataSyncJumpWidth = 4;
        hfdcan2.Init.DataTimeSeg1 = 15;
        hfdcan2.Init.DataTimeSeg2 = 4;
        hfdcan2.Init.StdFiltersNbr = 0;
        hfdcan2.Init.ExtFiltersNbr = 0;
        hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_QUEUE_OPERATION;
        if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK) {
            Error_Handler();
        }

        // Set TIM3 as source of the timestamp
        if (HAL_FDCAN_EnableTimestampCounter(&hfdcan2, FDCAN_TIMESTAMP_EXTERNAL) != HAL_OK) {
            Error_Handler();
        }

        /// @note Configure Tx delay compensation of the used transceiver for high speed data phase.
        ///   FDCAN automatically measures delay between falling edge on FDCAN_TX and FDCAN_RX.
        ///
        /// TdcOffset:
        ///   This is a value to be added to the measured delay. FDCAN measures delay between falling edges.
        ///   TdcOffset is added to the measured delay to get in the middle of the bit.
        ///   Documentation sucks. Nobody knows what minimal time quanta is. More info could be probably in CiA 601-2 which is paywalled.
        ///   Seems like minimal time quanta is the master CAN clock. Note that CAN2 doesn't have divider.
        ///
        ///   The value used was found experimentally for 1 & 8 Mbps and TJA1051/T3 transceiver.
        ///   Delay between FDCAN_TX and FDCAN_RX measured by logic analyzer is approximately 100 ns.
        ///   Values from 5 to 20 worked. At 160 MHz the length 20 * 6.25 ns = 125 ns or one bit.
        ///   Perhaps the offset needs to be between 25% and 100% of the bit length.
        ///   Of the working interval, 75% was used (80% of the bit); TdcOffset = 16.
        ///
        /// TdcFilter:
        ///   This is a minimal value for the measured delay. It prevents glitch on Rx to trigger too early.
        ///
        ///   The value used was found experimentally for 1 & 8 Mbps and TJA1051/T3 transceiver.
        ///   When the transceiver is working at correct speed, the value from PSR/TDCV register was read; TDCV = 30.
        ///   Of that value, 75% was used; TdcFilter = 22.
        if (HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan2, 16, 22) != HAL_OK) {
            Error_Handler();
        }
        if (HAL_FDCAN_EnableTxDelayCompensation(&hfdcan2) != HAL_OK) {
            Error_Handler();
        }

This is not ready to be a pull request. It will need different values at different speeds. Unfortunately, the documentation I have available is not good enough to have a proper solution. When I have Tag-Connect I may have a more deeper look into the firmware, but I cannot promise anything.

I guess that you are in process of merging the fork here, but any ideas on how or even if it should be incorporated into the firmware?

marckleinebudde commented 8 months ago

Hey @tomasjakubik,

I've cherry-picked and squashed @pgreenland's commit https://github.com/pgreenland/candleLight_fw/commit/4051608a60009072e7d2644a57f0802db70a135b into my https://github.com/marckleinebudde/candleLight_fw/tree/multichannel branch. Can you test, if this fixes your problem?

Cc: @lichtfeind

tomasjakubik commented 8 months ago

Hi, thanks. Now I can communicate at full 8 Mbps.

I missed that post on ST forum. Good idea to use DataTimeSeg1*DataPrescaler as the TdcOffset value. It should fit no matter the settings.

tomasjakubik commented 8 months ago

Maybe I spoke too soon. I think it can get stuck.

There is nothing wrong on the bus. Other devices communicate without issues. Rx and Tx LEDs do not blink. When trying to manually send something, cansend says write: No buffer space available. Nothing in dmesg. It starts working again when unplugged and replugged again. I have seen it several times and not once with firmware the candleLight FD had from factory.