/** * @file mcp2521_hardware_esp.hpp * @author AlexanderHD27 * @brief * @version 0.1 * @date 2024-11-16 * * @copyright Copyright (c) 2024 * */ #pragma once #include "mcp2521_hardware_handle.hpp" #ifdef ESP_PLATFORM #include "driver/gpio.h" #include "driver/spi_master.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" static void handleInteruptTaskCallerFn(void *arg); static void IRAM_ATTR gpio_isr_can_handler(void* arg); /** * @brief Hardware handle for MCP2521 over SPI on ESP32 * This is should not be used if multiple MCP2521 are on the same SPI bus */ class MCP2521_HardwareHandle_ESP : public I_MCP2521_HardwareHandle { protected: void spi_transmit(spi_transaction_t *t); /** * @brief Sempahore, that is set every time the MCP2521 triggers an interrupt by the canInterruptTaskHandle */ SemaphoreHandle_t canInterruptSemaphore = NULL; /** * @brief Handle to task that handles the MCP2521 interrupt * A Handle can be registered via the registerIntHandler method */ TaskHandle_t canInterruptTaskHandle = NULL; spi_device_handle_t spi_device_handle; private: spi_bus_config_t * spi_bus_config; char spi_tmp_buffer; spi_device_interface_config_t spi_device_config; /** * @brief Sempahore, that protects the SPI bus from being accessed by multiple tasks at the same time * */ SemaphoreHandle_t spiMutex = NULL; void * intHandlerArg = NULL; intHandlerFunction_t intHandler = NULL; public: MCP2521_HardwareHandle_ESP( spi_host_device_t spi_host, spi_bus_config_t *bus_config, gpio_num_t mosi, gpio_num_t miso, gpio_num_t sclk, gpio_num_t cs, gpio_num_t int_pin ); MCP2521_HardwareHandle_ESP( spi_host_device_t spi_host, spi_bus_config_t *bus_config, gpio_num_t cs, gpio_num_t int_pin ); static void initSPIBus( spi_host_device_t spi_host, gpio_num_t mosi, gpio_num_t miso, gpio_num_t sclk, spi_bus_config_t *bus_config ); void initSPIDevice( spi_host_device_t spi_host, gpio_num_t cs ); void initPins( gpio_num_t int_pin ); ~MCP2521_HardwareHandle_ESP(); spi_bus_config_t * getSPI_bus_config(); // ISR Stuff /** * @brief This function is called by the ISR, that is triggered by the MCP2521 * This function just set the canInterruptSemaphore, that then unblocks the canInterruptTaskHandle. * So this function should be as short as possible, let the reset of the work be done in the canInterruptTaskHandle */ void isr_can_interrupt(); /** * This is the methode run as canInterruptTaskHandle. * It should continously aquire the canInterruptSemaphore and then call the intHandler */ void handleIntteruptTaskFn(); // Inherited from MCP2521_Hardware_Handle void execute(uint8_t cmd); void execute(uint8_t cmd, uint8_t address); void read(uint8_t cmd, uint8_t *data, size_t length, uint8_t address); void read(uint8_t cmd, uint8_t *data, size_t length); uint8_t read(uint8_t cmd, uint8_t address); uint8_t read(uint8_t cmd); void write(uint8_t cmd, uint8_t *data, size_t length, uint8_t address); 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