Got MCP2521 to work

This commit is contained in:
AlexanderHD27
2024-11-06 22:01:28 +01:00
parent 4bfb1f533e
commit e7a0035041
17 changed files with 525 additions and 70 deletions

View File

@@ -21,6 +21,9 @@
"future": "cpp", "future": "cpp",
"bitset": "cpp", "bitset": "cpp",
"string_view": "cpp", "string_view": "cpp",
"regex": "cpp" "regex": "cpp",
"array": "cpp",
"string": "cpp",
"span": "cpp"
} }
} }

View File

@@ -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);

View File

@@ -1,5 +1,7 @@
idf_component_register(SRCS idf_component_register(SRCS
"interface_commands.cpp" "interface_commands.cpp"
"interface_commands_complex.cpp"
"interface_interrupts.cpp"
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
REQUIRES driver REQUIRES driver
REQUIRES mcp2521_hardware_interface REQUIRES mcp2521_hardware_interface

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include <stdint.h>
#define MCP2521_BFPCTRL 0x0C #define MCP2521_BFPCTRL 0x0C
#define MCP2521_BFPCTRL_B1BFS (1 << 5) #define MCP2521_BFPCTRL_B1BFS (1 << 5)
@@ -110,6 +111,10 @@ struct CANSTAT_Register {
#define MCP2521_TXB0CTRL_TXP1 (1 << 1) #define MCP2521_TXB0CTRL_TXP1 (1 << 1)
#define MCP2521_TXB0CTRL_TXP0 (1 << 0) #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 0x40
#define MCP2521_TXB1CTRL_ABTF (1 << 6) #define MCP2521_TXB1CTRL_ABTF (1 << 6)
#define MCP2521_TXB1CTRL_MLOA (1 << 5) #define MCP2521_TXB1CTRL_MLOA (1 << 5)
@@ -161,4 +166,27 @@ struct TXBnCTRL_Register {
#define MCP2521_OP_RTS 0b10000000 #define MCP2521_OP_RTS 0b10000000
#define MCP2521_OP_READ_STATUS 0b10100000 #define MCP2521_OP_READ_STATUS 0b10100000
#define MCP2521_OP_RX_STATUS 0b10110000 #define MCP2521_OP_RX_STATUS 0b10110000
#define MCP2521_OP_BIT_MODIFY 0b00000101 #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

View File

@@ -21,15 +21,55 @@ enum MCP2521_BUFFER_TYPE {
DATA = 1 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 { class MCP2521_Command_Interface {
private: private:
MCP2521_Hardware_Handle * hardware_handle; 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: public:
MCP2521_Command_Interface( MCP2521_Command_Interface(
MCP2521_Hardware_Handle * hardware_handle MCP2521_Hardware_Handle * hardware_handle
); );
void handleInterrupt();
void reset(); void reset();
void read_reg(uint8_t address, uint8_t *data, size_t length); void read_reg(uint8_t address, uint8_t *data, size_t length);
@@ -49,5 +89,45 @@ public:
uint8_t read_rx_status(); uint8_t read_rx_status();
void bit_modify(uint8_t address, uint8_t mask, uint8_t data); 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);
}; };

View File

@@ -9,8 +9,6 @@ class MCP2515 {
private: private:
public: public:
MCP2515(); MCP2515();
~MCP2515(); ~MCP2515();

View File

@@ -3,10 +3,34 @@
#include "mcp2521.hpp" #include "mcp2521.hpp"
#include "mcp2521_addresses.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_Command_Interface::MCP2521_Command_Interface(
MCP2521_Hardware_Handle * hardware_handle MCP2521_Hardware_Handle * hardware_handle
) { ) {
this->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() { 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) { 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); hardware_handle->write(MCP2521_OP_LOAD_TX_BUFFER | address, data, length);
} }

View File

@@ -0,0 +1,123 @@
#include <cstring>
#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);
}

View File

@@ -0,0 +1,114 @@
#include "mcp2521.hpp"
#include "mcp2521_addresses.hpp"
#include <stdio.h>
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);
}

View File

@@ -1,4 +1,5 @@
idf_component_register(SRCS "esp_implementation_init.cpp" idf_component_register(SRCS "esp_implementation_init.cpp"
"esp_implementation_cmd.cpp" "esp_implementation_cmd.cpp"
"esp_implementation_int.cpp"
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
REQUIRES driver) REQUIRES driver)

View File

@@ -1,8 +1,17 @@
#include "mcp2521_hardware_handle.hpp" #include "mcp2521_hardware_handle.hpp"
const uint8_t null_buffer[32] = {0};
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
#include "mcp2521_hardware_esp.hpp" #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) { void MCP2521_Hardware_Handle_ESP::execute(uint8_t cmd) {
spi_transaction_ext_t t = { spi_transaction_ext_t t = {
.base = { .base = {
@@ -19,7 +28,7 @@ void MCP2521_Hardware_Handle_ESP::execute(uint8_t cmd) {
.dummy_bits = 0, .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) { 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, .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) { 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, .addr = address,
.length = 8*length, .length = 8*length,
.rxlength = 8*length, .rxlength = 8*length,
.tx_buffer = NULL, .tx_buffer = null_buffer,
.rx_buffer = data .rx_buffer = data
}, },
.command_bits = 8, .command_bits = 8,
.address_bits = 0, .address_bits = 8,
.dummy_bits = 0, .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) { 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, .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) { 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, .addr = address,
.length = 8, .length = 8,
.rxlength = 8, .rxlength = 8,
.tx_buffer = NULL, .tx_buffer = null_buffer,
.rx_buffer = &result .rx_buffer = &result
}, },
.command_bits = 8, .command_bits = 8,
@@ -96,7 +105,7 @@ uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd, uint8_t address) {
.dummy_bits = 0, .dummy_bits = 0,
}; };
spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); spi_transmit((spi_transaction_t*)(&t));
return result; return result;
} }
@@ -109,7 +118,7 @@ uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd) {
.addr = 0, .addr = 0,
.length = 8, .length = 8,
.rxlength = 8, .rxlength = 8,
.tx_buffer = NULL, .tx_buffer = null_buffer,
.rx_buffer = &result .rx_buffer = &result
}, },
.command_bits = 8, .command_bits = 8,
@@ -117,7 +126,7 @@ uint8_t MCP2521_Hardware_Handle_ESP::read(uint8_t cmd) {
.dummy_bits = 0, .dummy_bits = 0,
}; };
spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); spi_transmit((spi_transaction_t*)(&t));
return result; return result;
} }
@@ -138,7 +147,7 @@ void MCP2521_Hardware_Handle_ESP::write(uint8_t cmd, uint8_t *data, size_t lengt
.dummy_bits = 0, .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) { 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, .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) { 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, .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) { 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, .dummy_bits = 0,
}; };
spi_device_transmit(this->spi_device_handle, (spi_transaction_t*)(&t)); spi_transmit((spi_transaction_t*)(&t));
} }
#endif #endif

