Skip to content

Commit 4d9223c

Browse files
committed
gs_usb: CAN-FD support
Enable CAN-FD frame handling through the gs_usb (candlelight/SocketCAN) interface, controlled by the host via GS_CAN_MODE_FD flag: - Add GS_CAN_FLAG_FD/BRS/ESI frame flag defines per gs_usb protocol - Advertise GS_CAN_FEATURE_FD in device capabilities - Handle GS_CAN_MODE_FD in breq_set_mode to set enable_fdcan - Update RAMN_GSUSB_ProcessRX to accept FD frames with FD/BRS/ESI flags - Update RAMN_GSUSB_ProcessTX to set FD/BRS flags on TX echo frames - Update RAMN_RxTask2Func TX path to decode FD/BRS/ESI flags from host - Fix marshal/unmarshal to use FDCAN_ConvertToActual for data copy size (DLC codes 9-15 map to 12-64 bytes, not 9-15 bytes) - Remove "CAN-FD is not supported" from ramn_config.h limitations
1 parent b1d7c60 commit 4d9223c

6 files changed

Lines changed: 158 additions & 47 deletions

File tree

firmware/RAMNV1/Core/Inc/ramn_config.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,15 @@
4747

4848
// Enable this flag to enable the candlelight interface (gs_usb drivers)
4949
// Current implementation is experimental:
50-
// - CAN-FD is not supported
5150
// - Due to clock differences, bit timings are not respected (but equivalent baudrates are used)
5251
// Try increasing _Min_Stack_Size if you run into issues
5352
//#define ENABLE_GSUSB
5453

54+
// Enable this flag to enable CAN-FD support in the gs_usb interface.
55+
// When enabled, FD frames (up to 64 bytes) with BRS and ESI flags are supported.
56+
// Requires ENABLE_GSUSB to be defined.
57+
//#define ENABLE_GSUSB_CANFD
58+
5559
#ifndef ENABLE_GSUSB
5660
#define USBD_VID 0x483
5761
#define USBD_PID 0x5740
@@ -399,6 +403,10 @@
399403
#error Cannot activate GSUSB without enabling USB
400404
#endif
401405

406+
#if defined(ENABLE_GSUSB_CANFD) && !defined(ENABLE_GSUSB)
407+
#error Cannot activate GSUSB_CANFD without enabling GSUSB
408+
#endif
409+
402410
#if defined(ENABLE_USB) && !defined(ENABLE_CDC) && !defined(ENABLE_GSUSB)
403411
#error At least one USB interface must be active if you enable USB
404412
#endif

