UAVCAN V0 on CAN3 peripheral, STM32F7

I am working on an existing project that uses UAVCAN V0 Libcanard on an STM32F7. My understanding is that this microcontroller has three CAN outputs. CAN1 and 2 are multiplexed on the same hardware, and CAN3 has its own hardware inside the chip. I’d like to use CAN3 for sending/receiving UAVCAN messages.

In the drivers folder on the Libuavcan git repo, the canard_stm32.c and .h files and the _internal_bxcan.h file appear to only contain code for using CAN1 and CAN2. Does any code exist for setting up and using CAN3?

I am not aware of any but you better search through GitHub to be sure. If you don’t find anything relevant there, you will need to modify the driver yourself to add support for CAN3.

Unfortunately I don’t see anything pre-existing on git.

To the _internal_bxcan.h file I added:
#define CANARD_STM32_CAN3 ((volatile CanardSTM32CANType*)0x40003400U) //Memory location of CAN3 config register from stm32f767xx.h.

I added another build config macro to canard_stm32.h for using CAN3 and set it to 1. The build config macros for CAN1 and 2 are set to zero.

I adjusted the #defines at the top of canard_stm32.c to look like this:
#if CANARD_STM32_USE_CAN3
#define BXCAN CANARD_STM32_CAN3
#elif CANARD_STM32_USE_CAN2
#define BXCAN CANARD_STM32_CAN2
#elif CANARD_STM32_USE_CAN1
#define BXCAN CANARD_STM32_CAN1
#endif

However, the canardSTM32Init function errors out at the first instance of: if(!waitMSRINAKBitStateChange(BXCAN, true))

It appears the value of the MCR register at this point is incorrect. I expect MCR to end in 01 (not sleep mode, request init), but instead it ends in 10 (sleep mode, not requesting init). The lines immediately preceeding the if statement are:
BXCAN->MCR &= ~CANARD_STM32_CAN_MCR_SLEEP; // Exit sleep mode
BXCAN->MCR |= CANARD_STM32_CAN_MCR_INRQ; // Request init

I expect these lines to change the last two bits of MCR from 10 to 01, but these lines have no effect on the value of MCR. Any thoughts on why this might be? I don’t think the MCR register is locked somehow.

Make sure you enabled the clock for the bxCAN macrocell. Depending on its configuration, you may also need to initialize CAN1 and/or CAN2, because in other STM32’s CAN2 cannot be initialized unless CAN1 is also active. Be sure to also set up the GPIO AF registers properly otherwise you will be getting INAK timeouts during initialization, although right now this is less relevant. If you posted your code here somebody might be able to help.

Ah, once I enabled the CAN3 timer it works great! Thanks for your advice.

Is there any interest in adding support for CAN3 to the code on the UAVCANv0 git repo? (I know v0 is legacy, and perhaps not being updated anymore.) I’m happy to contribute my code.

Sure. It would be even better to port your code to the new bxCAN driver in the v1 branch.

Thanks.

Is this done via pull request?

Yes.