#include "CanDataHandler.h" #include "fdcan.h" #include "string.h" #define MAX_DATA_STORAGE 100 #define MAX_EVENT_STORAGE 100 #define MAX_FILTER_SLOTS 100 // storage for upto MAX_DATA_STORAGE diffrent messages static CanDataMessageSlot CanDataStore[MAX_DATA_STORAGE] = {0}; // storage for upto MAX_EVENT_STORAGE diffrent event handlers static CanDataEventSlot CanEventStore[MAX_DATA_STORAGE] = {0}; // storage for upto MAX_FILTER_SLOTS diffrent can filters static CanDataFilterSlot CanFilterSlots[MAX_FILTER_SLOTS] = {0}; // this will setup the canfilter accoridng to the settings void setup_StmFdCanFilter(const CanDataFilterSlot* filterSetting ) { size_t f_index = filterSetting - CanFilterSlots;// index of the filter in CanFilterSlots FDCAN_FilterTypeDef sFilterConfig; sFilterConfig.IdType = FDCAN_STANDARD_ID; sFilterConfig.FilterIndex = f_index; sFilterConfig.FilterType = FDCAN_FILTER_DUAL; sFilterConfig.FilterConfig = filterSetting->fifo; sFilterConfig.FilterID1 = filterSetting->id[0]; sFilterConfig.FilterID2 = filterSetting->id[1]; HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig); } void CanDataHandler_init(void) { // Reset all data message slots for (int i = 0; i < MAX_DATA_STORAGE; i++) { CanDataStore[i].msg.canid = 0; CanDataStore[i].msg.data_length = 0; memset(CanDataStore[i].msg.data, 0, MAX_DATA_LENGTH); CanDataStore[i].filter.ref = NULL; CanDataStore[i].filter.index = 0; } // Reset all event message slots for (int i = 0; i < MAX_EVENT_STORAGE; i++) { CanEventStore[i].canid = 0; CanEventStore[i].eventCall = NULL; CanEventStore[i].filter.ref = NULL; CanEventStore[i].filter.index = 0; } // Reset all filter slots for (int i = 0; i < MAX_FILTER_SLOTS; i++) { CanFilterSlots[i].free = CANDATA_ALLFREE; CanFilterSlots[i].fifo = CANDATA_FIFOX_UNDEFIEND; CanFilterSlots[i].id[0] = 0; CanFilterSlots[i].id[1] = 0; } } /** * Finds and returns an unused filter slot. If no unused slot is found, returns NULL. */ CanDataFilterRef CanData_unusedFilterSlot(CanDataSlotFifo reqest_fifo) { CanDataFilterRef filterRef = {NULL, 0}; for (size_t i = 0; i < MAX_FILTER_SLOTS; i++) { // find a slot with free some id if (CanFilterSlots[i].free != CANDATA_FULL) { // either the fifo settig matches or is undefined if(CanFilterSlots[i].fifo == reqest_fifo || CanFilterSlots[i].fifo == CANDATA_FIFOX_UNDEFIEND) filterRef.ref = &CanFilterSlots[i]; // Determine the index based on the 'free' field switch (CanFilterSlots[i].free) { case CANDATA_ALLFREE: filterRef.index = 0; CanFilterSlots[i].free = CANDATA_FREE1; break; case CANDATA_FREE1: filterRef.index = 1; CanFilterSlots[i].free = CANDATA_FULL; break; case CANDATA_FREE0: filterRef.index = 0; CanFilterSlots[i].free = CANDATA_FULL; break; default: break; } break; } } return filterRef; } void CanData_clearFilterSlot(CanDataFilterRef filter) { // reset the filter can id filter.ref->id[filter.index] = 0; // set the slot as free if(filter.index == 0) { filter.ref->free = filter.ref->free & CANDATA_FREE0; } else if( filter.index == 1) { filter.ref->free = filter.ref->free & CANDATA_FREE1; } // if the filterslot is now fully free reset the fifo settings if(filter.ref->free == CANDATA_ALLFREE) { filter.ref->fifo = CANDATA_FIFOX_UNDEFIEND; } // finaly write new HW config setup_StmFdCanFilter(filter.ref); } /** * Finds and returns an unused data message slot. If no unused slot is found, returns NULL. */ CanDataMessageSlot * CanData_unusedDataSlot() { for (size_t i = 0; i < MAX_DATA_STORAGE; i++) { if (CanDataStore[i].msg.canid == 0) { return &CanDataStore[i]; } } return NULL; // No unused slot found } /** * Finds and returns an unused event slot. If no unused slot is found, returns NULL. */ CanDataEventSlot * CanData_unusedEventSlot() { for (size_t i = 0; i < MAX_EVENT_STORAGE; i++) { if (CanEventStore[i].canid == 0) { return &CanEventStore[i]; } } return NULL; // No unused slot found } /** * Registers a data message with given CanDataId. Returns true if registration is successful, false otherwise. */ bool CanData_regDataMsg(CanDataId canid) { // check if we already have this canid to avoid duplicates if(CanData_getDataMessage(canid) != NULL) { return true; // but return true beause there is already a vaild entry for this canid } // Find an unused slot in the data store CanDataMessageSlot *dataSlot = CanData_unusedDataSlot(); if (!dataSlot) { return false; // No unused data slot available } // Find and configure an unused slot for the data message CanDataFilterRef filter = CanData_unusedFilterSlot(CANDATA_FIFO0_DATA); if (filter.ref == NULL) { return false; // No unused filter slot available } // Configure the filter slot filter.ref->id[filter.index] = canid; // Set up the filter with the new settings setup_StmFdCanFilter(filter.ref); // Register the data message with the data slot dataSlot->msg.canid = canid; dataSlot->filter = filter; // Store the pointer to the filter slot return true; } /** * Registers a event message with given CanDataId. Returns true if registration is successful, false otherwise. */ bool CanData_regEventMsg(CanDataId canid, EventCallback event_callback) { // Check for vaild callback if(event_callback == NULL) { return false; } // Check if the canid is already registered for (int i = 0; i < MAX_EVENT_STORAGE; i++) { if (CanEventStore[i].canid == canid) { return false; // The canid is already registered } } // Find an unused slot in the event store CanDataEventSlot *eventSlot = CanData_unusedEventSlot(); if (eventSlot == NULL) { return false; // No unused event slot available } // Find and configure an unused slot for the data message CanDataFilterRef filter = CanData_unusedFilterSlot(CANDATA_FIFO0_DATA); if (filter.ref == NULL) { return false; // No unused filter slot available } // Configure the filter slot filter.ref->id[filter.index] = canid; // Set up the filter with the new settings setup_StmFdCanFilter(filter.ref); // Register the event message with the event slot eventSlot->canid = canid; eventSlot->eventCall = event_callback; eventSlot->filter = filter; // Store the pointer to the filter slot return true; } // Function to remove a CAN ID from Event Messages Register bool CanData_removeEvent(CanDataId canid) { // Search for the event slot with the given CanDataId for (size_t i = 0; i < MAX_EVENT_STORAGE; i++) { if (CanEventStore[i].canid == canid) { CanDataEventSlot * eventSlot = &CanEventStore[i]; CanDataFilterRef filter = eventSlot->filter; // reset the CanDataEventSlot eventSlot->canid =0; eventSlot->eventCall = NULL; eventSlot->filter.index =0; eventSlot->filter.ref = NULL; // reset the filter CanData_clearFilterSlot(filter); return true; } } return false; } // Function to insert a Data Message into the array void CanData_insertDataMessage(CanDataId canid, uint8_t* data, uint8_t data_length) { if(data == NULL || data_length == 0 ) { return; } // Search for the data slot with the given CanDataId for (size_t i = 0; i < MAX_DATA_STORAGE; i++) { if (CanDataStore[i].msg.canid == canid) { // If found, update the data message in the slot CanDataStore[i].msg.data_length = data_length; memcpy(CanDataStore[i].msg.data, data, data_length); return; } } } // Function to read stored Data Message based on CAN ID // Returns a const pointer to the stored data or NULL if not found const CanDataMessage* CanData_getDataMessage(CanDataId canid) { // Search for the data message with the given CanDataId for (size_t i = 0; i < MAX_DATA_STORAGE; i++) { if (CanDataStore[i].msg.canid == canid) { return &CanDataStore[i].msg; // Return a pointer to the found data message } } return NULL; // No data message with the given CanDataId found } // Function to handle reception of Data Messages from FIFO0 void CanData_canFifo0RxCallback(CanDataId canid, uint8_t* data, uint8_t len) { // Insert the data message into the data store CanData_insertDataMessage(canid, data, len); } // Function to handle reception of Event Messages from FIFO1 void CanData_canFifo1RxCallback(CanDataId canid, uint8_t* data, uint8_t len) { // Search for the event slot with the given CanDataId for (size_t i = 0; i < MAX_EVENT_STORAGE; i++) { if (CanEventStore[i].canid == canid) { // If found, call the event callback with the received data CanEventStore[i].eventCall(canid ,data, len); return; } } }