View File

@@ -2,8 +2,12 @@
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
#include "mcp2521_hardware_esp.hpp" #include "mcp2521_hardware_esp.hpp"
#include "driver/gpio.h"
#include <string.h> #include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
MCP2521_Hardware_Handle_ESP::MCP2521_Hardware_Handle_ESP( MCP2521_Hardware_Handle_ESP::MCP2521_Hardware_Handle_ESP(
spi_host_device_t spi_host, spi_host_device_t spi_host,
spi_bus_config_t *bus_config, 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( void MCP2521_Hardware_Handle_ESP::initSPIBus(
spi_host_device_t spi_host, spi_host_device_t spi_host,
gpio_num_t mosi, 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); 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() { spi_bus_config_t * MCP2521_Hardware_Handle_ESP::getSPI_bus_config() {

View File

@@ -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

View File

@@ -5,6 +5,8 @@
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/spi_master.h" #include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
class MCP2521_Hardware_Handle_ESP : public MCP2521_Hardware_Handle { class MCP2521_Hardware_Handle_ESP : public MCP2521_Hardware_Handle {
char spi_tmp_buffer; 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_interface_config_t spi_device_config;
spi_device_handle_t spi_device_handle; 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: public:
MCP2521_Hardware_Handle_ESP( MCP2521_Hardware_Handle_ESP(
spi_host_device_t spi_host, spi_host_device_t spi_host,
@@ -52,6 +63,10 @@ public:
spi_bus_config_t * getSPI_bus_config(); spi_bus_config_t * getSPI_bus_config();
// ISR Stuff
void isr_can_interrupt();
void handleIntteruptTaskFn();
// Inherited from MCP2521_Hardware_Handle // Inherited from MCP2521_Hardware_Handle
void execute(uint8_t cmd); void execute(uint8_t cmd);
void execute(uint8_t cmd, uint8_t address); 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, size_t length);
void write(uint8_t cmd, uint8_t data, uint8_t address); void write(uint8_t cmd, uint8_t data, uint8_t address);
void write(uint8_t cmd, uint8_t data); void write(uint8_t cmd, uint8_t data);
void registerIntHandler(intHandlerFunction_t handler, void * arg);
}; };
#endif #endif

View File

@@ -2,8 +2,12 @@
#include <cstdint> #include <cstdint>
#include <strings.h> #include <strings.h>
typedef void (*intHandlerFunction_t)(void *);
class MCP2521_Hardware_Handle { class MCP2521_Hardware_Handle {
public: public:
virtual void registerIntHandler(intHandlerFunction_t handler, void * arg) = 0;
virtual void execute(uint8_t cmd) = 0; virtual void execute(uint8_t cmd) = 0;
virtual void execute(uint8_t cmd, uint8_t address) = 0; virtual void execute(uint8_t cmd, uint8_t address) = 0;

View File

@@ -31,6 +31,21 @@
#define EXTERNAL_TRIGGER GPIO_NUM_26 #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() { extern "C" void app_main() {
printf("Hello world!\n"); printf("Hello world!\n");
@@ -57,24 +72,28 @@ extern "C" void app_main() {
MCP2521_Command_Interface mcp2521(&hardware_mcp2521); MCP2521_Command_Interface mcp2521(&hardware_mcp2521);
uint8_t data[4] = {0xf0, 0x42, 0x13, 0x37};
gpio_set_level(EXTERNAL_TRIGGER, false); gpio_set_level(EXTERNAL_TRIGGER, false);
printf("CANCTRL: %x\n", mcp2521.read_reg(MCP2521_CANCTRL)); mcp2521.reset();
printf("RX_STATUS: %x\n", mcp2521.read_rx_status()); mcp2521.enable_interrupts(true, true, true, true, true, true, true, true);
printf("STATUS: %x\n", mcp2521.read_status());
uint8_t data[16]; mcp2521.register_rx0_handler(onRX, &mcp2521);
hardware_mcp2521.read(MCP2521_OP_READ, data, 16, MCP2521_RXB0CTRL); mcp2521.register_rx1_handler(onRX, &mcp2521);
mcp2521.set_mode_of_operation(MCP2521_OPERATION_MODE::LOOPBACK, true);
for(int i=0; i<0x10; i++) { vTaskDelay(3 / portTICK_PERIOD_MS);
printf("%x ", i);
for(int j=0; j<8; j++) {
printf("%u", (data[i] >> (7-j)) & 1);
}
printf("\n");
}
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; bool flag = true;
while (true) { while (true) {

Binary file not shown.