-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Improve CAN Demo projects (#167)
* refactor: Improve CAN Demo project names Rename Foo to Send and Bar to Receive to be clearer about their purposes. Update CAN bus name from `veh` to `demobus` to emphasize this demo. Improves READMEs * fixes filenames * initial periphs * Linux MCAL * Demo CAN Work, Blink for linux * adds button to Demo CAN Send cli * renames postbuild to fix casing * Fix hardcoded ID in mcal/linux. Improve README to add instructions. Add IO for stm32 & CLI platforms. * Simplify message to use just one field. Fix button type in Send * Print CAN bytes only up to frame DLC * updates Receive pinout & adds docs for stm platform * Add link to WSL article * Remove Linux Toolchain cmds since they did not fix their listed problem * Use std::format instead of stream operator. * Simplify CMakeLists * Update to new config scheme * Update to new config scheme
- Loading branch information
1 parent
72c9b35
commit 7a6a00a
Showing
68 changed files
with
1,053 additions
and
599 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
add_library(mcal-linux STATIC) | ||
|
||
target_include_directories(mcal-linux PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../..) | ||
|
||
add_subdirectory(periph) | ||
target_link_libraries(mcal-linux INTERFACE shared) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# No special postbuild actions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Linux MCAL | ||
|
||
A more advanced CLI. CAN messages are sent over virtual can (vcan) to enable true CAN communication between processes. | ||
|
||
## Note on Namespace Name | ||
|
||
The namespace is `mcal::lnx`, not `mcal::linux` as one might expect. This is because g++ defines `linux=1`, preventing `linux` from being used as an identifier. | ||
|
||
## WSL Compatability | ||
|
||
You can run this platform through the Windows Subsystem for Linux but must recompile your WSL kernel to include the CAN modules. See <https://macformula.github.io/racecar/tutorials/wsl-can/>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Blake Freer | ||
# November 8, 2024 | ||
# No cmake instructions as the default Linux compiler should work. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
target_sources(mcal-linux | ||
PRIVATE | ||
adc.cc | ||
can.cc | ||
digital_input.cc | ||
digital_output.cc | ||
) | ||
|
||
add_subdirectory(vcan) | ||
target_link_libraries(mcal-linux PUBLIC vcan pthread) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#include <cstdint> | ||
#include <format> | ||
#include <iostream> | ||
|
||
#include "adc.h" | ||
|
||
namespace mcal::lnx::periph { | ||
|
||
ADCInput::ADCInput(std::string name) : name_(name) {} | ||
|
||
void ADCInput::Start() { | ||
std::cout << std::format("Reading ADC \"{}\"\n", name_); | ||
} | ||
|
||
uint32_t ADCInput::Read() { | ||
Start(); | ||
|
||
uint32_t adc_val; | ||
std::cout << " | Enter an unsigned 32-bit value: "; | ||
std::cin >> adc_val; | ||
std::cout << " | Obtained value " << adc_val << std::endl; | ||
|
||
return adc_val; | ||
} | ||
|
||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <string> | ||
|
||
#include "shared/periph/adc.h" | ||
|
||
namespace mcal::lnx::periph { | ||
|
||
class ADCInput : public shared::periph::ADCInput { | ||
public: | ||
ADCInput(std::string name); | ||
|
||
void Start() override; | ||
uint32_t Read() override; | ||
|
||
private: | ||
std::string name_; | ||
}; | ||
|
||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
#include <linux/can.h> | ||
#include <sys/types.h> | ||
|
||
#include <cstring> | ||
#include <format> | ||
#include <iomanip> | ||
#include <mutex> | ||
#include <string> | ||
#include <thread> | ||
|
||
#include "can.h" | ||
#include "shared/comms/can/raw_can_msg.h" | ||
#include "vcan/vcan.h" | ||
|
||
static std::string message_to_string(const shared::can::RawCanMsg& msg) { | ||
std::string str = std::format("[{:02X}]", msg.header.id); | ||
for (int i = 0; i < sizeof(msg.header.data_len); ++i) { | ||
str += std::format(" {:02X}", msg.data[i]); | ||
} | ||
return str; | ||
} | ||
|
||
static can_frame to_can_frame(const shared::can::RawCanMsg& msg) { | ||
struct can_frame frame{.can_id = msg.header.id, | ||
.can_dlc = msg.header.data_len}; | ||
std::memcpy(&frame.data, msg.data, 8); | ||
return frame; | ||
} | ||
|
||
static shared::can::RawCanMsg from_can_frame(const can_frame& frame) { | ||
shared::can::RawCanMsg msg; | ||
msg.header = { | ||
.id = frame.can_id, | ||
.data_len = frame.can_dlc, | ||
.is_extended_frame = static_cast<bool>(frame.can_id & CAN_EFF_FLAG), | ||
}; | ||
msg.tick_timestamp = 0; | ||
|
||
std::copy(frame.data, frame.data + 8, msg.data); | ||
|
||
return msg; | ||
} | ||
|
||
namespace mcal::lnx::periph { | ||
|
||
CanBase::CanBase(std::string iface) : socket_(iface) {} | ||
|
||
void CanBase::Setup() { | ||
socket_.Open(); | ||
|
||
// Another thread handles reading | ||
reader_thread_ = std::thread(&CanBase::StartReading, this); | ||
} | ||
|
||
void CanBase::Send(const shared::can::RawCanMsg& can_tx_msg) { | ||
std::cout << std::format("CanBase {}: Sending\n| {}", socket_.GetIface(), | ||
message_to_string(can_tx_msg)) | ||
<< std::endl; | ||
|
||
auto frame = to_can_frame(can_tx_msg); | ||
socket_.Write(&frame); | ||
} | ||
|
||
void CanBase::ReadQueue(shared::can::RawCanMsg can_rx_msgs[], size_t len) { | ||
uint16_t msg_idx = 0; | ||
std::lock_guard<std::mutex> lock(queue_access_); | ||
while (!can_queue_.empty() && msg_idx < len) { | ||
can_rx_msgs[msg_idx] = can_queue_.front(); | ||
|
||
std::cout << std::format("CanBase {}: Received\n| {}", | ||
socket_.GetIface(), | ||
message_to_string(can_rx_msgs[msg_idx])) | ||
<< std::endl; | ||
|
||
can_queue_.pop(); | ||
msg_idx++; | ||
} | ||
} | ||
|
||
void CanBase::StartReading() { | ||
struct can_frame frame; | ||
shared::can::RawCanMsg raw_msg; | ||
|
||
while (true) { | ||
// Block until a frame arrives | ||
ssize_t bytes_read = socket_.Read(&frame); | ||
if (bytes_read == -1) { | ||
perror("Error reading from CAN socket."); | ||
exit(1); | ||
} | ||
|
||
raw_msg = from_can_frame(frame); | ||
|
||
{ // push RawCanMsg to queue | ||
std::lock_guard<std::mutex> lock(queue_access_); | ||
can_queue_.push(raw_msg); | ||
} | ||
} | ||
} | ||
|
||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#pragma once | ||
|
||
#include <mutex> | ||
#include <queue> | ||
#include <thread> | ||
|
||
#include "mcal/linux/periph/vcan/vcan.h" | ||
#include "shared/comms/can/raw_can_msg.h" | ||
#include "shared/periph/can.h" | ||
#include "vcan/vcan.h" | ||
|
||
namespace mcal::lnx::periph { | ||
|
||
class CanBase : public shared::periph::CanBase { | ||
public: | ||
CanBase(std::string can_iface); | ||
|
||
void Setup(); | ||
void Send(const shared::can::RawCanMsg&); | ||
void ReadQueue(shared::can::RawCanMsg[], size_t len); | ||
|
||
private: | ||
struct vcan::VcanSocket socket_; | ||
|
||
std::queue<shared::can::RawCanMsg> can_queue_; | ||
std::mutex queue_access_; | ||
std::thread reader_thread_; | ||
|
||
void StartReading(); | ||
}; | ||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#include <format> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#include "digital_input.h" | ||
|
||
namespace mcal::lnx::periph { | ||
|
||
DigitalInput::DigitalInput(std::string name) : name_(name) {}; | ||
|
||
bool DigitalInput::Read() { | ||
int value; | ||
|
||
std::cout << std::format("Reading DigitalInput \"{}\"", name_) << std::endl; | ||
std::cout << "| Enter 0 for False, 1 for True: "; | ||
std::cin >> value; | ||
std::cout << std::format("| Value was {}", value ? "true" : "false") | ||
<< std::endl; | ||
|
||
return value; | ||
} | ||
|
||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
#include "shared/periph/gpio.h" | ||
|
||
namespace mcal::lnx::periph { | ||
|
||
class DigitalInput : public shared::periph::DigitalInput { | ||
public: | ||
DigitalInput(std::string name); | ||
|
||
bool Read() override; | ||
|
||
private: | ||
std::string name_; | ||
}; | ||
|
||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include <format> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#include "digital_output.h" | ||
|
||
namespace mcal::lnx::periph { | ||
|
||
DigitalOutput::DigitalOutput(std::string name) : name_(name) {} | ||
|
||
void DigitalOutput::Set(bool value) { | ||
std::cout << std::format("DigitalOutput \"{}\" => {}", name_, | ||
value ? "true" : "false") | ||
<< std::endl; | ||
} | ||
|
||
void DigitalOutput::SetHigh() { | ||
Set(true); | ||
} | ||
|
||
void DigitalOutput::SetLow() { | ||
Set(false); | ||
} | ||
|
||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#pragma once | ||
|
||
#include <iostream> | ||
#include <string> | ||
|
||
#include "shared/periph/gpio.h" | ||
|
||
namespace mcal::lnx::periph { | ||
class DigitalOutput : public shared::periph::DigitalOutput { | ||
public: | ||
DigitalOutput(std::string name); | ||
|
||
void Set(bool value) override; | ||
void SetHigh() override; | ||
void SetLow() override; | ||
|
||
private: | ||
std::string name_; | ||
}; | ||
|
||
} // namespace mcal::lnx::periph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
add_library(vcan STATIC vcan.cc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#include <linux/can.h> | ||
#include <linux/can/raw.h> | ||
#include <net/if.h> | ||
#include <sys/ioctl.h> | ||
#include <sys/socket.h> | ||
#include <unistd.h> | ||
|
||
#include <cstdio> | ||
#include <cstring> | ||
#include <format> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#include "vcan.h" | ||
|
||
namespace mcal::lnx::periph::vcan { | ||
|
||
VcanSocket::VcanSocket(std::string iface) : iface_(iface) {} | ||
|
||
int VcanSocket::Open() { | ||
socket_ = socket(PF_CAN, SOCK_RAW, CAN_RAW); | ||
if (socket_ == -1) { | ||
perror("Error while opening socket."); | ||
return -1; | ||
} | ||
strcpy(ifr_.ifr_name, iface_.c_str()); | ||
ioctl(socket_, SIOGIFINDEX, &ifr_); | ||
|
||
addr_.can_family = AF_CAN; | ||
addr_.can_ifindex = ifr_.ifr_ifindex; | ||
|
||
int bind_status = bind(socket_, (struct sockaddr*)&addr_, sizeof(addr_)); | ||
if (bind_status == -1) { | ||
perror("Error in socket bind."); | ||
return -1; | ||
} | ||
|
||
std::cout << std::format("Opened \"{}\" at index {}.\n", iface_, | ||
addr_.can_ifindex); | ||
|
||
return 0; | ||
} | ||
|
||
VcanSocket::~VcanSocket() { | ||
close(socket_); | ||
} | ||
|
||
int VcanSocket::Write(struct can_frame* frame) { | ||
return write(socket_, frame, sizeof(struct can_frame)); | ||
} | ||
|
||
int VcanSocket::Read(struct can_frame* frame) { | ||
return read(socket_, frame, sizeof(struct can_frame)); | ||
} | ||
|
||
std::string VcanSocket::GetIface() const { | ||
return iface_; | ||
} | ||
|
||
} // namespace mcal::lnx::periph::vcan |
Oops, something went wrong.