Skip to content

Commit

Permalink
usb: device: gs_usb: make capturing hardware timestamp on sof optional
Browse files Browse the repository at this point in the history
Make the capturing of hardware timestamps on USB Start of Frame (SoF)
events optional and disable it by default.

Capturing the hardware timestamp on SoF improves the accuracy of the time
synchronization between the USB host and the device (in the range of ~110
to 20 microseconds depending on the board according to my measurements),
but comes with a cost of much higher CPU load.

This does not affect the relative timestamping of CAN RX/TX frames, only
their absolute timestamp as compared to the USB host time.

Signed-off-by: Henrik Brix Andersen <[email protected]>
  • Loading branch information
henrikbrixandersen committed Sep 4, 2024
1 parent 4ca426d commit 92db3f3
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 11 deletions.
14 changes: 14 additions & 0 deletions app/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ tests:
- frdm_k64f
- lpcxpresso55s16
- nucleo_h723zg
app.cannectivity.sof:
depends_on: usb_device can
integration_platforms:
- nucleo_h723zg
extra_configs:
- CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF=y
app.cannectivity.release:
depends_on: usb_device can
extra_args:
Expand All @@ -31,6 +37,14 @@ tests:
integration_platforms:
- frdm_k64f
- lpcxpresso55s16
app.cannectivity.usbd_next.sof:
depends_on: usbd can
extra_args:
- FILE_SUFFIX=usbd_next
integration_platforms:
- lpcxpresso55s16
extra_configs:
- CONFIG_USBD_GS_USB_TIMESTAMP_SOF=y
app.cannectivity.usbd_next.release:
depends_on: usbd can
extra_args:
Expand Down
9 changes: 8 additions & 1 deletion subsys/usb/device/class/Kconfig.gs_usb
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,17 @@ config USB_DEVICE_GS_USB_IDENTIFICATION

config USB_DEVICE_GS_USB_TIMESTAMP
bool "Enable support for hardware timestamps"
imply USB_DEVICE_SOF
help
Enable support for hardware timestamps provided by the application.

config USB_DEVICE_GS_USB_TIMESTAMP_SOF
bool "Capture hardware timestamp on USB SoF"
depends on USB_DEVICE_GS_USB_TIMESTAMP
select USB_DEVICE_SOF
help
Capture the hardware timestamp on each USB Start of Frame event. This improves the
timestamp accurracy with the cost of a higher CPU load.

