BERGSONNE

USB

Plug a Core into a computer and it shows up as a serial port — no drivers, no crystal. core_usb is a USB CDC device with printf and buffered RX, plus a vendor HID path for raw 64-byte reports. It sits on hal_usb_cdc. Use the Core / HAL / LL toggle at the top of the sidebar to switch.

Overview

USB device is available on the Cores with a USB peripheral — Core.ST.L4 and Core.ST.H5. It runs crystal-less: the HSI48 oscillator plus the Clock Recovery System (synced to USB SOF) keeps the clock USB-accurate, so no external part is needed.

CDC appears as a COM port
On the host it’s a virtual serial device (/dev/tty.usbmodem*, a COM port on Windows) — no driver install on modern OSes. The same port is what make flash-dfu touches at 1200 baud to enter the bootloader.

CDC serial

Init once, then write like any serial port. core_usb_connected() tells you the host has actually opened the port (so you don’t spew into the void):

#include "core.h"   // Core.ST.L4 / H5

core_usb_init();

while (1) {
    if (core_usb_connected()) {
        core_usb_printf("adc=%u ticks=%lu\r\n", raw, core_millis());
    }
    core_delay_ms(500);
}

Receiving

Two RX modes. Poll a background ring buffer, or register a callback that fires from the USB interrupt as bytes arrive (when set, data isn’t buffered for polling):

// Polling:
while (core_usb_available()) {
    uint8_t b = core_usb_getc();
}

// Or callback-driven:
static void on_rx(const uint8_t *data, uint16_t len, void *ctx) { /* ... */ }
core_usb_on_receive(on_rx, NULL);

HID reports

Alongside CDC, the device exposes a vendor HID interface for raw 64-byte reports — handy for a custom host tool (via hidapi / pyusb) with no OS driver. It’s TX-only today:

uint8_t report[8] = { 0x01, 0x02, 0x03, 0x04 };
core_usb_hid_send(report, sizeof(report));   // zero-padded to 64 bytes

Cross-architecture support

CDC serial is the verified path on the USB-capable Cores; HID rides the same stack. MSC and USB host are not implemented. (The ROM DFU bootloader is covered in bootloading.)

·L0M0+L4M4·W5M33H5M33WCH (RISC-V) · Nordic (nRF54) — in development
·L0M0+L4M4·W5M33H5M33WCH (RISC-V) · Nordic (nRF54) — in development

See the implementation status for the full matrix.

API reference

Default-instance · Tier 2
void core_usb_print(const char * s);
Print a string followed by a newline. Thin wrapper for DSL-style callers.
void core_usb_print_int(int v);
Print a signed integer followed by a newline.
void core_usb_print_float(double v);
Print a double with a newline. %g trims trailing zeros for readability.
void core_usb_print_bool(int v);
Print "true" / "false" followed by a newline.
Lower-level · Tier 1
void core_usb_init(void);
Initialize USB CDC. Device appears as /dev/tty.usbmodem* on the host.
int core_usb_connected(void);
Returns 1 if a host terminal is connected (DTR set).
int core_usb_write(const uint8_t * buf, uint16_t len);
Transmit data (blocking). Returns bytes sent, or -1 if not configured.
void core_usb_on_receive(hal_usb_cdc_rx_cb_t cb, void * ctx);
Set a callback for received data. Called from USB ISR. When set, data is NOT buffered for polling reads.
uint16_t core_usb_available(void);
Returns the number of bytes available to read (ring buffer mode).
uint8_t core_usb_getc(void);
Read a single byte (blocking — waits for data).
uint16_t core_usb_read(uint8_t * buf, uint16_t max);
Read available bytes into buf (non-blocking). Returns bytes read.
int core_usb_try_read(uint8_t * byte);
Non-blocking single byte read. Returns 1 if a byte was read, 0 if empty.

Generated from core_usb.htiles@5d70049.