diff --git a/firmware/projects/Demo/CANErrors/CMakeLists.txt b/firmware/projects/Demo/CANErrors/CMakeLists.txt new file mode 100644 index 000000000..f089022d5 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/CMakeLists.txt @@ -0,0 +1,20 @@ +# Luai Bashar +# November 5, 2024 + +# The target executable 'main' is created in the master CMakeLists. Do not change its name. +# We only need to add the source code files and include directories. + +include("${CMAKE_SOURCE_DIR}/cmake/cangen.cmake") + +target_sources(main + PRIVATE + main.cc +) + +target_include_directories(main + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/inc +) + +# Notice that we don't include any mcal/ subdirectory in this CMake file. +# The master CMakeLists handles platform selection and library linking. \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/README.md b/firmware/projects/Demo/CANErrors/README.md new file mode 100644 index 000000000..a66db442c --- /dev/null +++ b/firmware/projects/Demo/CANErrors/README.md @@ -0,0 +1,32 @@ +# CANErrors +This is the CAN Errors demo project. It defines a global system for the vehicle to send/receive errors through different subsystems. It defines: +- A 64 bit CAN error signal. Each bit represents a different error, and will be sent periodically for other systems to know if an error has occurred +- The `ErrorHandler` class, an interface to set/send different errors on the CAN signal +- Enum `Error` that defines all 64 possible errors to send through the CAN signal + +## How to use `ErrorHandler` + +### Defining an instance of ErrorHandler: +``` +ErrorHandler error_handler{}; +``` + +### Setting errors with ErrorHandler: +- `SetError` takes an error from the `Error` enum and sets it +``` +error_handler.SetError(Error0); +error_handler.SetError(Error15); +error_handler.SetError(Error48); +``` + +### Sending errors with ErrorHandler: +- `SendError` takes a CAN bus and sends the errors through that bus. It resets the errors to send the next set of errors +``` +error_handler.SendError(error_can_bus); +``` + +## Building the Project +- To build the project, run the following in the firmware directory `make PROJECT=Demo/CANErrors PLATFORM=cli` + - This should create a build file with no errors! + - This will also generate the dbc files automatically, but if you want to generate them seperately, run `cangen projects/Demo/CANErrors` +- To execute the new build, run `./build/Demo/CANErrors/cli/main.exe` \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/bindings.h b/firmware/projects/Demo/CANErrors/bindings.h new file mode 100644 index 000000000..f3ad02d53 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/bindings.h @@ -0,0 +1,9 @@ +#pragma once + +#include "shared/comms/can/can_bus.h" + +namespace bindings { + extern shared::periph::CanBase& error_can_base; + extern void Initialize(); + extern void TickBlocking(uint32_t); +} // namespace bindings \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/config.yaml b/firmware/projects/Demo/CANErrors/config.yaml new file mode 100644 index 000000000..8e0788a79 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/config.yaml @@ -0,0 +1,5 @@ +canGen: + busses: + - name: error + node: tms + dbcFile: errors.dbc \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/errors.dbc b/firmware/projects/Demo/CANErrors/errors.dbc new file mode 100644 index 000000000..194bed25b --- /dev/null +++ b/firmware/projects/Demo/CANErrors/errors.dbc @@ -0,0 +1,9 @@ +VERSION "" + +BS_: + +BU_: TMS + +// Defines one 64 bit signal where each bit represents a different error +BO_ 390 TMS_ERROR: 8 TMS + SG_ Errors : 0|64@1+ (1,0) [0|0] "bitfield" Vector__XXX \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/inc/app.h b/firmware/projects/Demo/CANErrors/inc/app.h new file mode 100644 index 000000000..673342fd6 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/inc/app.h @@ -0,0 +1,107 @@ +/// @author Luai Bashar +/// @date 2024-11-10 +/// @brief Functions and types that will be used in CANErrors main + +#pragma once + +#include "../generated/can/error_can_messages.h" +#include "shared/comms/can/can_bus.h" + +/*************************************************************** + App-level objects +***************************************************************/ + +// Defines all possible errors to set +enum class Error { + kError0 = 0, + kError1 = 1, + kError2 = 2, + kError3 = 3, + kError4 = 4, + kError5 = 5, + kError6 = 6, + kError7 = 7, + kError8 = 8, + kError9 = 9, + kError10 = 10, + kError11 = 11, + kError12 = 12, + kError13 = 13, + kError14 = 14, + kError15 = 15, + kError16 = 16, + kError17 = 17, + kError18 = 18, + kError19 = 19, + kError20 = 20, + kError21 = 21, + kError22 = 22, + kError23 = 23, + kError24 = 24, + kError25 = 25, + kError26 = 26, + kError27 = 27, + kError28 = 28, + kError29 = 29, + kError30 = 30, + kError31 = 31, + kError32 = 32, + kError33 = 33, + kError34 = 34, + kError35 = 35, + kError36 = 36, + kError37 = 37, + kError38 = 38, + kError39 = 39, + kError40 = 40, + kError41 = 41, + kError42 = 42, + kError43 = 43, + kError44 = 44, + kError45 = 45, + kError46 = 46, + kError47 = 47, + kError48 = 48, + kError49 = 49, + kError50 = 50, + kError51 = 51, + kError52 = 52, + kError53 = 53, + kError54 = 54, + kError55 = 55, + kError56 = 56, + kError57 = 57, + kError58 = 58, + kError59 = 59, + kError60 = 60, + kError61 = 61, + kError62 = 62, + kError63 = 63 +}; + +// Interface to set/send all possible errors for the system +class ErrorHandler { + public: + // Sets the error based on the error index given + void SetError(Error error) { + uint64_t error_index = static_cast(error); + error_message_.errors |= (1ULL << error_index); + } + + // Sends the error message through the provided CAN bus + // TODO: Error message is only for a specific bus, change this when autogen code is created + void SendError(shared::can::CanBus error_can_bus) { + error_can_bus.Send(error_message_); + + // Reset after a send to not send duplicate errors + ResetError(); + } + private: + // Object that holds a 64 bit int, each bit representing an error + generated::can::TMS_ERROR error_message_{}; + + // Resets all errors back to untriggered + void ResetError() { + error_message_.errors = 0; + } +}; \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/main.cc b/firmware/projects/Demo/CANErrors/main.cc new file mode 100644 index 000000000..3fd35ffc3 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/main.cc @@ -0,0 +1,49 @@ +/// @author Luai Bashar +/// @date 2024-11-05 + +#include + +#include "app.h" +#include "bindings.h" +#include "shared/comms/can/can_bus.h" +#include "generated/can/error_msg_registry.h" + +// Initializing can bus that sends the error message +generated::can::ErrorMsgRegistry error_can_registry{}; +shared::can::CanBus error_can_bus{ + bindings::error_can_base, + error_can_registry, +}; + +int main(void) { + // Initialize the CLI and milliseconds to repeat by + bindings::Initialize(); + uint32_t tick_duration = 100; + + // Initialize the error object that sets/sends each error + ErrorHandler error_message{}; + + while (true) { + error_can_bus.Update(); + + // Test #1: Iterate through each error, setting it and sending it + for (int i = 0; i < 64; i++) { + Error error = static_cast(i); + error_message.SetError(error); + error_message.SendError(error_can_bus); + } + + // Test #2: Set random errors using the enum + error_message.SetError(Error::kError0); + error_message.SetError(Error::kError5); + error_message.SetError(Error::kError10); + error_message.SetError(Error::kError15); + error_message.SetError(Error::kError20); + error_message.SendError(error_can_bus); + + // Wait for 100ms before repeating the process + bindings::TickBlocking(tick_duration); + } + + return 0; +} \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/platforms/cli/CMakeLists.txt b/firmware/projects/Demo/CANErrors/platforms/cli/CMakeLists.txt new file mode 100644 index 000000000..6748669b7 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/platforms/cli/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(bindings PRIVATE bindings.cc) + +target_link_libraries(bindings PUBLIC mcal-cli) \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/platforms/cli/bindings.cc b/firmware/projects/Demo/CANErrors/platforms/cli/bindings.cc new file mode 100644 index 000000000..53df07dd2 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/platforms/cli/bindings.cc @@ -0,0 +1,34 @@ +/// @author Luai Bashar +/// @date 2024-11-05 + +#include +#include + +#include "mcal/cli/periph/can.h" +#include "shared/periph/can.h" + +#include "../../generated/can/error_can_messages.h" +#include "shared/comms/can/can_bus.h" + +namespace mcal { + using namespace cli::periph; + + CanBase error_can_base{"vcan0"}; +} + +namespace bindings { + shared::periph::CanBase& error_can_base = mcal::error_can_base; + + // Simulates a sleep, waiting for inputted ticks ms + void TickBlocking(uint32_t ticks) { + std::chrono::milliseconds duration(ticks); + + std::this_thread::sleep_for(duration); + } + + // Initializes the can/CLI outputs + void Initialize() { + mcal::error_can_base.Setup(); + std::cout << "Initializing CLI..." << std::endl; + } +} \ No newline at end of file diff --git a/firmware/projects/Demo/CANErrors/platforms/cli/mcal_conf.cmake b/firmware/projects/Demo/CANErrors/platforms/cli/mcal_conf.cmake new file mode 100644 index 000000000..a30e90e12 --- /dev/null +++ b/firmware/projects/Demo/CANErrors/platforms/cli/mcal_conf.cmake @@ -0,0 +1 @@ +set(MCAL cli) \ No newline at end of file