1 CAN FD
1.1 MCU with CAN FD
GD32C103: USART upgrade
STM32G0B1: RM0444, DS13560, AN5096, USART1 (PA9, PA10) and DFU (PA11, PA12)
STM32G431: RM0440, DS12589, AN5093, USART1 (PA9, PA10) and DFU (PA11, PA12)
Refer to AN2606 to get what STM32 devices support DFU bootloader.
NUCLEO-G431RB评估板上的唯一一个USB接口不是连接到STM32G431的,而是给ST-Link用的。
Discovery开发板一般有2个USB接口,一个是ST-Link,另外一个是USB通信口。
1.2 FD Format bit
STM32G0x1 R1.FDF: Receive Register 1, FD Format bit; if this bit is set, a CAN FD frame was received, otherwise, a CAN 2.0 frame was received.
1.3 gcc
github kylesrm / stm32g431-nucleo-makefile
cp lib/HAL/Inc/stm32g4xx_hal_conf_template.h src/stm32g4xx_hal_conf.h
1.4 schematics
github lijinlong21549 / STM32G474_board
1.5 CAN FD bus transceiver
TJA1042
2 PCAN FD
moonglow / pcan_pro_x
USB_EP_MSGOUT:
struct ucan_tx_msg {
uint16_t size;
uint16_t type;
uint32_t tag_low;
uint32_t tag_high;
uint8_t channel_dlc;
uint8_t client;
uint16_t flags;
uint32_t can_id;
uint8_t d[];
}attribute((packed));
USB_EP_MSGIN:
struct ucan_rx_msg {
// size 整个结构体的长度
uint16_t size;
uint16_t type;
// unit: us
uint32_t ts_low;
// ts_high = 0
uint32_t ts_high;
// tag_low = 0
uint32_t tag_low;
// tag_high = 0
uint32_t tag_high;
// high 4-bit is DLC,
// low 4-bit is CAN instance ID, 0 or 1
uint8_t channel_dlc;
uint8_t client;
uint16_t flags;
uint32_t can_id;
uint8_t d[];
}attribute((packed));
struct ucan_command {
// low 12-bit means opcode
// high 4-bit means CAN instance ID
uint16_t opcode_channel;
uint16_t args[3];
}attribute((packed));
static const uint8_t pcan_fd_len2dlc[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
9, 9, 9, 9, /* 9 - 12 */
10, 10, 10, 10, /* 13 - 16 */
11, 11, 11, 11, /* 17 - 20 */
12, 12, 12, 12, /* 21 - 24 */
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
15, 15, 15, 15, 15, 15, 15, 15 /* 57 - 64 */
};
static const uint8_t pcan_fd_dlc2len[] =
{
0, 1, 2, 3, 4, 5, 6, 7,
8, 12, 16, 20, 24, 32, 48, 64
};
3 STM32F072 Porting
3.1 Porting
moonglow / pcan_pro_x
Src/pcanpro_fd_protocol.c
Src/pcanpro_timestamp.c
Src/pcanfd_ucan.h
Src/pcanfd_usb_fw.h
Src/pcanpro_can.h
Src/pcan_usbpro_fw.h
Src/pcanpro_protocol.h
Src/pcanpro_timestamp.h
Add include "pcan_fd/pcanpro_fd_protocol.c" to Src/pcan_usb.c.
3.2 Debug
- Windows PCAN-View
When PCAN-View starts, it will send the below commands.
01: UCAN_CMD_RESET_MODE
80: UCAN_USB_CMD_CLK_SET - PCAN-View Clock Frequency, 20 MHz
04: UCAN_CMD_TIMING_SLOW - PCAN-View Nominal Bit rate, 500 kBit/s, STM32G4 FDCAN_NBTP
05: UCAN_CMD_TIMING_FAST - PCAN-View Data Bit rate, 2 MBit/s, STM32G4 FDCAN_DBTP
02: UCAN_CMD_NORMAL_MODE - bus active
0c: UCAN_CMD_CLR_DIS_OPTION
0b: UCAN_CMD_SET_EN_OPTION
3ff: UCAN_CMD_END_OF_COLLECTION
每一个High-speed USB_EP_CMDOUT MPL(Max Packet Length)可以包含多个8字节命令(Aggregation mode),但是实际上只有第一个8字节是命令,跟在8个字节后面的是8个FF,表示命令集合结束。8个FF后面的数据是无效数据,是Windows PCAN FD驱动没有清零导致的传给PCAN FD下位机的误导数据。下一个High-speed MPL报文重复该模式。
- Busload packet
PCAN FD sends 16-byte UCAN_MSG_BUSLOAD (10 00 04 00) to Windows PC periodically through USB_EP_MSGIN when PCAN-View starts. We can append debug messages to UCAN_MSG_BUSLOAD (10 00 ff ff 00 00 00 00 00 00 00 00 xx xx xx xx). Then use Bus Hound to catch the packets.
- Full-speed USB
PCAN-USB: VID_0C72&PID_000C
PCAN-USB FD: VID_0C72&PID_0012
需要修改bRequest = USB_VENDOR_REQUEST_INFO的返回值,否则Windows会发送wValue = 0的SET_CONFIG,进而导致Windows PCAN-View不工作。修改点是pcan_device.device_nr = 0,pcan_device.can[0].channel_nr = 0。
USB_EP_CMDOUT buffer size: 128-byte, otherwise STM32 Full-speed USB cannot receive UCAN_CMD_NORMAL_MODE.
USB_EP_MSGOUT buffer size: 256-byte
USB_EP_MSGIN_CH1: UCAN_USB_MSG_CALIBRATION = 0x100
当USB是Full-speed时,此时Max Packet Length是64字节,Windows PCAN-View USB_EP_MSGIN的buffer size是4096字节,因为函数pcan_protocol_poll中每次都发送64字节,没有Zero Length Packet或者Short Packet,这个导致Windows的URB无法退出,一直等待设备发送了4096字节才退出URB。需要修改该处的代码,使每次发送字节数不要是Max Packet Length的整数倍。
- Bit timing
STM32F072 CANbps = APB_clock / BRP / (tseg1 + tseg2 + 1)
需要调用函数_get_precalculated_bitrate将PCAN-View要设置的低速500 kBit/s换算成STM32F072的寄存器值,寄存器名字是CAN_BTR,地址是0x4000_641C,每个写进去的字段需要减去1。
从函数SystemClock_Config中找出APB1 bxCAN的时钟信息,APB1的时钟是48 MHz。
- Timer
使用2个16-bit定时器实现us定时,TIM3.CNT存储us的低16-bit,TIM9.CNT存储us的高16-bit,设置TIM3的PSC到(48 - 1),即是对48 MHz APB1进行48分频,所以每一个bit即是1us,设置TIM9的PSC到(1 - 1),即是对TIM3.CNT的溢出计数不分频,故而TIM9.CNT存储的是us的高16-bit。
可以直接使用32-bit TIM2,将PSC设置为(48-1),并且时钟分频的值为0后,每个bit就代表1uS。
- LED
PCAN FD双通道需要5个LED。