config USB_DEVICE_GS_USB_TERMINATION
bool "Enable support for CAN bus termination resistors"
help
Expand Down
12 changes: 8 additions & 4 deletions subsys/usb/device/class/gs_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ struct gs_usb_data {
void *user_data;
struct net_buf_pool *pool;

#ifdef CONFIG_USB_DEVICE_GS_USB_TIMESTAMP
#ifdef CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF
uint32_t timestamp;
bool sof_seen;
#endif /* CONFIG_USB_DEVICE_GS_USB_TIMESTAMP */
#endif /* CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF */

struct k_fifo rx_fifo;
struct k_thread rx_thread;
Expand Down Expand Up @@ -648,17 +648,21 @@ static int gs_usb_request_timestamp(const struct device *dev, int32_t *tlen, uin
return -ENOTSUP;
}

#ifdef CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF
if (data->sof_seen) {
timestamp = data->timestamp;
data->sof_seen = false;
} else {
#endif /* CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF */
err = data->ops.timestamp(dev, &timestamp, data->user_data);
if (err != 0) {
LOG_ERR("failed to get current timestamp (err %d)", err);
return err;
}
#ifdef CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF
LOG_WRN_ONCE("USB SoF event not supported, timestamp will be less accurate");
}
#endif /* CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF */

LOG_DBG("timestamp: 0x%08x", timestamp);

Expand Down Expand Up @@ -1370,7 +1374,7 @@ static void gs_usb_status_callback(struct usb_cfg_data *cfg, enum usb_dc_status_
LOG_DBG("USB device clear halt");
break;
case USB_DC_SOF:
#ifdef CONFIG_USB_DEVICE_GS_USB_TIMESTAMP
#ifdef CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF
int err;

if (data->ops.timestamp != NULL) {
Expand All @@ -1383,7 +1387,7 @@ static void gs_usb_status_callback(struct usb_cfg_data *cfg, enum usb_dc_status_
/* Not all USB device controller drivers support SoF events */
data->sof_seen = true;
}
#endif /* CONFIG_USB_DEVICE_GS_USB_TIMESTAMP */
#endif /* CONFIG_USB_DEVICE_GS_USB_TIMESTAMP_SOF */
break;
case USB_DC_UNKNOWN:
__fallthrough;
Expand Down
7 changes: 7 additions & 0 deletions subsys/usb/device_next/class/Kconfig.gs_usb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ config USBD_GS_USB_TIMESTAMP
help
Enable support for hardware timestamps provided by the application.

config USBD_GS_USB_TIMESTAMP_SOF
bool "Capture hardware timestamp on USB SoF"
depends on USBD_GS_USB_TIMESTAMP
help
Capture the hardware timestamp on each USB Start of Frame event. This improves the
timestamp accurracy with the cost of a higher CPU load.

config USBD_GS_USB_TERMINATION
bool "Enable support for CAN bus termination resistors"
help
Expand Down
16 changes: 10 additions & 6 deletions subsys/usb/device_next/class/gs_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ struct gs_usb_data {
struct net_buf_pool *pool;

atomic_t state;
#ifdef CONFIG_USBD_GS_USB_TIMESTAMP
#ifdef CONFIG_USBD_GS_USB_TIMESTAMP_SOF
uint32_t timestamp;
bool sof_seen;
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP */
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP_SOF */

struct k_sem in_sem;
struct k_fifo rx_fifo;
Expand Down Expand Up @@ -638,7 +638,7 @@ static int gs_usb_request_device_config(const struct device *dev, struct net_buf
return 0;
}

#ifdef CONFIG_USBD_GS_USB_TIMESTAMP
#ifdef CONFIG_USBD_GS_USB_TIMESTAMP_SOF
static void gs_usb_sof(struct usbd_class_data *const c_data)
{
const struct device *dev = usbd_class_get_private(c_data);
Expand All @@ -658,7 +658,7 @@ static void gs_usb_sof(struct usbd_class_data *const c_data)
/* Not all USB device controller drivers support SoF events */
data->sof_seen = true;
}
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP */
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP_SOF */

static int gs_usb_request_timestamp(const struct device *dev, struct net_buf *buf)
{
Expand All @@ -672,17 +672,21 @@ static int gs_usb_request_timestamp(const struct device *dev, struct net_buf *bu
return -ENOTSUP;
}

#ifdef CONFIG_USBD_GS_USB_TIMESTAMP_SOF
if (data->sof_seen) {
timestamp = data->timestamp;
data->sof_seen = false;
} else {
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP_SOF */
err = data->ops.timestamp(dev, &timestamp, data->user_data);
if (err != 0) {
LOG_ERR("failed to get current timestamp (err %d)", err);
return err;
}
#ifdef CONFIG_USBD_GS_USB_TIMESTAMP_SOF
LOG_WRN_ONCE("USB SoF event not supported, timestamp will be less accurate");
}
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP_SOF */

LOG_DBG("timestamp: 0x%08x", timestamp);
net_buf_add_le32(buf, timestamp);
Expand Down Expand Up @@ -1558,9 +1562,9 @@ struct usbd_class_api gs_usb_api = {
.control_to_dev = gs_usb_control_to_dev,
.control_to_host = gs_usb_control_to_host,
.request = gs_usb_request,
#ifdef CONFIG_USBD_GS_USB_TIMESTAMP
#ifdef CONFIG_USBD_GS_USB_TIMESTAMP_SOF
.sof = gs_usb_sof,
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP */
#endif /* CONFIG_USBD_GS_USB_TIMESTAMP_SOF */
.enable = gs_usb_enable,
.disable = gs_usb_disable,
.get_desc = gs_usb_get_desc,
Expand Down

0 comments on commit 92db3f3

Please sign in to comment.