34#ifndef _DEFAULT_SOURCE
35#define _DEFAULT_SOURCE
64 {20000000, 125000, {(3 - 1), (4 - 1), (11 - 1), (10 - 1)}},
82 {40000000, 125000, {(3 - 1), (4 - 1), (11 - 1), (20 - 1)}},
90 uint16_t rx_timeout_bits)
99 uint8_t spi_mode = SPI_MODE_0;
100 uint8_t spi_bpw = 32;
101 uint32_t spi_max_speed_hz = freq / 2;
124 mode.clkRef = (freq == 40000000);
135 }
while (cccr.init == 0);
142 }
while (cccr.cce == 0);
186 HASSERT(rx_timeout_bits >= 10);
195 tocc.top = (rx_timeout_bits - 1);
212 }
while (cccr.init == 1);
247 MCANInterrupt mcan_interrupt;
248 mcan_interrupt.data = 0x3FFFFFFF;
330 rxf0a.fai = rxf0s.fgi;
347 HASSERT((count %
sizeof(
struct can_frame)) == 0);
349 struct can_frame *data = (
struct can_frame*)buf;
352 count /=
sizeof(
struct can_frame);
356 size_t frames_read = 0;
357 MRAMRXBuffer *mram_rx_buffer =
reinterpret_cast<MRAMRXBuffer*
>(data);
366 static_assert(
sizeof(
struct can_frame) ==
sizeof(MRAMRXBuffer),
"RX buffer size does not match assumptions.");
369 frames_read = std::min(
RX_FIFO_SIZE - rxf0s.fgi, rxf0s.ffl);
372 frames_read = std::min(frames_read, count);
377 mram_rx_buffer, frames_read);
381 rxf0a.fai = rxf0s.fgi + (frames_read - 1);
384 if (frames_read == rxf0s.ffl)
398 for (
size_t i = 0; i < frames_read; ++i)
400 struct can_frame tmp;
402 tmp.can_id = mram_rx_buffer[i].id;
403 if (!mram_rx_buffer[i].xtd)
408 tmp.can_dlc = mram_rx_buffer[i].dlc;
409 tmp.can_rtr = mram_rx_buffer[i].rtr;
410 tmp.can_eff = mram_rx_buffer[i].xtd;
411 tmp.can_err = mram_rx_buffer[i].esi;
413 std::atomic_thread_fence(std::memory_order_seq_cst);
415 data[i].raw[0] = tmp.raw[0];
416 data[i].raw[1] = tmp.raw[1];
419 if (frames_read == 0)
422 if ((file->
flags & O_NONBLOCK) || result > 0)
429 rxBuf->block_until_condition(file,
true);
433 count -= frames_read;
434 result += frames_read;
438 if (!result && (file->
flags & O_NONBLOCK))
443 return result *
sizeof(
struct can_frame);
451 HASSERT((count %
sizeof(
struct can_frame)) == 0);
453 const struct can_frame *data = (
const struct can_frame*)buf;
456 count /=
sizeof(
struct can_frame);
460 size_t frames_written = 0;
488 frames_written = std::min(
493 frames_written = std::min(frames_written, count);
496 uint32_t put_index = txfqs.tfqpi;
499 for (
size_t i = 0; i < frames_written; ++i, ++put_index)
504 tx_buffers[i].
id = data[i].can_id;
509 tx_buffers[i].id = data[i].can_id << 18;
511 tx_buffers[i].rtr = data[i].can_rtr;
512 tx_buffers[i].xtd = data[i].can_eff;
513 tx_buffers[i].esi = data[i].can_err;
514 tx_buffers[i].dlc = data[i].can_dlc;
515 tx_buffers[i].brs = 0;
516 tx_buffers[i].fdf = 0;
517 tx_buffers[i].efc = 0;
518 tx_buffers[i].mm = 0;
519 tx_buffers[i].data64 = data[i].data64;
520 txbar |= 0x1 << put_index;
531 if (frames_written == txfqs.tffl)
539 uint32_t watermark_index = txfqs.tfgi + (
TX_FIFO_SIZE / 2);
540 if (watermark_index >=
552 if (frames_written == 0)
555 if ((file->
flags & O_NONBLOCK) || result > 0)
562 txBuf->block_until_condition(file,
false);
567 result += frames_written;
568 count -= frames_written;
569 data += frames_written;
573 if (!result && (file->
flags & O_NONBLOCK))
578 return result *
sizeof(
struct can_frame);
638__attribute__((optimize(
"-O3")))
649 enable_ = register_read(INTERRUPT_ENABLE);
650 spiStatus_ = register_read(STATUS);
651 status_ = register_read(INTERRUPT_STATUS);
659 spi_ioc_transfer xfer[2];
660 xfer[0].tx_buf = (
unsigned long)&msg;
662 xfer[0].len =
sizeof(MRAMSPIMessage);
664 xfer[1].rx_buf = (
unsigned long)regs_;
665 xfer[1].len =
sizeof(regs_);
667 spi_->transfer_with_cs_assert_polled(xfer, 2);
682 MCANInterrupt mcan_interrupt;
683 mcan_interrupt.data = register_read(IR);
686 register_write(IR, mcan_interrupt.data & mcanInterruptEnable_.data);
689 uint32_t status = register_read(INTERRUPT_STATUS);
692 register_write(INTERRUPT_STATUS, status);
697 if (mcan_interrupt.bo || mcan_interrupt.ep || mcan_interrupt.rf0l)
701 psr.data = register_read(PSR);
703 if (mcan_interrupt.rf0l)
708 if (mcan_interrupt.ep)
727 if (mcan_interrupt.bo)
733 testPin_->write(!testPin_->read());
742 register_write(CCCR, cccr.data);
743 cccr.data = register_read(CCCR);
744 }
while (cccr.init == 1);
747 register_write(TXBCR, TX_FIFO_BUFFERS_MASK);
749 txBuf->signal_condition();
751 testPin_->write(!testPin_->read());
765 if (mcan_interrupt.tc && txCompleteMask_)
773 txBuf->signal_condition();
778 register_write(TXBTIE, txCompleteMask_);
782 if (mcan_interrupt.too && mcanInterruptEnable_.too)
790 rxBuf->signal_condition();
794 mcanInterruptEnable_.too = 0;
795 register_write(IE, mcanInterruptEnable_.data);
See OSMutexLock in os/OS.hxx.
DeviceBuffer< struct can_frame > * txBuf
transmit buffer
DeviceBuffer< struct can_frame > * rxBuf
receive buffer
bool select(File *file, int mode) OVERRIDE
Device select method.
void select_insert()
Add client to list of clients needing woken.
const char * name
device name
int open(File *, const char *, int, int) OVERRIDE
Open method.
OSMutex lock_
protects internal structures.
Class to allow convenient locking and unlocking of mutexes in a C context.
static int get_priority_max()
Get the maximum thread priority.
void start(const char *name, int priority, size_t stack_size)
Starts the thread.
Specification of CAN driver for the TCAN4550.
static constexpr uint32_t TX_FIFO_SIZE
size in elements for the TX FIFO
static constexpr uint16_t TX_BUFFERS_MRAM_ADDR
start address of TX BUFFERS in MRAM
void disable() override
function to disable device
MCANInterrupt mcanInterruptEnable_
shadow for the interrupt enable
bool select(File *file, int mode) override
Device select method.
static constexpr uint32_t TX_DEDICATED_BUFFER_COUNT
size in elements for the dedicated TX buffers
static constexpr uint16_t RX_FIFO_0_MRAM_ADDR
start address of RX FIFO 0 in MRAM
uint32_t register_read(Registers address)
Read from a SPI register.
void init(const char *spi_name, uint32_t freq, uint32_t baud, uint16_t rx_timeout_bits)
Initialize CAN device settings.
int spiFd_
SPI bus that accesses TCAN4550.
int ioctl(File *file, unsigned long int key, unsigned long data) override
Request an ioctl transaction.
Registers
SPI Registers, word addressing, not byte addressing.
@ TXFQS
0xC4 0xC4 TX FIFO/queue status
@ RXF0C
0xA0 -— RX FIFO 0 configuration
@ NBTP
nominal bit timing and prescaler
@ INTERRUPT_STATUS
interrupt and diagnostic flags
@ TXBAR
0xD0 0xCC TX buffer add request
@ RXF0S
0xA4 0x90 RX FIFO 0 status
@ TXESC
0xC8 -— TX buffer element size configuration
@ TXEFC
0xF0 -— TX event FIFO configuration
@ RXF0A
0xA8 0x94 RX FIFO 0 Acknowledge
@ ILE
interrupt line enable
@ TXBC
0xC0 0xC0 TX buffer configuration
@ INTERRUPT_ENABLE
interrupt and diagnostic flags
@ MODE
modes of operation and pin configurations
@ TXBTIE
0xE0 0xDC TX buffer transmission interrupt enable
@ TXBCR
0xD4 0xD0 TX buffer cancellation request
@ TSCC
timestamp counter configuration
@ TOCC
timeout counter configuration
static constexpr uint32_t RX_FIFO_SIZE
size in elements for the RX FIFO
void txbuf_write(uint16_t offset, MRAMTXBufferMultiWrite *buf, size_t count)
Write one or more TX buffers.
ssize_t write(File *file, const void *buf, size_t count) override
Write to a file or device.
static constexpr size_t MRAM_SIZE_WORDS
size in words of the MRAM memory
void(* interruptEnable_)()
enable interrupt callback
static constexpr uint16_t TX_EVENT_FIFO_MRAM_ADDR
start address of TX Event FIFO in MRAM
void register_write(Registers address, uint32_t data)
Write to a SPI register.
SPI * spi_
pointer to a SPI object instance
ssize_t read(File *file, void *buf, size_t count) override
Read from a file or device.
static constexpr uint32_t TX_FIFO_BUFFERS_MASK
mask of all the TX buffers used in the TX FIFO
void enable() override
function to enable device
uint8_t txPending_
waiting on a TX active event
void rxbuf_read(uint16_t offset, MRAMRXBuffer *buf, size_t count)
Read one or more RX buffers.
static constexpr uint32_t SPI_MAX_SPEED_HZ
maximum SPI clock speed in Hz
void flush_buffers() override
Called after disable.
MRAMTXBufferMultiWrite txBufferMultiWrite_
Allocating this buffer here avoids having to put it on the TCAN4550Can::write() caller's stack.
uint8_t state_
present bus state
uint8_t rxPending_
waiting on a RX active event
uint32_t txCompleteMask_
shadow for the transmit complete buffer mask
static const TCAN4550Baud BAUD_TABLE[]
baud rate settings table
void(* interruptDisable_)()
disable interrupt callback
static constexpr uint32_t TX_EVENT_FIFO_SIZE
size in elements for the TX event FIFO
#define CAN_STATE_BUS_OFF
CAN bus off.
#define CAN_STATE_ACTIVE
CAN bus active.
#define SIOCGCANSTATE
Read the CAN state.
uint32_t can_state_t
CAN state type.
#define CAN_STATE_STOPPED
CAN bus stopped.
#define CAN_STATE_BUS_PASSIVE
CAN bus error passive.
#define FWRITE
Workaround for missing header defines on some newlib versions.
#define FREAD
Workaround for missing header defines on some newlib versions.
#define ARRAYSIZE(a)
Returns the number of elements in a statically defined array (of static size)
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
BootloaderState state_
Global state variables.
#define SEC_TO_NSEC(_sec)
Convert a second value to a nanosecond value.
uint32_t tc
transmission completed
uint32_t too
timeout occurred
uint32_t rf0l
RX FIFO 0 message lost.
uint32_t data
raw word value
uint32_t bo
bus-off status
MRAMTXBuffer txBuffers[TX_FIFO_SIZE]
buffer payload
uint32_t id
CAN identifier.