Skip to main content

CANFD Functions

dev.io.canfd - wire path i\c - generated from fwMenuCANFD.

enable_canfd_stream

Stream CAN(FD). Streams received CAN frames and errors to the host.

Stream CAN(FD)

Enables or disables streaming of received CAN/CAN-FD frames and bus errors from the selected channel to the host.

Arguments
  • channel — CAN controller index
    • 0 — CAN channel 0 (obCANFD1)
    • 1 — CAN channel 1 (obCANFD2)
  • enabled — stream state
    • 0 — disable streaming
    • 1 — enable streaming
Returns
  • success1 if both arguments parsed correctly, 0 otherwise.
Example
o 0 1 # enable streaming on channel 0
o 1 0 # disable streaming on channel 1
Notes
  • Each channel streams independently; toggling one channel does not affect the other.
  • If only channel parses successfully but enabled does not, streaming on that channel is forced off as a safety fallback.
  • All frames will be received unless a receive filter is configured (see Setup Filter) so the controller actually accepts the frames you want to observe.
  • FreeWili2 only has one CAN channel (channel 2 is resevered for future orcas)

Wire command: i\c\o

ArgWire type
channeldecS32
enableddecS32

Returns: none (Ok/Err only)

dev.io.canfd.enable_canfd_stream(channel: int, enabled: int) -> Result
ow_status ow_io_canfd_enable_canfd_stream(ow_device* dev, int32_t channel, int32_t enabled);
dev.io().canfd().enable_canfd_stream(channel: i32, enabled: i32) -> Result<(), OwError>

The C and Rust signatures above are also the WASM guest signatures - the device API surface is identical; only the transport differs (ow_open_wasm(&dev) in C, OneWili::open() in Rust).

dev.io.canfd.enable_canfd_stream(channel, enabled) # check dev.ok

write_canfd

Transmit CAN(FD). Transmits a CAN(FD) frame.

Transmit CAN(FD)

Transmits a single CAN 2.0 or CAN-FD frame on the selected channel. The frame is queued to the controller's transmit FIFO and sent as soon as the bus permits.

Arguments
  • channel — CAN controller index
    • 0 — CAN channel 0 (obCANFD1)
    • 1 — CAN channel 1 (obCANFD2)
    • Note: FreeWili2 only has one CAN channel; channel 1 is reserved for future Orcas.
  • arbId — arbitration ID (hex)
    • 11-bit value (0x0000x7FF) when xtdId = 0
    • 29-bit value (0x000000000x1FFFFFFF) when xtdId = 1
  • canFd — frame format
    • 0 — classic CAN 2.0 frame
    • 1 — CAN-FD frame (allows >8 data bytes and bit-rate switching as configured on the controller)
  • xtdId — identifier length
    • 0 — standard 11-bit ID
    • 1 — extended 29-bit ID
  • dataIn — payload bytes in hex, space-separated (e.g. DE AD BE EF). May be empty for a zero-length frame.
Valid payload lengths (DLC)
  • Classic CAN (canFd = 0): 08 bytes.
  • CAN-FD (canFd = 1): 08, 12, 16, 20, 24, 32, 48, or 64 bytes.

Any other byte count is rejected and the command reports Invalid.

Returns
  • success1 if the frame was accepted by the controller for transmission, 0 otherwise.
Examples
#### Classic CAN, standard ID 0x123, 4 data bytes
w 0 0x123 0 0 DE AD BE EF

#### Classic CAN, extended ID 0x1ABCDEF, no data (remote/empty frame)
w 0 0x01ABCDEF 0 1

#### CAN-FD, standard ID 0x200, 16-byte payload
w 0 0x200 1 0 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
Notes
  • The frame is queued to the transmit FIFO; if the FIFO is full or the bus is unavailable the frame may be delayed.
  • Make sure the controller's bit timing (and FD data-phase timing) is configured before transmitting — see the Neptune/Orca setup commands.
  • For periodic / repeated transmission use Transmit CAN(FD) Periodic instead.

Wire command: i\c\w

ArgWire type
channeldecS32
arb_idhexU32
can_fddecS32
xtd_iddecS32
data_inbyteArray

Returns: none (Ok/Err only)

dev.io.canfd.write_canfd(channel: int, arb_id: int, can_fd: int, xtd_id: int, data_in: bytes | bytearray) -> Result
ow_status ow_io_canfd_write_canfd(ow_device* dev, int32_t channel, uint32_t arb_id, int32_t can_fd, int32_t xtd_id, const uint8_t* data_in, size_t data_in_len);
dev.io().canfd().write_canfd(channel: i32, arb_id: u32, can_fd: i32, xtd_id: i32, data_in: &[u8]) -> Result<(), OwError>

