Here’s the original code: https://github.com/Phonog/Arduino_STM32 … areCAN/src
I’ve added RCC_CAN into rccF4.h/rccF4.c
[RCC_CAN] = { .clk_domain = APB1, .line_num = 25 },and also changed NVIC namings so it compiles OK. Also AFIO RCC is not used in F4.
Currently the problem is that CAN goes into init mode but does not leave it and it timeouts. Init is performed in can_init function.
From reference:
Once the initialization is complete, the software must request the hardware to enter Normal
mode to be able to synchronize on the CAN bus and start reception and transmission.
The request to enter Normal mode is issued by clearing the INRQ bit in the CAN_MCR
register. The bxCAN enters Normal mode and is ready to take part in bus activities when it
has synchronized with the data transfer on the CAN bus. This is done by waiting for the
occurrence of a sequence of 11 consecutive recessive bits (Bus Idle state). The switch to
Normal mode is confirmed by the hardware by clearing the INAK bit in the CAN_MSR
register.
I have a small test bench CAN network with 2 devices terminated with 120ohm resistors. First one is USBTin CAN-BUS adapter and the other is “mini blue board” aka VCC_GND_F407. I tested with micropython that can driver works and USBTin receives messages from F4 and shows them in the viewer program so CAN BUS is proven to work and CAN hardware in F4 is working.
python code:
from pyb import CAN
import time
#250kBit, F4, PB8 (RX), PB9 (TX)
can = CAN(1, CAN.NORMAL, extframe=False, prescaler=12, sjw=1, bs1=11, bs2=2)
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126
while True:
print("sending...")
can.send(b'00000000', 1) # send a message with id 123
time.sleep(.005)
print(can.info())
Eventually you could try to activate the pull-up for the Rx pin.
Be sure that the RCC_CAN1/2 entries in rccF4.h/c have the same position in the respective lists.
Some hints what to check: https://stackoverflow.com/a/13821030
Maybe try Loopback mode?
Have you cleared the INRQ bit?
I would check in my program the status of CAN_MSR/MCR registers after each step I take.
[michael_l – Sat Sep 08, 2018 1:27 pm] –
The bxCAN enters Normal mode and is ready to take part in bus activities when it
has synchronized with the data transfer on the CAN bus. This is done by waiting for the
occurrence of a sequence of 11 consecutive recessive bits (Bus Idle state).
It is not clear to me where those recessive bits should come from, from the other connected device?
Or they are generated by the HW when sending some data?
So try to send some data right after you enter normal mode (by clearing INRQ it), and check the status of the MSR/MCR registers.
Could you maybe share your development on github so that I can check your current code?
You can remove all USB and AFIO related stuff from the code made by Phonog.
I am not sure where and how, but you have to assign parts of the code to these interrupts: __irq_can1_tx, __irq_can1_rx0, (__irq_can1_rx1 maybe optional). Associated NVIC_CAN1_TX, NVIC_CAN1_RX0, NVIC_CAN1_RX1 should be also used in nvic_irq_… functions.
Ok, I got leaving init mode working by changing this:
gpio_set_mode(PD0, GPIO_INPUT_FLOATING); –> gpio_set_mode(PD0, GPIO_AF_INPUT);
I didn’t understand this was needed.
RCC_APB1RSTR at bit 25 is for CAN1. I use only CAN1 module here. Also the same bit 25 for RCC_APB1ENR.
Sending messages still fail… so that is strange. Guess I’ll have to start debugging it. Recessive bits are read from the bus
LOOPBACK mode will halt the program so I haven’t tried it that much.
Yes, I’ll put the code in github, but later. Attached is the .zip file. It contains some hardcoded stuff though, like using PD0/PD1 for pins. I’ve used HardwareCANexample.ino for testing and modified it with Serial prints
1. the baud rate configuration for 500kbit was wrong
2. I had to disable CAN interrupts or it would fault the MCU <– this is something to fix next
When I enable this interrupt nvic_irq_enable(NVIC_CAN1_TX);
Maybe an
extern “C” void __irq_can_tx(void)
…
}
helps?
Also, you can check with the debugger the interrupt vector address for that IRQ.
A MAP file viewer can also help sometimes: http://www.sikorskiy.net/prj/amap/
correct function name is: __irq_can1_tx and I am using __irq_can_tx .
That’s why the handler was never called…
I’ll try this tonight. Basically interrupts are not needed here but this library has been built so that it stores messages in internal buffer so I’ll leave it as it is. Maybe I’ll add some diagnostic functions to find out the state of the controller and various error counters.
Keep us informed!
I’ve tested all baud rates, also added an error stats function. Two examples for normal mode and loopback.
I will add it to my repo as a library, if you have nothing against.
[stevestrong – Wed Sep 12, 2018 12:58 pm] –
@michael_i, nice job, than you.
I will add it to my repo as a library, if you have nothing against.
Sure, by all means !


