6 years ago.

Help needed to test CANnucleo

Hi guys,

Since I've only NUCLEO-F103RB available, can someone help test/debug or share experience with the new CANnucleo library on other NUCLEO boards equipped with CAN interface: NUCLEO-F072RB, NUCLEO-F091RC, NUCLEO-F302R8, NUCLEO-F303RE, NUCLEO-F334R8, DISCO-F334C8? See also Example: CAN_Nucleo_Hello. Any contribution is welcome and appreciated.



Question relating to:

Controller Area Network library for NUCLEO boards equipped with CAN peripheral. CAN, can bus, CAN Nucleo, canbus, CANbus Nucleo, Controller Area Network, Nucleo

I have tried to use the CANnucleo with NUCLEO-F072RB . However I get about 30 errors when I attempt to compile. 9 are within the CAN.h and the rest are in the CAN.ccp. I am very new to coding so can't offer much debugging help.

Errors in CAN.h: Expected either a definition or a tag name "class CAN' Line:133, Col:8 multiple errors on line:174 and 175

Errors in CAN.cpp line 32, 35, 36, 37, 45, 46, 48, 56 & 57

I'm happy to provide more detail of errors if needed.

posted by Paul Wright 03 Aug 2015

Thank you Paul for your feedback. I've tried to compile the library also for the other NUCLEO boards but with no success. Seems I'm able to make it work only with NUCLEO-F103RB. So I give up and update the library accordingly.

posted by Zoltan Hudak 04 Aug 2015

I am working on implementing can_api.c for nucleo-F091RC.

The STM32 library defines "CAN" in stm32f091xc.h: #define CAN ((CAN_TypeDef *) CAN_BASE)

I renamed the class CAN to Can and it fixed the issue of "Expected either a definition or a tag name"

You can get a bare bones implementation to compile by doing the following: add to device.h: #define DEVICE_CAN 1 add to objects.h:

struct can_s {
    CAN_HandleTypeDef *hcan;
    int index;

create can_api.c and implement bare minimum functions for everything in can_api.h

I am trying to get the code I have used from STM32CubeMX to complete the api functions.

posted by Paul Paterson 13 Dec 2015

I imported CAN_Nucleo_Hello program. Compiled without any changes! It is getting hung up somewhere though. It does not appear as though anything is happening after the first message is sent.

I tried for a really long time to get my board to read with interrupts, and ended up settling for polling. I have no problems with interrupt read with the CubeMX code compiled on Keil uVision5, though. Perhaps there is a conflict with the mbed interrupt settings? I am not familiar with either STM32 HAL, or performing the reads manually to understand if there would be an issue.

posted by Paul Paterson 04 Jan 2016

1 Answer

5 years, 7 months ago.

I forked mbed-src to add can_api.c, still a big work in progress (missing some implementations like can_reset!), but I got communication up tonight!

Your library as it is requires a number of changes to the mbed API. The only made some minor changes other than adding can_api.c.

I did add a check for null in CAN.cpp, but this would be okay anyway.

void Can::_irq_handler(uint32_t id, CanIrqType type) {
    Can *handler = (Can*)id;
    if  (handler->_irq[type] != NULL)

edited device.h to get the CAN.h stuff included.

edited objects.h to add a can_s object. This points to CAN_HandleTypeDef that get's passed around from the Can class. I think it is important to use the obj parameter. Some STM32 chips have multiple CAN devices, and they are separated by having two different Can classes. If you use a global handle, then I think it will get messy if you try to extend it.

The change from class CAN to class Can has larger repercussions i suppose, too. But the other option is to have STM32 change THEIR library, but that seems silly. I am not sure how else to work any macro magic around this issue.

I used the STM32 HAL and that got us going pretty quickly. It is clear that this library is built to work directly on the peripherals though. I'm still getting a handle on how the HAL does it, but my understanding is that there are shortcomings (like the interrupt receive bug you got fixed) that might benefit from extracting some of the HAL code out and edit the device more directly.

So I tried to eliminate as many global/file scope variables as possible. Still have the PinName vars to carry over the initialization, haven't figured that one out. But putting everything (i.e. the ISRs) inside of can_api helped.

The way I am trying to do this is still have a can.attach to get the application ISR routines added. So right now, if the application adds a rx function, then the HAL_CAN_RxCpltCallback will try to call it. If one was never attached, this is why I needed to add the null check in the Can class.

Other than that, we have different styles, but you did some excellent work!


On the CAN/Can naming issue - can you work around it by doing a #undefine CAN in your files after all the ST files have been included?

posted by Andy A 14 Dec 2015

I reverted CAN.h, CAN.cpp to the main branch source. Then added only the #undef CAN in CAN.h above #include "can_api.h". I was using the CAN definition, but expanded it to ((CAN_TypeDef *) CAN_BASE) to no longer rely on the define.

Code is compiling. I believe this should be okay, but I don't know what if any larger repercussions it my have.

Also, after reviewing FunctionPointer more, I see it should be safe to attempt .Call() even if no user functions have been attached. I did not include the null check again, as it get's performed inside of the FunctionPointer class.

Thanks Andy!

posted by Paul Paterson 14 Dec 2015

Thank you Paul for embarking on this. Your work sounds very promising. I think also the trick with #undef CAN suggested by Andy will come in handy.

posted by Zoltan Hudak 14 Dec 2015