rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
xl2515.c File Reference

The XL2515 over SPI: the part of the CAN driver that touches hardware. More...

#include "xl2515.h"
#include <string.h>
#include "hardware/gpio.h"
#include "hardware/spi.h"
#include "pico/stdlib.h"
#include "can_timing.h"
#include "iomcu_pins.h"
#include "mcp2515.h"

Functions

static void cs_low (void)
 Drives the chip select low, selecting the part.
static void cs_high (void)
 Drives the chip select high, deselecting the part.
static void write_regs (uint8_t addr, const uint8_t *data, size_t n)
 Writes n registers starting at addr, with a WRITE command.
static void write_reg (uint8_t addr, uint8_t value)
 Writes one register.
static void read_regs (uint8_t addr, uint8_t *out, size_t n)
 Reads n registers starting at addr, with a READ command.
static uint8_t read_reg (uint8_t addr)
 Reads one register.
static void bit_modify (uint8_t addr, uint8_t mask, uint8_t value)
 Read-modify-write in the part rather than here: the interrupt flags are set by the controller between a read and a write, and clearing them with a whole-register write would drop whatever arrived in between.
bool xl2515_init (uint32_t bitrate)
 Reset, set the bit timing for bitrate, and enter normal mode.
bool xl2515_send (const link_can_frame_t *f)
 Queue one frame in TXB0 and request transmission.
static bool fetch_rx (void *ctx, uint8_t buf[13])
 Consume the next full receive buffer, RXB0 before RXB1.
bool xl2515_recv (link_can_frame_t *f, uint32_t *refused)
 Take one frame from whichever receive buffer has one.
bool xl2515_take_overflow (void)
 True if a frame arrived with both receive buffers full since the last call.
void xl2515_errors (uint8_t *tx_errors, uint8_t *rx_errors, uint8_t *flags)
 The controller's own error counters, for the bring-up report.

Detailed Description

The XL2515 over SPI: the part of the CAN driver that touches hardware.

SPDX-License-Identifier: MIT

Function Documentation

◆ bit_modify()

void bit_modify ( uint8_t addr,
uint8_t mask,
uint8_t value )
static

Read-modify-write in the part rather than here: the interrupt flags are set by the controller between a read and a write, and clearing them with a whole-register write would drop whatever arrived in between.

Parameters
addrAddress of the register.
maskBits to change.
valueNew value of the bits in mask.

◆ fetch_rx()

bool fetch_rx ( void * ctx,
uint8_t buf[13] )
static

Consume the next full receive buffer, RXB0 before RXB1.

Parameters
ctxUnused.
bufReceives the 13 bytes of the buffer.
Returns
True when a buffer was read. False when neither holds a frame.

◆ read_reg()

uint8_t read_reg ( uint8_t addr)
static

Reads one register.

Parameters
addrAddress of the register.
Returns
The register value.

◆ read_regs()

void read_regs ( uint8_t addr,
uint8_t * out,
size_t n )
static

Reads n registers starting at addr, with a READ command.

Parameters
addrAddress of the first register.
outReceives the n values.
nNumber of registers to read.

◆ write_reg()

void write_reg ( uint8_t addr,
uint8_t value )
static

Writes one register.

Parameters
addrAddress of the register.
valueValue to write.

◆ write_regs()

void write_regs ( uint8_t addr,
const uint8_t * data,
size_t n )
static

Writes n registers starting at addr, with a WRITE command.

Parameters
addrAddress of the first register.
dataValues to write.
nNumber of registers to write.

◆ xl2515_errors()

void xl2515_errors ( uint8_t * tx_errors,
uint8_t * rx_errors,
uint8_t * flags )

The controller's own error counters, for the bring-up report.

Either pointer may be NULL.

Parameters
tx_errorsReceives the transmit error counter (TEC). May be NULL.
rx_errorsReceives the receive error counter (REC). May be NULL.
flagsReceives the error flags register (EFLG). May be NULL.

◆ xl2515_init()

bool xl2515_init ( uint32_t bitrate)

Reset, set the bit timing for bitrate, and enter normal mode.

False if the part does not answer. The datasheet guarantees configuration mode after a reset, so a CANSTAT that says otherwise means nothing is listening on the SPI bus: an SPI wiring fault, not a CAN wiring fault.

Parameters
bitrateCAN bit rate in bit/s.
Returns
True when the controller is in normal mode. False when the part does not answer, or the crystal cannot make bitrate.

◆ xl2515_recv()

bool xl2515_recv ( link_can_frame_t * f,
uint32_t * refused )

Take one frame from whichever receive buffer has one.

A buffer holding a frame this link does not carry is consumed, adds 1 to refused (modulo 2^32, NULL counts nothing) and the other buffer is tried. False if none holds a valid frame.

Parameters
fReceives the frame.
refusedCounts the frames this link does not carry. NULL counts nothing.
Returns
True when a valid frame was taken. False when no buffer holds one.

◆ xl2515_send()

bool xl2515_send ( const link_can_frame_t * f)

Queue one frame in TXB0 and request transmission.

False if the buffer is still busy with the previous one.

Parameters
fThe frame to send. NULL is refused, and so is a DLC above 8.
Returns
True when the frame is queued. False when the buffer is still busy with the previous frame, or the identifier cannot be packed.

◆ xl2515_take_overflow()

bool xl2515_take_overflow ( void )

True if a frame arrived with both receive buffers full since the last call.

The flags are sticky and the MCU (microcontroller unit) clears them, which makes this the one record of a frame lost with nothing wrong on the wire: it arrived, it was correct, and there was nowhere to put it. Reading clears them, so the answer covers the time since the last call.

Returns
True when an overflow was seen since the last call.