diff --git a/can-interface/.vscode/settings.json b/can-interface/.vscode/settings.json index 55394fa..d4cb104 100644 --- a/can-interface/.vscode/settings.json +++ b/can-interface/.vscode/settings.json @@ -21,6 +21,9 @@ "future": "cpp", "bitset": "cpp", "string_view": "cpp", - "regex": "cpp" + "regex": "cpp", + "array": "cpp", + "string": "cpp", + "span": "cpp" } } diff --git a/can-interface/a b/can-interface/a deleted file mode 100644 index 56a7847..0000000 --- a/can-interface/a +++ /dev/null @@ -1,26 +0,0 @@ - - - - txBuffer[0] = 0b00000011; // Read Instruction - txBuffer[1] = 0x0f; // CANCTRL Register Address - - spi_transaction_t transaction0 = { // RESET - .cmd = 0b11000000, - .length = 3 * 8, - .rxlength = 3 * 8, - .tx_buffer = txBuffer, - .rx_buffer = rxBuffer - }; - - spi_transaction_t transaction1 = { // READ STAT/S - .cmd = 0b10110000, - .length = 2 * 8, - .rxlength = 2 * 8, - .tx_buffer = txBuffer, - .rx_buffer = rxBuffer - }; - - - vTaskDelay(100 / portTICK_PERIOD_MS); - gpio_set_level(EXTERNAL_TRIGGER, false); - spi_device_transmit(mp2125_handle, &transaction0); \ No newline at end of file diff --git a/can-interface/components/mcp2521/CMakeLists.txt b/can-interface/components/mcp2521/CMakeLists.txt index ece7c6f..2fcfa42 100644 --- a/can-interface/components/mcp2521/CMakeLists.txt +++ b/can-interface/components/mcp2521/CMakeLists.txt @@ -1,5 +1,7 @@ idf_component_register(SRCS "interface_commands.cpp" + "interface_commands_complex.cpp" + "interface_interrupts.cpp" INCLUDE_DIRS "include" REQUIRES driver REQUIRES mcp2521_hardware_interface diff --git a/can-interface/components/mcp2521/include/mcp2521_addresses.hpp b/can-interface/components/mcp2521/include/mcp2521_addresses.hpp index 58cad00..d87ba99 100644 --- a/can-interface/components/mcp2521/include/mcp2521_addresses.hpp +++ b/can-interface/components/mcp2521/include/mcp2521_addresses.hpp @@ -1,4 +1,5 @@ #pragma once +#include #define MCP2521_BFPCTRL 0x0C #define MCP2521_BFPCTRL_B1BFS (1 << 5) @@ -110,6 +111,10 @@ struct CANSTAT_Register { #define MCP2521_TXB0CTRL_TXP1 (1 << 1) #define MCP2521_TXB0CTRL_TXP0 (1 << 0) +#define MCP2521_TXB0DLC 0x35 +#define MCP2521_TXB1DLC 0x45 +#define MCP2521_TXB2DLC 0x55 + #define MCP2521_TXB1CTRL 0x40 #define MCP2521_TXB1CTRL_ABTF (1 << 6) #define MCP2521_TXB1CTRL_MLOA (1 << 5) @@ -161,4 +166,27 @@ struct TXBnCTRL_Register { #define MCP2521_OP_RTS 0b10000000 #define MCP2521_OP_READ_STATUS 0b10100000 #define MCP2521_OP_RX_STATUS 0b10110000 -#define MCP2521_OP_BIT_MODIFY 0b00000101 \ No newline at end of file +#define MCP2521_OP_BIT_MODIFY 0b00000101 + +#define MCP2521_TXB0SIDH 0x31 +#define MCP2521_TXB1SIDH 0x41 +#define MCP2521_TXB2SIDH 0x51 + +#define MCP2521_TXB0SIDL 0x32 +#define MCP2521_TXB1SIDL 0x42 +#define MCP2521_TXB2SIDL 0x52 + +#define MCP2521_RXB0SIDH 0x61 +#define MCP2521_RXB1SIDH 0x71 + +#define MCP2521_RXB0SIDL 0x62 +#define MCP2521_RXB1SIDL 0x72 + +#define MCP2521_RXB0EID8 0x63 +#define MCP2521_RXB1EID8 0x73 + +#define MCP2521_RXB0EID0 0x64 +#define MCP2521_RXB1EID0 0x74 + +#define MCP2521_RXB0DLC 0x65 +#define MCP2521_RXB1DLC 0x75 \ No newline at end of file diff --git a/can-interface/components/mcp2521/include/mcp2521_command.hpp b/can-interface/components/mcp2521/include/mcp2521_command.hpp index 4391147..471ce0b 100644 --- a/can-interface/components/mcp2521/include/mcp2521_command.hpp +++ b/can-interface/components/mcp2521/include/mcp2521_command.hpp @@ -21,15 +21,55 @@ enum MCP2521_BUFFER_TYPE { DATA = 1 }; +enum MCP2521_OPERATION_MODE { + NORMAL = 0b000, + SLEEP = 0b001, + LOOPBACK = 0b010, + LISTEN_ONLY = 0b011, + CONFIG = 0b100 +}; + +struct rx_info { + bool extended; + + uint16_t id; + uint32_t extended_id; + + bool rtr; + bool extended_rtr; + + uint8_t length; +}; + class MCP2521_Command_Interface { private: MCP2521_Hardware_Handle * hardware_handle; + + intHandlerFunction_t rx0_handler; + intHandlerFunction_t rx1_handler; + intHandlerFunction_t tx0_handler; + intHandlerFunction_t tx1_handler; + intHandlerFunction_t tx2_handler; + intHandlerFunction_t error_handler; + intHandlerFunction_t wakeup_handler; + intHandlerFunction_t message_error_handler; + + void * rx0_handler_arg; + void * rx1_handler_arg; + void * tx0_handler_arg; + void * tx1_handler_arg; + void * tx2_handler_arg; + void * error_handler_arg; + void * wakeup_handler_arg; + void * message_error_handler_arg; public: MCP2521_Command_Interface( MCP2521_Hardware_Handle * hardware_handle ); + void handleInterrupt(); + void reset(); void read_reg(uint8_t address, uint8_t *data, size_t length); @@ -49,5 +89,45 @@ public: uint8_t read_rx_status(); void bit_modify(uint8_t address, uint8_t mask, uint8_t data); + + // More Complex Commands + void set_tx_id(MCP2521_TX_BUFFER buffer, uint16_t id, bool extended); + + /** + * @brief Loads the Data Length Code register for the specified buffer + * + * @param buffer What Buffer to load the DLC register for + * @param length How many bytes are in the message (0-8) + * @param rtr: Remote Transmission Request + */ + void set_DLC_reg(MCP2521_TX_BUFFER buffer, uint8_t length, bool rtr); + + /** + * @brief Loads the data and id into the specified buffer + * + * @param buffer + * @param id + * @param data + * @param length + */ + void prepare_tx(MCP2521_TX_BUFFER buffer, uint32_t id, uint8_t *data, size_t length, bool rtr, bool extended); + + void set_mode_of_operation(MCP2521_OPERATION_MODE mode, bool singleshot); + void set_singleshot_mode(bool enable); + + void enable_interrupts(bool MessageError, bool ErrorInterrupt, bool WakeUp, bool TXB0, bool TXB1, bool TXB2, bool RXB0, bool RXB1); + rx_info get_rx_id(MCP2521_RX_BUFFER buffer); + + + + // Registering Handlers for Interrupts + void register_rx0_handler(intHandlerFunction_t handler, void * arg); + void register_rx1_handler(intHandlerFunction_t handler, void * arg); + void register_tx0_handler(intHandlerFunction_t handler, void * arg); + void register_tx1_handler(intHandlerFunction_t handler, void * arg); + void register_tx2_handler(intHandlerFunction_t handler, void * arg); + void register_error_handler(intHandlerFunction_t handler, void * arg); + void register_wakeup_handler(intHandlerFunction_t handler, void * arg); + void register_message_error_handler(intHandlerFunction_t handler, void * arg); }; diff --git a/can-interface/components/mcp2521/include/mcp2521_register.hpp b/can-interface/components/mcp2521/include/mcp2521_register.hpp index ed98e0a..f4b5702 100644 --- a/can-interface/components/mcp2521/include/mcp2521_register.hpp +++ b/can-interface/components/mcp2521/include/mcp2521_register.hpp @@ -9,8 +9,6 @@ class MCP2515 { private: - - public: MCP2515(); ~MCP2515(); diff --git a/can-interface/components/mcp2521/interface_commands.cpp b/can-interface/components/mcp2521/interface_commands.cpp index 9c8795c..dfc25cc 100644 --- a/can-interface/components/mcp2521/interface_commands.cpp +++ b/can-interface/components/mcp2521/interface_commands.cpp @@ -3,10 +3,34 @@ #include "mcp2521.hpp" #include "mcp2521_addresses.hpp" +void runIntHandler(void *arg) { + MCP2521_Command_Interface *command_interface = (MCP2521_Command_Interface *)arg; + command_interface->handleInterrupt(); +} + MCP2521_Command_Interface::MCP2521_Command_Interface( MCP2521_Hardware_Handle * hardware_handle ) { this->hardware_handle = hardware_handle; + this->hardware_handle->registerIntHandler(runIntHandler, (void *)this); + + rx0_handler = NULL; + rx1_handler = NULL; + tx0_handler = NULL; + tx1_handler = NULL; + tx2_handler = NULL; + error_handler = NULL; + wakeup_handler = NULL; + message_error_handler = NULL; + + rx0_handler_arg = NULL; + rx1_handler_arg = NULL; + tx0_handler_arg = NULL; + tx1_handler_arg = NULL; + tx2_handler_arg = NULL; + error_handler_arg = NULL; + wakeup_handler_arg = NULL; + message_error_handler_arg = NULL; } void MCP2521_Command_Interface::reset() { @@ -35,7 +59,7 @@ void MCP2521_Command_Interface::write_reg(uint8_t address, uint8_t data) { } void MCP2521_Command_Interface::write_tx_buf(MCP2521_TX_BUFFER buffer, MCP2521_BUFFER_TYPE type, uint8_t *data, size_t length) { - uint8_t address = buffer | (type << 2); + uint8_t address = (buffer << 1) | (type); hardware_handle->write(MCP2521_OP_LOAD_TX_BUFFER | address, data, length); } diff --git a/can-interface/components/mcp2521/interface_commands_complex.cpp b/can-interface/components/mcp2521/interface_commands_complex.cpp new file mode 100644 index 0000000..4a10a6a --- /dev/null +++ b/can-interface/components/mcp2521/interface_commands_complex.cpp @@ -0,0 +1,123 @@ +#include + +#include "mcp2521.hpp" +#include "mcp2521_addresses.hpp" + +void MCP2521_Command_Interface::set_tx_id(MCP2521_TX_BUFFER buffer, uint16_t id, bool extended) { + uint8_t addr_offset = 0; + switch (buffer) + { + case MCP2521_TX_BUFFER::TXB0: + addr_offset = 0x00; + break; + case MCP2521_TX_BUFFER::TXB1: + addr_offset = 0x10; + break; + case MCP2521_TX_BUFFER::TXB2: + addr_offset = 0x20; + break; + } + + uint8_t upper_id = (id >> 3) & 0xFF; + uint8_t lower_id = ((id & 0b111) << 5); + + if(extended) { + lower_id |= 0b1000; + lower_id |= (id >> 8) & 0b11; + } + + write_reg(MCP2521_TXB0SIDH | addr_offset, upper_id); + write_reg(MCP2521_TXB0SIDL | addr_offset, lower_id); +} + +// 00110101 0x35 +// 01000101 0x45 +// 01010101 0x55 + +void MCP2521_Command_Interface::set_DLC_reg(MCP2521_TX_BUFFER buffer, uint8_t length, bool rtr) { + uint8_t data = length; + + if (rtr) + data |= 0b01000000; + + uint8_t reg_address = 0; + + switch (buffer) { + case MCP2521_TX_BUFFER::TXB0: + reg_address = MCP2521_TXB0DLC; + break; + case MCP2521_TX_BUFFER::TXB1: + reg_address = MCP2521_TXB1DLC; + break; + case MCP2521_TX_BUFFER::TXB2: + reg_address = MCP2521_TXB2DLC; + break; + } + + write_reg(reg_address, data); +} + +void MCP2521_Command_Interface::set_mode_of_operation(MCP2521_OPERATION_MODE mode, bool singleshot) { + + uint8_t single = singleshot ? 0b00001000 : 0x0; + + bit_modify(MCP2521_CANCTRL, 0b11101000 , (mode << 5) | single); +} + +void MCP2521_Command_Interface::set_singleshot_mode(bool enable) { + uint8_t data = enable ? 0x08 : 0x00; + bit_modify(MCP2521_CANCTRL, 0x08, data); +} + +void MCP2521_Command_Interface::enable_interrupts(bool MessageError, bool ErrorInterrupt, bool WakeUp, bool TXB0, bool TXB1, bool TXB2, bool RXB0, bool RXB1) { + uint8_t interrupt_flags = 0; + + if (MessageError) interrupt_flags |= 0b10000000; + if (WakeUp) interrupt_flags |= 0b01000000; + if (ErrorInterrupt) interrupt_flags |= 0b00100000; + if (TXB2) interrupt_flags |= 0b00010000; + if (TXB1) interrupt_flags |= 0b00001000; + if (TXB0) interrupt_flags |= 0b00000100; + if (RXB1) interrupt_flags |= 0b00000010; + if (RXB0) interrupt_flags |= 0b00000001; + + write_reg(MCP2521_CANINTE, interrupt_flags); +} + +rx_info MCP2521_Command_Interface::get_rx_id(MCP2521_RX_BUFFER buffer) { + uint8_t data[5]; + uint8_t addr_offset = MCP2521_RXB0SIDH; + + switch (buffer) { + case MCP2521_RX_BUFFER::RXB0: + addr_offset |= 0x00; + break; + case MCP2521_RX_BUFFER::RXB1: + addr_offset |= 0x10; + break; + } + + read_reg(addr_offset, data, 5); + + rx_info res; + res.extended = data[1] & 0b1000; + res.id = (data[0] << 3) | (data[1] >> 5); + res.extended_id = ((data[1] & 0b11) << 16) | (data[2] << 8) | data[3]; + res.rtr = data[1] & 0b10000; + res.extended_rtr = (data[4] & 0b1000000); + res.length = (data[4] & 0b1111); + + return res; +} + +void MCP2521_Command_Interface::prepare_tx( + MCP2521_TX_BUFFER buffer, + uint32_t id, + uint8_t *data, + size_t length, + bool rtr, bool extended) { + + set_tx_id(buffer, id, extended); + set_DLC_reg(buffer, length, rtr); + write_tx_buf(buffer, MCP2521_BUFFER_TYPE::DATA, data, length); +} \ No newline at end of file diff --git a/can-interface/components/mcp2521/interface_interrupts.cpp b/can-interface/components/mcp2521/interface_interrupts.cpp new file mode 100644 index 0000000..bb47cf4 --- /dev/null +++ b/can-interface/components/mcp2521/interface_interrupts.cpp @@ -0,0 +1,114 @@ +#include "mcp2521.hpp" +#include "mcp2521_addresses.hpp" +#include + +void MCP2521_Command_Interface::register_rx0_handler(intHandlerFunction_t handler, void* args) { + rx0_handler = handler; + rx0_handler_arg = args; +} + +void MCP2521_Command_Interface::register_rx1_handler(intHandlerFunction_t handler, void* args) { + rx1_handler = handler; + rx1_handler_arg = args; +} + +void MCP2521_Command_Interface::register_tx0_handler(intHandlerFunction_t handler, void* args) { + tx0_handler = handler; + tx0_handler_arg = args; +} + +void MCP2521_Command_Interface::register_tx1_handler(intHandlerFunction_t handler, void* args) { + tx1_handler = handler; + tx1_handler_arg = args; +} + +void MCP2521_Command_Interface::register_tx2_handler(intHandlerFunction_t handler, void* args) { + tx2_handler = handler; + tx2_handler_arg = args; +} + +void MCP2521_Command_Interface::register_error_handler(intHandlerFunction_t handler, void* args) { + error_handler = handler; + error_handler_arg = args; +} + +void MCP2521_Command_Interface::register_wakeup_handler(intHandlerFunction_t handler, void* args) { + wakeup_handler = handler; + wakeup_handler_arg = args; +} + +void MCP2521_Command_Interface::register_message_error_handler(intHandlerFunction_t handler, void* args) { + message_error_handler = handler; + message_error_handler_arg = args; +} + +void MCP2521_Command_Interface::handleInterrupt() { + uint8_t flags = read_reg(MCP2521_CANINTF); + uint8_t clearBits = 0; + + if (flags & MCP2521_CANINTF_RX0IF) { + if (rx0_handler) { + rx0_handler(rx0_handler_arg); + } + flags &= ~MCP2521_CANINTF_RX0IF; + clearBits |= MCP2521_CANINTF_RX0IF; + } + + if (flags & MCP2521_CANINTF_RX1IF) { + if (rx1_handler) { + rx1_handler(rx1_handler_arg); + } + flags &= ~MCP2521_CANINTF_RX1IF; + clearBits |= MCP2521_CANINTF_RX1IF; + } + + if (flags & MCP2521_CANINTF_TX0IF) { + if (tx0_handler) { + tx0_handler(tx0_handler_arg); + } + flags &= ~MCP2521_CANINTF_TX0IF; + clearBits |= MCP2521_CANINTF_TX0IF; + } + + if (flags & MCP2521_CANINTF_TX1IF) { + if (tx1_handler) { + tx1_handler(tx1_handler_arg); + } + flags &= ~MCP2521_CANINTF_TX1IF; + clearBits |= MCP2521_CANINTF_TX1IF; + } + + if (flags & MCP2521_CANINTF_TX2IF) { + if (tx2_handler) { + tx2_handler(tx2_handler_arg); + } + flags &= ~MCP2521_CANINTF_TX2IF; + clearBits |= MCP2521_CANINTF_TX2IF; + } + + if (flags & MCP2521_CANINTF_ERRIF) { + if (error_handler) { + error_handler(error_handler_arg); + } + flags &= ~MCP2521_CANINTF_ERRIF; + clearBits |= MCP2521_CANINTF_ERRIF; + } + + if (flags & MCP2521_CANINTF_WAKIF) { + if (wakeup_handler) { + wakeup_handler(wakeup_handler_arg); + } + flags &= ~MCP2521_CANINTF_WAKIF; + clearBits |= MCP2521_CANINTF_WAKIF; + } + + if (flags & MCP2521_CANINTF_MERRF) { + if (message_error_handler) { + message_error_handler(message_error_handler_arg); + } + flags &= ~MCP2521_CANINTF_MERRF; + clearBits |= MCP2521_CANINTF_MERRF; + } + + bit_modify(MCP2521_CANINTF, clearBits, 0); +} \ No newline at end of file diff --git a/can-interface/components/mcp2521_hardware_interface/CMakeLists.txt b/can-interface/components/mcp2521_hardware_interface/CMakeLists.txt index ca3d4db..abe86ac 100644 --- a/can-interface/components/mcp2521_hardware_interface/CMakeLists.txt +++ b/can-interface/components/mcp2521_hardware_interface/CMakeLists.txt @@ -1,4 +1,5 @@ idf_component_register(SRCS "esp_implementation_init.cpp" "esp_implementation_cmd.cpp" + "esp_implementation_int.cpp" INCLUDE_DIRS "include" REQUIRES driver) \ No newline at end of file diff --git a/can-interface/components/mcp2521_hardware_interface/esp_implementation_cmd.cpp b/can-interface/components/mcp2521_hardware_interface/esp_implementation_cmd.cpp index c3196e0..e5bc557 100644 --- a/can-interface/components/mcp2521_hardware_interface/esp_implementation_cmd.cpp +++ b/can-interface/components/mcp2521_hardware_interface/esp_implementation_cmd.cpp @@ -1,8 +1,17 @@ #include "mcp2521_hardware_handle.hpp" + +const uint8_t null_buffer[32] = {0}; + #ifdef ESP_PLATFORM #include "mcp2521_hardware_esp.hpp" +void MCP2521_Hardware_Handle_ESP::spi_transmit(spi_transaction_t *t) { + xSemaphoreTake(spiMutex, portMAX_DELAY); + spi_device_transmit(this->spi_device_handle, t); + xSemaphoreGive(spiMutex); +} + void MCP2521_Hardware_Handle_ESP::execute(uint8_t cmd) { spi_transaction_ext_t t = { .base = { @@ -19,7 +28,7 @@ void MCP2521_Hardware_Handle_ESP::execute(uint8_t cmd) { .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } void MCP2521_Hardware_Handle_ESP::execute(uint8_t cmd, uint8_t address) { @@ -38,7 +47,7 @@ void MCP2521_Hardware_Handle_ESP::execute(uint8_t cmd, uint8_t address) { .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } void MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t *data, size_t length, uint8_t address) { @@ -49,15 +58,15 @@ void MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t *data, size_t length .addr = address, .length = 8*length, .rxlength = 8*length, - .tx_buffer = NULL, + .tx_buffer = null_buffer, .rx_buffer = data }, .command_bits = 8, - .address_bits = 0, + .address_bits = 8, .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } void MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t *data, size_t length) { @@ -76,7 +85,7 @@ void MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t *data, size_t length .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t address) { @@ -88,7 +97,7 @@ uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t address) { .addr = address, .length = 8, .rxlength = 8, - .tx_buffer = NULL, + .tx_buffer = null_buffer, .rx_buffer = &result }, .command_bits = 8, @@ -96,7 +105,7 @@ uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t address) { .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); return result; } @@ -109,7 +118,7 @@ uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd) { .addr = 0, .length = 8, .rxlength = 8, - .tx_buffer = NULL, + .tx_buffer = null_buffer, .rx_buffer = &result }, .command_bits = 8, @@ -117,7 +126,7 @@ uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd) { .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); return result; } @@ -138,7 +147,7 @@ void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t *data, size_t lengt .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t *data, size_t length) { @@ -157,7 +166,7 @@ void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t *data, size_t lengt .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t data, uint8_t address) { @@ -176,7 +185,7 @@ void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t data, uint8_t addre .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t data) { @@ -195,7 +204,7 @@ void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t data) { .dummy_bits = 0, }; - spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); + spi_transmit((spi_transaction_t*)(&t)); } #endif diff --git a/can-interface/components/mcp2521_hardware_interface/esp_implementation_init.cpp b/can-interface/components/mcp2521_hardware_interface/esp_implementation_init.cpp index e981a34..b2610b8 100644 --- a/can-interface/components/mcp2521_hardware_interface/esp_implementation_init.cpp +++ b/can-interface/components/mcp2521_hardware_interface/esp_implementation_init.cpp @@ -2,8 +2,12 @@ #ifdef ESP_PLATFORM #include "mcp2521_hardware_esp.hpp" +#include "driver/gpio.h" #include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + MCP2521_Hardware_Handle_ESP::MCP2521_Hardware_Handle_ESP( spi_host_device_t spi_host, spi_bus_config_t *bus_config, @@ -34,18 +38,6 @@ MCP2521_Hardware_Handle_ESP::~MCP2521_Hardware_Handle_ESP() { } -void MCP2521_Hardware_Handle_ESP::initPins( - gpio_num_t int_pin -) { - gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = 1 << int_pin; - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); -} - void MCP2521_Hardware_Handle_ESP::initSPIBus( spi_host_device_t spi_host, gpio_num_t mosi, @@ -89,6 +81,8 @@ void MCP2521_Hardware_Handle_ESP::initSPIDevice( }; spi_bus_add_device(spi_host, &this->spi_device_config, &this->spi_device_handle); + + spiMutex = xSemaphoreCreateMutex(); } spi_bus_config_t * MCP2521_Hardware_Handle_ESP::getSPI_bus_config() { diff --git a/can-interface/components/mcp2521_hardware_interface/esp_implementation_int.cpp b/can-interface/components/mcp2521_hardware_interface/esp_implementation_int.cpp new file mode 100644 index 0000000..a186324 --- /dev/null +++ b/can-interface/components/mcp2521_hardware_interface/esp_implementation_int.cpp @@ -0,0 +1,65 @@ +#include "mcp2521_hardware_handle.hpp" + +#ifdef ESP_PLATFORM +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "mcp2521_hardware_esp.hpp" + +static void IRAM_ATTR gpio_isr_can_handler(void* arg) { + MCP2521_Hardware_Handle_ESP * handle = (MCP2521_Hardware_Handle_ESP *)arg; + handle->isr_can_interrupt(); +} + +static void handleInteruptTaskCallerFn(void *arg) { + MCP2521_Hardware_Handle_ESP * handle = (MCP2521_Hardware_Handle_ESP *)arg; + handle->handleIntteruptTaskFn(); +} + +void MCP2521_Hardware_Handle_ESP::initPins( + gpio_num_t int_pin +) { + canInterruptSemaphore = xSemaphoreCreateBinary(); + + gpio_config_t io_conf; + io_conf.intr_type = GPIO_INTR_NEGEDGE; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pin_bit_mask = 1 << int_pin; + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.pull_up_en = GPIO_PULLUP_ENABLE; + gpio_config(&io_conf); + + gpio_install_isr_service(0); + gpio_isr_handler_add(int_pin, gpio_isr_can_handler, this); + + xTaskCreate( + (TaskFunction_t)&handleInteruptTaskCallerFn, + "canInterruptTask", + 2048, + this, + 5, + &canInterruptTaskHandle + ); +} + +void MCP2521_Hardware_Handle_ESP::handleIntteruptTaskFn() { + while(true) { + xSemaphoreTake(canInterruptSemaphore, portMAX_DELAY); + intHandler(intHandlerArg); + } +} + +void MCP2521_Hardware_Handle_ESP::isr_can_interrupt() { + BaseType_t wokenTask = pdFALSE; + xSemaphoreGiveFromISR(canInterruptSemaphore, &wokenTask); + + if(wokenTask) { + portYIELD_FROM_ISR(); + } +} + +void MCP2521_Hardware_Handle_ESP::registerIntHandler(intHandlerFunction_t handler, void * arg) { + intHandlerArg = arg; + intHandler = handler; +} + +#endif \ No newline at end of file diff --git a/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_esp.hpp b/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_esp.hpp index 8cb2ab0..08df7c5 100644 --- a/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_esp.hpp +++ b/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_esp.hpp @@ -5,6 +5,8 @@ #include "driver/gpio.h" #include "driver/spi_master.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" class MCP2521_Hardware_Handle_ESP : public MCP2521_Hardware_Handle { char spi_tmp_buffer; @@ -13,6 +15,15 @@ class MCP2521_Hardware_Handle_ESP : public MCP2521_Hardware_Handle { spi_device_interface_config_t spi_device_config; spi_device_handle_t spi_device_handle; + SemaphoreHandle_t canInterruptSemaphore = NULL; + SemaphoreHandle_t spiMutex = NULL; + TaskHandle_t canInterruptTaskHandle = NULL; + + void spi_transmit(spi_transaction_t *t); + + void * intHandlerArg = NULL; + intHandlerFunction_t intHandler = NULL; + public: MCP2521_Hardware_Handle_ESP( spi_host_device_t spi_host, @@ -52,6 +63,10 @@ public: spi_bus_config_t * getSPI_bus_config(); + // ISR Stuff + void isr_can_interrupt(); + void handleIntteruptTaskFn(); + // Inherited from MCP2521_Hardware_Handle void execute(uint8_t cmd); void execute(uint8_t cmd, uint8_t address); @@ -65,6 +80,8 @@ public: void write(uint8_t cmd, uint8_t *data, size_t length); void write(uint8_t cmd, uint8_t data, uint8_t address); void write(uint8_t cmd, uint8_t data); + + void registerIntHandler(intHandlerFunction_t handler, void * arg); }; #endif diff --git a/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_handle.hpp b/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_handle.hpp index 57d884b..34ffe1c 100644 --- a/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_handle.hpp +++ b/can-interface/components/mcp2521_hardware_interface/include/mcp2521_hardware_handle.hpp @@ -2,8 +2,12 @@ #include #include +typedef void (*intHandlerFunction_t)(void *); + class MCP2521_Hardware_Handle { public: + virtual void registerIntHandler(intHandlerFunction_t handler, void * arg) = 0; + virtual void execute(uint8_t cmd) = 0; virtual void execute(uint8_t cmd, uint8_t address) = 0; diff --git a/can-interface/main/hello_world_main.cpp b/can-interface/main/hello_world_main.cpp index f8b8d1c..55f7e69 100755 --- a/can-interface/main/hello_world_main.cpp +++ b/can-interface/main/hello_world_main.cpp @@ -31,6 +31,21 @@ #define EXTERNAL_TRIGGER GPIO_NUM_26 +void onRX(void *arg) { + MCP2521_Command_Interface *mcp2521 = (MCP2521_Command_Interface *)arg; + + rx_info info = mcp2521->get_rx_id(MCP2521_RX_BUFFER::RXB0); + uint8_t data[8]; + + mcp2521->read_rx_buf(MCP2521_RX_BUFFER::RXB0, MCP2521_BUFFER_TYPE::DATA, data, info.length); + + printf("RX: (%x) ", info.id); + for (int i = 0; i < info.length; i++) { + printf("%x ", data[i]); + } + printf("\n"); +} + extern "C" void app_main() { printf("Hello world!\n"); @@ -57,24 +72,28 @@ extern "C" void app_main() { MCP2521_Command_Interface mcp2521(&hardware_mcp2521); + uint8_t data[4] = {0xf0, 0x42, 0x13, 0x37}; gpio_set_level(EXTERNAL_TRIGGER, false); - printf("CANCTRL: %x\n", mcp2521.read_reg(MCP2521_CANCTRL)); - printf("RX_STATUS: %x\n", mcp2521.read_rx_status()); - printf("STATUS: %x\n", mcp2521.read_status()); + mcp2521.reset(); + mcp2521.enable_interrupts(true, true, true, true, true, true, true, true); - uint8_t data[16]; - hardware_mcp2521.read(MCP2521_OP_READ, data, 16, MCP2521_RXB0CTRL); + mcp2521.register_rx0_handler(onRX, &mcp2521); + mcp2521.register_rx1_handler(onRX, &mcp2521); + mcp2521.set_mode_of_operation(MCP2521_OPERATION_MODE::LOOPBACK, true); - for(int i=0; i<0x10; i++) { - printf("%x ", i); - for(int j=0; j<8; j++) { - printf("%u", (data[i] >> (7-j)) & 1); - } - printf("\n"); - } + vTaskDelay(3 / portTICK_PERIOD_MS); - gpio_set_level(EXTERNAL_TRIGGER, true); + mcp2521.prepare_tx( + MCP2521_TX_BUFFER::TXB0, 0x042, data, 4, false, false); + + mcp2521.request_to_send(MCP2521_TX_BUFFER::TXB0); + + mcp2521.set_tx_id(MCP2521_TX_BUFFER::TXB0, 0x041, false); + mcp2521.request_to_send(MCP2521_TX_BUFFER::TXB0); + + + vTaskDelay(20 / portTICK_PERIOD_MS); bool flag = true; while (true) { diff --git a/can-interface/pulseView-debug-session b/can-interface/pulseView-debug-session new file mode 100644 index 0000000..8913bfb Binary files /dev/null and b/can-interface/pulseView-debug-session differ