Device Driver: CAN Controller JF0815#
Plan#
Wrap JF0815 HW wrapper in class with blocking interface
Use semaphores to block in either direction
Register ISRs for wakeups, internally (as an implementation detail)
Driver Usage: Transmit#
#include "can-jf0815.h"
#include <why-time.h>
#include <why-irq.h>
#include <print>
int main()
{
Why::init();
CAN_JF0815 can("my-can");
while (true) {
can.xmit(CANFrame{/*id*/42, /*dlc*/7, "1234567"});
Why::sleep_milli(500);
}
return 0;
}
Driver Usage: Receive#
#include "can-jf0815.h"
#include <why-time.h>
#include <why-irq.h>
#include <print>
int main()
{
Why::init();
CAN_JF0815 can("my-can");
while (true) {
auto frame = can.recv();
std::println("ID {}, dlc {}, data {}", frame.id, frame.dlc, std::string((const char*)frame.data, frame.dlc));
}
return 0;
}
Driver Implementation#
#pragma once
#include <can-jf0815-hw.h>
#include <why-semaphore.h>
#include <string>
class CAN_JF0815
{
public:
CAN_JF0815(const std::string& can_iface);
void xmit(const CANFrame&); // <-- blocks caller until frame xmitted
CANFrame recv(); // <-- blocks caller until frame received
private:
CAN_JF0815_HW _controller;
Why::Semaphore _sem_xmit_done;
Why::Semaphore _sem_recv_ready;
void _isr_xmit_done();
void _isr_recv_ready();
};
#include "can-jf0815.h"
#include <why-irq.h>
CAN_JF0815::CAN_JF0815(const std::string& can_iface)
: _controller(can_iface),
_sem_xmit_done(Why::Semaphore(0)),
_sem_recv_ready(Why::Semaphore(0))
{
Why::IRQ::connect(CAN_JF0815_HW::IRQ_XMIT_DONE, [this](int irqnum){_isr_xmit_done();});
Why::IRQ::connect(CAN_JF0815_HW::IRQ_RECV_READY, [this](int irqnum){_isr_recv_ready();});
}
void CAN_JF0815::xmit(const CANFrame& frame)
{
_controller.begin_xmit(frame);
_sem_xmit_done.take(); // <-- block until xmitted
}
CANFrame CAN_JF0815::recv()
{
_sem_recv_ready.take(); // <-- block until frame in recv buffer
return _controller.commit_recv();
}
void CAN_JF0815::_isr_xmit_done()
{
_sem_xmit_done.give(); // <-- wakeup xmitter thread
}
void CAN_JF0815::_isr_recv_ready()
{
_sem_recv_ready.give(); // <-- wakeup receiver thread
}