The C and Rust signatures above are also the WASM guest signatures - the device API surface is identical; only the transport differs (ow_open_wasm(&dev) in C, OneWili::open() in Rust).

dev.io.canfd.write_canfd(channel, arb_id, can_fd, xtd_id, data_in) # check dev.ok

write_canfd_periodic

Transmit CAN(FD) Periodic. Transmits a CAN(FD) frame periodically (period in us; 0 = as fast as possible).

Transmit CAN(FD) Periodic

Configures one of the controller's periodic-transmit slots. Each slot holds a CAN/CAN-FD frame that is re-sent automatically at a fixed interval (or as fast as the bus permits) until it is disabled.

Arguments
  • index — periodic slot, 0RPCANFD_NUM_PERIODICS-1. Each channel has its own independent set of slots.
  • enable — slot state
    • 1 — enable the slot (and load it with the frame defined below)
    • 0 — disable the slot
  • period — transmit interval in microseconds
    • 0 — send as fast as possible (whenever the TX FIFO has room)
    • >0 — send one frame every period µs
  • channel — CAN controller index
    • 0 — CAN channel 0 (obCANFD1)
    • 1 — CAN channel 1 (obCANFD2)
    • Note: FreeWili2 only has one CAN channel; channel 1 is reserved for future Orcas.
  • arbId — arbitration ID (hex)
    • 11-bit (0x0000x7FF) when xtdId = 0
    • 29-bit (0x000000000x1FFFFFFF) when xtdId = 1
  • canFd — frame format
    • 0 — classic CAN 2.0
    • 1 — CAN-FD
  • xtdId — identifier length
    • 0 — standard 11-bit ID
    • 1 — extended 29-bit ID
  • dataIn — payload bytes in hex, space-separated (e.g. DE AD BE EF). May be empty for a zero-length frame.
Valid payload lengths (DLC)
  • Classic CAN (canFd = 0): 08 bytes.
  • CAN-FD (canFd = 1): 08, 12, 16, 20, 24, 32, 48, or 64 bytes.

Any other byte count is rejected and the command reports Invalid.

Short form (toggle only)

If only the first arguments parse — index, enable, and channel — the previously configured frame in that slot is simply enabled or disabled without being re-loaded:

p <index> <enable> <period_ignored> <channel>

In practice, to just turn a configured slot off, the simplest form is:

p 0 0 0 0 # disable slot 0 on channel 0
Returns
  • success1 if the slot was updated, 0 otherwise.
Examples
#### Slot 0 on channel 0: send classic standard-ID 0x123 with 4 data bytes every 10 ms
p 0 1 10000 0 0x123 0 0 DE AD BE EF

#### Slot 1 on channel 0: send CAN-FD standard-ID 0x200, 16-byte payload, as fast as possible
p 1 1 0 0 0x200 1 0 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF

#### Slot 2 on channel 0: extended-ID 0x1ABCDEF, no data, every 1 s
p 2 1 1000000 0 0x01ABCDEF 0 1

#### Disable slot 0 on channel 0
p 0 0 0 0
Notes
  • Frames are queued to the transmit FIFO; if the FIFO is full or the bus is unavailable the frame is delayed until room becomes available.
  • period = 0 ("as fast as possible") fills any free TX FIFO slots every service tick and can saturate the bus — use with care.
  • Make sure the controller's bit timing (and FD data-phase timing) is configured before transmitting — see the Neptune/Orca setup commands.
  • Periodic slots are independent per channel; slot 0 on channel 0 is unrelated to slot 0 on channel 1.
  • To send a single, one-shot frame instead of a periodic stream, use Transmit CAN(FD).

Wire command: i\c\p

ArgWire type
indexdecS32
enabledecS32
perioddecS32
channeldecS32
arb_idhexU32
can_fddecS32
xtd_iddecS32
data_inbyteArray

Returns: none (Ok/Err only)

dev.io.canfd.write_canfd_periodic(index: int, enable: int, period: int, channel: int, arb_id: int, can_fd: int, xtd_id: int, data_in: bytes | bytearray) -> Result
ow_status ow_io_canfd_write_canfd_periodic(ow_device* dev, int32_t index, int32_t enable, int32_t period, int32_t channel, uint32_t arb_id, int32_t can_fd, int32_t xtd_id, const uint8_t* data_in, size_t data_in_len);
dev.io().canfd().write_canfd_periodic(index: i32, enable: i32, period: i32, channel: i32, arb_id: u32, can_fd: i32, xtd_id: i32, data_in: &[u8]) -> Result<(), OwError>

