PCAN FD

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

  1. 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报文重复该模式。

  1. 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.

  1. 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的整数倍。

  1. 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。

  1. 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。

  1. LED

PCAN FD双通道需要5个LED。