firmware/RAMNV1/Core/Src/main.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,10 +2293,7 @@ void RAMN_RxTask2Func(void *argument)
22932293
else
22942294
{
22952295

2296-
// TODO implement CAN-FD
2297-
22982296
//recvFrame->echo_id
2299-
//recvFrame.flags
23002297
//recvFrame.reserved
23012298

23022299

@@ -2308,9 +2305,20 @@ void RAMN_RxTask2Func(void *argument)
23082305
if (recvFrame->can_id & CAN_EFF_FLAG) CANTxHeader.IdType = FDCAN_EXTENDED_ID;
23092306
else CANTxHeader.IdType = FDCAN_STANDARD_ID;
23102307

2311-
CANTxHeader.BitRateSwitch = FDCAN_BRS_OFF;
2312-
CANTxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
2313-
CANTxHeader.FDFormat = FDCAN_CLASSIC_CAN;
2308+
#ifdef ENABLE_GSUSB_CANFD
2309+
if (recvFrame->flags & GS_CAN_FLAG_FD)
2310+
{
2311+
CANTxHeader.FDFormat = FDCAN_FD_CAN;
2312+
CANTxHeader.BitRateSwitch = (recvFrame->flags & GS_CAN_FLAG_BRS) ? FDCAN_BRS_ON : FDCAN_BRS_OFF;
2313+
CANTxHeader.ErrorStateIndicator = (recvFrame->flags & GS_CAN_FLAG_ESI) ? FDCAN_ESI_PASSIVE : FDCAN_ESI_ACTIVE;
2314+
}
2315+
else
2316+
#endif
2317+
{
2318+
CANTxHeader.FDFormat = FDCAN_CLASSIC_CAN;
2319+
CANTxHeader.BitRateSwitch = FDCAN_BRS_OFF;
2320+
CANTxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
2321+
}
23142322
CANTxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
23152323

23162324
//CANTxHeader.MessageMarker = 0U;

firmware/RAMNV1/Core/Src/ramn_gsusb.c

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,6 @@ RAMN_Result_t RAMN_GSUSB_ProcessRX(FDCAN_RxHeaderTypeDef *canRxHeader, uint8_t *
3030
qret = xQueueReceive(RAMN_GSUSB_PoolQueueHandle, &frameData, portMAX_DELAY);
3131
if (qret == pdPASS)
3232
{
33-
// Does not support CAN FD yet
34-
if(canRxHeader->FDFormat == FDCAN_FD_CAN)
35-
{
36-
#ifdef HANG_ON_ERRORS
37-
Error_Handler();
38-
#endif
39-
return RAMN_ERROR;
40-
}
41-
4233
frameData->can_id = canRxHeader->Identifier;
4334
if (canRxHeader->IdType != FDCAN_STANDARD_ID) frameData->can_id |= CAN_EFF_FLAG;
4435
if (canRxHeader->RxFrameType != FDCAN_DATA_FRAME) frameData->can_id |= CAN_RTR_FLAG;
@@ -49,7 +40,20 @@ RAMN_Result_t RAMN_GSUSB_ProcessRX(FDCAN_RxHeaderTypeDef *canRxHeader, uint8_t *
4940
frameData->can_dlc = canRxHeader->DataLength;
5041
frameData->timestamp_us = (xTaskGetTickCount() * (1000000 /*us per sec*/ / configTICK_RATE_HZ) );
5142

52-
if (!(frameData->can_id & CAN_RTR_FLAG)) RAMN_memcpy(frameData->data, canRxData, frameData->can_dlc);
43+
#ifdef ENABLE_GSUSB_CANFD
44+
if (canRxHeader->FDFormat == FDCAN_FD_CAN)
45+
{
46+
frameData->flags |= GS_CAN_FLAG_FD;
47+
if (canRxHeader->BitRateSwitch == FDCAN_BRS_ON) frameData->flags |= GS_CAN_FLAG_BRS;
48+
if (canRxHeader->ErrorStateIndicator == FDCAN_ESI_PASSIVE) frameData->flags |= GS_CAN_FLAG_ESI;
49+
}
50+
#endif
51+
52+
if (!(frameData->can_id & CAN_RTR_FLAG))
53+
{
54+
uint8_t actual = FDCAN_ConvertToActual(frameData->can_dlc);
55+
RAMN_memcpy(frameData->data, canRxData, actual);
56+
}
5357

5458
// Send to task
5559
qret = xQueueSendToBack(RAMN_GSUSB_SendQueueHandle, &frameData, CAN_QUEUE_TIMEOUT);
@@ -75,21 +79,25 @@ RAMN_Result_t RAMN_GSUSB_ProcessTX(FDCAN_TxHeaderTypeDef *canTxHeader, uint8_t *
7579
qret = xQueueReceive(RAMN_GSUSB_PoolQueueHandle, &frameData, CAN_QUEUE_TIMEOUT);
7680
if (qret == pdPASS)
7781
{
78-
// Does not support CAN FD yet
79-
if(canTxHeader->FDFormat == FDCAN_FD_CAN)
80-
{
81-
#ifdef HANG_ON_ERRORS
82-
Error_Handler();
83-
#endif
84-
return RAMN_ERROR;
85-
}
86-
8782
frameData->can_id = canTxHeader->Identifier;
8883
frameData->echo_id = 0xFFFFFFFF;
8984
frameData->channel = 0;
85+
frameData->flags = 0;
9086
frameData->can_dlc = canTxHeader->DataLength;
9187
frameData->timestamp_us = 0; // timestamps are ignored on send
92-
RAMN_memcpy(frameData->data, canRxData, frameData->can_dlc);
88+
89+
#ifdef ENABLE_GSUSB_CANFD
90+
if (canTxHeader->FDFormat == FDCAN_FD_CAN)
91+
{
92+
frameData->flags |= GS_CAN_FLAG_FD;
93+
if (canTxHeader->BitRateSwitch == FDCAN_BRS_ON) frameData->flags |= GS_CAN_FLAG_BRS;
94+
}
95+
#endif
96+
97+
{
98+
uint8_t actual = FDCAN_ConvertToActual(frameData->can_dlc);
99+
RAMN_memcpy(frameData->data, canRxData, actual);
100+
}
93101

94102
// Send to task
95103
qret = xQueueSendToBack(RAMN_GSUSB_SendQueueHandle, &frameData, CAN_QUEUE_TIMEOUT);

firmware/RAMNV1/Middlewares/ST/STM32_USB_Device_Library/USBClass/Composite/gs_usb/gs_usb_breq.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ void breq_set_mode(USBD_GS_CAN_HandleTypeDef *hcan, USBD_SetupReqTypedef *req)
8383
}
8484
else if (mode->mode == GS_CAN_MODE_START)
8585
{
86+
#ifdef ENABLE_GSUSB_CANFD
87+
hcan->enable_fdcan = (mode->flags & GS_CAN_MODE_FD) != 0;
88+
#else
89+
hcan->enable_fdcan = 0;
90+
#endif
8691
FDCAN_InitQueues(hcan);
8792
hcan->timestamps_enabled = (mode->flags & GS_CAN_MODE_HW_TIMESTAMP) != 0;
8893
hcan->pad_pkts_to_max_pkt_size = (mode->flags & GS_CAN_MODE_PAD_PKTS_TO_MAX_PKT_SIZE) != 0;
@@ -121,6 +126,7 @@ void breq_set_bittiming(USBD_GS_CAN_HandleTypeDef *hcan, USBD_SetupReqTypedef *r
121126
*/
122127
void breq_set_data_bittiming(USBD_GS_CAN_HandleTypeDef *hcan, USBD_SetupReqTypedef *req)
123128
{
129+
#ifdef ENABLE_GSUSB_CANFD
124130
struct gs_device_bittiming *timing;
125131

126132
timing = (struct gs_device_bittiming *)hcan->ep0_buf;
@@ -133,6 +139,7 @@ void breq_set_data_bittiming(USBD_GS_CAN_HandleTypeDef *hcan, USBD_SetupReqTyped
133139
);
134140

135141
hcan->enable_fdcan = 1;
142+
#endif
136143
}
137144

138145
#endif

firmware/RAMNV1/Middlewares/ST/STM32_USB_Device_Library/USBClass/Composite/gs_usb/usbd_gs_usb.c

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ const struct gs_device_bt_const gscan_btconst = {
6464
| GS_CAN_FEATURE_HW_TIMESTAMP
6565
| GS_CAN_FEATURE_IDENTIFY
6666
| GS_CAN_FEATURE_USER_ID
67-
| GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE,
67+
| GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE
68+
#ifdef ENABLE_GSUSB_CANFD
69+
| GS_CAN_FEATURE_FD
70+
| GS_CAN_FEATURE_BT_CONST_EXT
71+
#endif
72+
,
6873
48000000, // can timing base clock
6974
1, // tseg1 min
7075
16, // tseg1 max
@@ -76,6 +81,36 @@ const struct gs_device_bt_const gscan_btconst = {
7681
1, // brp increment;
7782
};
7883

84+
#ifdef ENABLE_GSUSB_CANFD
85+
static const struct gs_device_bt_const_extended gscan_btconst_ext = {
86+
GS_CAN_FEATURE_LISTEN_ONLY // supported features
87+
| GS_CAN_FEATURE_LOOP_BACK
88+
| GS_CAN_FEATURE_HW_TIMESTAMP
89+
| GS_CAN_FEATURE_IDENTIFY
90+
| GS_CAN_FEATURE_USER_ID
91+
| GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE
92+
| GS_CAN_FEATURE_FD
93+
| GS_CAN_FEATURE_BT_CONST_EXT,
94+
48000000, // can timing base clock
95+
1, // tseg1 min
96+
16, // tseg1 max
97+
2, // tseg2 min
98+
8, // tseg2 max
99+
4, // sjw max
100+
1, // brp min
101+
512, // brp_max
102+
1, // brp increment
103+
1, // dtseg1 min
104+
16, // dtseg1 max
105+
2, // dtseg2 min
106+
8, // dtseg2 max
107+
4, // dsjw max
108+
1, // dbrp min
109+
512, // dbrp_max
110+
1, // dbrp increment
111+
};
112+
#endif
113+
79114

80115
/* Microsoft Compatible ID Feature Descriptor */
81116
static const uint8_t USBD_MS_COMP_ID_FEATURE_DESC[] = {
@@ -224,11 +259,15 @@ static uint8_t gsusb_config_request(USBD_HandleTypeDef *pdev, USBD_SetupReqTyped
224259
USBD_CtlPrepareRx(pdev, hcan->ep0_buf, req->wLength);
225260
break;
226261
case GS_USB_BREQ_DATA_BITTIMING:
227-
262+
#ifdef ENABLE_GSUSB_CANFD
228263
hcan->enable_fdcan = 1;
229264
hcan->last_setup_request = *req;
230265
USBD_CtlPrepareRx(pdev, hcan->ep0_buf, req->wLength);
231266
break;
267+
#else
268+
ret = USBD_FAIL;
269+
break;
270+
#endif
232271
case GS_USB_BREQ_DEVICE_CONFIG:
233272
RAMN_memcpy(hcan->ep0_buf, &gscan_dconf, sizeof(gscan_dconf));
234273
USBD_CtlSendData(pdev, hcan->ep0_buf, req->wLength);
@@ -239,6 +278,14 @@ static uint8_t gsusb_config_request(USBD_HandleTypeDef *pdev, USBD_SetupReqTyped
239278
USBD_CtlSendData(pdev, hcan->ep0_buf, req->wLength);
240279
break;
241280

281+
#ifdef ENABLE_GSUSB_CANFD
282+
case GS_USB_BREQ_BT_CONST_EXT:
283+
// Use USBD_DescBuf instead of ep0_buf: extended bt_const (72 bytes) exceeds ep0_buf (64 bytes)
284+
RAMN_memcpy(USBD_DescBuf, &gscan_btconst_ext, sizeof(gscan_btconst_ext));
285+
USBD_CtlSendData(pdev, USBD_DescBuf, MIN(sizeof(gscan_btconst_ext), req->wLength));
286+
break;
287+
#endif
288+
242289
case GS_USB_BREQ_TIMESTAMP:
243290
RAMN_memcpy(hcan->ep0_buf, &hcan->sof_timestamp_us, sizeof(hcan->sof_timestamp_us));
244291
USBD_CtlSendData(pdev, hcan->ep0_buf, sizeof(hcan->sof_timestamp_us));
@@ -412,16 +459,19 @@ void GSUSB_MarshalFrame(USBD_HandleTypeDef *pdev, struct gs_host_frame *in, uint
412459
out[ofs++] = in->channel;
413460
out[ofs++] = in->flags;
414461
out[ofs++] = in->reserved;
415-
RAMN_memcpy(&out[ofs], in->data, in->can_dlc);
416-
if(!hcan->enable_fdcan)
417462
{
418-
RAMN_memset(&out[ofs + in->can_dlc], 0x00, 8 - in->can_dlc);
419-
ofs += 8;
420-
}
421-
else
422-
{
423-
RAMN_memset(&out[ofs + in->can_dlc], 0x00, 64 - in->can_dlc);
424-
ofs += 64;
463+
uint8_t actual = FDCAN_ConvertToActual(in->can_dlc);
464+
RAMN_memcpy(&out[ofs], in->data, actual);
465+
if(!hcan->enable_fdcan)
466+
{
467+
RAMN_memset(&out[ofs + actual], 0x00, 8 - actual);
468+
ofs += 8;
469+
}
470+
else
471+
{
472+
RAMN_memset(&out[ofs + actual], 0x00, 64 - actual);
473+
ofs += 64;
474+
}
425475
}
426476

427477
if (hcan->timestamps_enabled)
@@ -446,16 +496,19 @@ void GSUSB_UnmarshalFrame(USBD_HandleTypeDef *pdev, uint8_t *in, uint16_t inlen,
446496
out->channel = in[ofs++];
447497
out->flags = in[ofs++];
448498
out->reserved = in[ofs++];
449-
RAMN_memcpy(out->data, &in[ofs], out->can_dlc);
450-
if(!hcan->enable_fdcan)
451-
{
452-
RAMN_memset(&out->data[out->can_dlc], 0x00, 8 - out->can_dlc);
453-
ofs += 8;
454-
}
455-
else
456499
{
457-
RAMN_memset(&out->data[out->can_dlc], 0x00, 64 - out->can_dlc);
458-
ofs += 64;
500+
uint8_t actual = FDCAN_ConvertToActual(out->can_dlc);
501+
RAMN_memcpy(out->data, &in[ofs], actual);
502+
if(!hcan->enable_fdcan)
503+
{
504+
RAMN_memset(&out->data[actual], 0x00, 8 - actual);
505+
ofs += 8;
506+
}
507+
else
508+
{
509+
RAMN_memset(&out->data[actual], 0x00, 64 - actual);
510+
ofs += 64;
511+
}
459512
}
460513

461514
if (hcan->timestamps_enabled)

firmware/RAMNV1/Middlewares/ST/STM32_USB_Device_Library/USBClass/Composite/gs_usb/usbd_gs_usb.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,12 @@ THE SOFTWARE.
6060

6161
#define GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE (1<<7)
6262
#define GS_CAN_FEATURE_FD (1<<8)
63+
#define GS_CAN_FEATURE_BT_CONST_EXT (1<<10)
6364

6465
#define GS_CAN_FLAG_OVERFLOW 1
66+
#define GS_CAN_FLAG_FD (1<<1)
67+
#define GS_CAN_FLAG_BRS (1<<2)
68+
#define GS_CAN_FLAG_ESI (1<<3)
6569

6670
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
6771
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
@@ -163,6 +167,8 @@ enum gs_usb_breq {
163167
GS_USB_BREQ_TIMESTAMP,
164168
GS_USB_BREQ_IDENTIFY,
165169
GS_USB_BREQ_DATA_BITTIMING,
170+
GS_USB_BREQ_GET_USER_ID, // not implemented, placeholder for correct enum numbering
171+
GS_USB_BREQ_BT_CONST_EXT,
166172
};
167173

168174
enum gs_can_mode {
@@ -231,6 +237,27 @@ struct __attribute__ ((__packed__)) gs_device_bt_const {
231237
uint32_t brp_inc;
232238
};
233239

240+
struct __attribute__ ((__packed__)) gs_device_bt_const_extended {
241+
uint32_t feature;
242+
uint32_t fclk_can;
243+
uint32_t tseg1_min;
244+
uint32_t tseg1_max;
245+
uint32_t tseg2_min;
246+
uint32_t tseg2_max;
247+
uint32_t sjw_max;
248+
uint32_t brp_min;
249+
uint32_t brp_max;
250+
uint32_t brp_inc;
251+
uint32_t dtseg1_min;
252+
uint32_t dtseg1_max;
253+
uint32_t dtseg2_min;
254+
uint32_t dtseg2_max;
255+
uint32_t dsjw_max;
256+
uint32_t dbrp_min;
257+
uint32_t dbrp_max;
258+
uint32_t dbrp_inc;
259+
};
260+
234261

235262
struct __attribute__ ((__packed__)) gs_host_frame {
236263
uint32_t echo_id;

0 commit comments

Comments
 (0)