The C and Rust signatures above are also the WASM guest signatures - the device API surface is identical; only the transport differs (ow_open_wasm(&dev) in C, OneWili::open() in Rust).

dev.io.canfd.write_canfd_periodic(index, enable, period, channel, arb_id, can_fd, xtd_id, data_in) # check dev.ok

setup_filter

Setup Filter. Sets up a hardware receive filter (the byte-filter args are optional).

Setup Filter

Configures one of the CAN controller's hardware receive filters. Frames that do not match an enabled filter are dropped before reaching the stream / FIFO. If there are no filters configure Stream CAN(FD) shows all messages.

Arguments

Arguments are space-separated. The four byte-filter arguments at the end are optional.

  • channel — CAN controller index
    • 0 — CAN channel 0 (obCANFD1)
    • 1 — CAN channel 1 (obCANFD2)
    • Note: FreeWili2 only has one CAN channel; channel 1 is reserved for future Orcas.
  • index — hardware filter slot, 0RPCANFD_FILTERS_COUNT-1 (up to 32).
  • enable1 to enable the filter, 0 to disable it.
  • xtdId0 = standard 11-bit ID, 1 = extended 29-bit ID.
  • mask — ID mask (hex). A 1 bit means "this bit must match"; a 0 bit is don't-care.
  • accept — ID value to match after the mask is applied (hex).
  • maskb0, acceptB0 (optional) — mask/accept for data byte 0 (hex, 8-bit). Standard IDs only.
  • maskb1, acceptB1 (optional) — mask/accept for data byte 1 (hex, 8-bit). Standard IDs only.

A frame is accepted when:

(rxId & mask) == accept
(rxByte0 & maskb0) == acceptB0 # if byte filters provided
(rxByte1 & maskb1) == acceptB1 # if byte filters provided
Returns
  • success1 if the filter was updated, 0 otherwise.
Examples
#### Enable filter 0 on channel 0, standard ID, accept only ID 0x123
f 0 0 1 0 0x7FF 0x123

#### Accept any standard ID 0x100–0x10F (mask off low 4 bits)
f 0 1 1 0 0x7F0 0x100

#### Same as above, but only frames whose first data byte is 0xA5
f 0 1 1 0 0x7F0 0x100 0xFF 0xA5 0x00 0x00

#### Disable filter 2 on channel 0 (only the first three args are needed)
f 0 2 0
Notes
  • Omitting mask/accept is only valid when enable is 0; otherwise parsing fails and the command reports Invalid.
  • If the byte-filter arguments are omitted, all four byte mask/accept values are cleared to 0 (i.e., no byte filtering).
  • Byte filtering applies to standard IDs only; do not rely on maskb0/maskb1 when xtdId = 1.
  • Filters are re-applied to the controller immediately (setupFilters(false)) after a successful update.
  • if no filters are configured all frames will be received.

Wire command: i\c\f

ArgWire type
channeldecS32
indexdecS32
enabledecS32
xtd_iddecS32
maskhexU32
accepthexU32
maskb0hexU32
accept_b0hexU32
maskb1hexU32
accept_b1hexU32

Returns: none (Ok/Err only)

dev.io.canfd.setup_filter(channel: int, index: int, enable: int, xtd_id: int, mask: int, accept: int, maskb0: int, accept_b0: int, maskb1: int, accept_b1: int) -> Result
ow_status ow_io_canfd_setup_filter(ow_device* dev, int32_t channel, int32_t index, int32_t enable, int32_t xtd_id, uint32_t mask, uint32_t accept, uint32_t maskb0, uint32_t accept_b0, uint32_t maskb1, uint32_t accept_b1);
dev.io().canfd().setup_filter(channel: i32, index: i32, enable: i32, xtd_id: i32, mask: u32, accept: u32, maskb0: u32, accept_b0: u32, maskb1: u32, accept_b1: u32) -> Result<(), OwError>

The C and Rust signatures above are also the WASM guest signatures - the device API surface is identical; only the transport differs (ow_open_wasm(&dev) in C, OneWili::open() in Rust).

dev.io.canfd.setup_filter(channel, index, enable, xtd_id, mask, accept, maskb0, accept_b0, maskb1, accept_b1) # check dev.ok

read_can_registers

Read CAN Register(s). Reads 32-bit words from CAN controller SFR registers.

Read CAN Register(s)

Reads one or more consecutive 32-bit Special Function Registers (SFRs) from the selected CAN controller and returns them to the host as name/value pairs.

Arguments
  • channel — CAN controller index
    • 0 — CAN channel 0 (obCANFD1)
    • 1 — CAN channel 1 (obCANFD2)
    • Note: FreeWili2 only has one CAN channel; channel 1 is reserved for future Orcas.
  • startAddress — SFR start address (hex). Aligned to the controller's 32-bit register map (e.g. MCP25xxFD-style SFRs on the on-board controller).
  • wordCount — number of consecutive 32-bit words to read, starting at startAddress.
Returns
  • registers — a list of name=value pairs, one per 32-bit word, with each value formatted as a 32-bit hex number.
Example
#### Read 4 words starting at SFR address 0x000 on channel 0
r 0 0x000 4
Notes
  • The command operates directly on the CAN controller's SFR space — be careful when reading registers that have read-side-effects (e.g. interrupt/error status clears).
  • Use Set CAN Register (s) to write a register, and the Neptune/Orca setup commands for normal bit-timing and configuration changes.
  • Returns Invalid if channel is out of range or any argument fails to parse.
  • FreeWili GUI decodes these values for helpful debugging

Wire command: i\c\r

ArgWire type
channeldecS32
start_addresshexU32
word_countdecS32

Returns: registers (namevaluepairH32)

dev.io.canfd.read_can_registers(channel: int, start_address: int, word_count: int) -> Result
ow_status ow_io_canfd_read_can_registers(ow_device* dev, int32_t channel, uint32_t start_address, int32_t word_count, char* registers, size_t registers_cap);
dev.io().canfd().read_can_registers(channel: i32, start_address: u32, word_count: i32) -> Result<String, OwError>

The C and Rust signatures above are also the WASM guest signatures - the device API surface is identical; only the transport differs (ow_open_wasm(&dev) in C, OneWili::open() in Rust).

dev.io.canfd.read_can_registers(channel, start_address, word_count) # returns value; check dev.ok

set_can_register

Set CAN Register. Sets a CAN controller register.

Set CAN Register

Writes a single 32-bit (or 8-bit) Special Function Register (SFR) on the selected CAN controller. This is a direct register write — bypassing the normal setup commands — and should be used only when you know exactly what the controller expects.

Arguments
  • channel — CAN controller index
    • 0 — CAN channel 0 (obCANFD1)
    • 1 — CAN channel 1 (obCANFD2)
    • Note: FreeWili2 only has one CAN channel; channel 1 is reserved for future Orcas.
  • startAddress — SFR address (hex). Aligned to the controller's 32-bit register map (e.g. MCP25xxFD-style SFRs on the on-board controller).
  • byteCount — write width
    • 1 — write the low 8 bits of wordToWrite to startAddress
    • 4 — write the full 32-bit wordToWrite to startAddress
  • wordToWrite — value to write (hex). Only the low byteCount bytes are used.
Returns
  • success1 if the write was accepted, 0 otherwise.
Examples
#### Write the 32-bit value 0x00000004 to SFR 0x000 on channel 0
s 0 0x000 4 0x00000004

#### Write the single byte 0xA5 to SFR 0x010 on channel 0
s 0 0x010 1 0xA5
Notes
  • This is a raw register write — be careful with registers that have write-side-effects (mode changes, FIFO control, interrupt clears, etc.).
  • For normal bit-timing and configuration changes, prefer the Neptune/Orca setup commands instead of writing SFRs directly.
  • Use Read CAN Register(s) (r) to verify the value after writing.
  • Returns Invalid if channel is out of range or any argument fails to parse.

Wire command: i\c\s

ArgWire type
channeldecS32
start_addresshexU32
byte_countdecS32
word_to_writehexU32

Returns: none (Ok/Err only)

dev.io.canfd.set_can_register(channel: int, start_address: int, byte_count: int, word_to_write: int) -> Result
ow_status ow_io_canfd_set_can_register(ow_device* dev, int32_t channel, uint32_t start_address, int32_t byte_count, uint32_t word_to_write);
dev.io().canfd().set_can_register(channel: i32, start_address: u32, byte_count: i32, word_to_write: u32) -> Result<(), OwError>

The C and Rust signatures above are also the WASM guest signatures - the device API surface is identical; only the transport differs (ow_open_wasm(&dev) in C, OneWili::open() in Rust).

dev.io.canfd.set_can_register(channel, start_address, byte_count, word_to_write) # check dev.ok