Initial commit
This commit is contained in:
33
CLS.c
Normal file
33
CLS.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "CLS_BSP.h"
|
||||
#include "CLS.h"
|
||||
#include "CLSAddress.h"
|
||||
#include "cmsis_os2.h"
|
||||
|
||||
osTimerId_t CLS_HeatbeatTimerId; // Timer ID
|
||||
static uint8_t cls_hartbeat_counter = 0;
|
||||
static CLS_BSP_TxHeaderType cls_hartbeat_header = CREATE_BSP_CAN_HEADER(GENERATE_CLS_ADDRESS(CLS_CODE_STATUS,CLS_DEVICE,CLS_CH_STA_HEATBEAT), CLS_BSP_DLC_BYTES_1);
|
||||
|
||||
|
||||
void CLS_Heatbeat(void *argument) {
|
||||
// Code to be executed every 500ms
|
||||
cls_hartbeat_counter++;
|
||||
CLS_BSP_CAN_AddMessageToSend(&cls_hartbeat_header, &cls_hartbeat_counter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CLS_Init(void) {
|
||||
osTimerAttr_t timerAttr;
|
||||
timerAttr.name = "CLS_Heatbeat";
|
||||
timerAttr.attr_bits = 0U;
|
||||
timerAttr.cb_mem = NULL;
|
||||
timerAttr.cb_size = 0U;
|
||||
|
||||
|
||||
CLS_HeatbeatTimerId = osTimerNew((osTimerFunc_t)CLS_Heatbeat, osTimerPeriodic, NULL, &timerAttr);
|
||||
if (CLS_HeatbeatTimerId != NULL) { // Timer object created
|
||||
if (osTimerStart(CLS_HeatbeatTimerId, 500) == osOK) { // Timer started
|
||||
// Timer started successfully
|
||||
}
|
||||
}
|
||||
}
|
||||
9
CLS.h
Normal file
9
CLS.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define CLS_DEVICE_MASTER 0x11
|
||||
#define CLS_SLAVE_AR(n) n
|
||||
|
||||
#define CLS_DEVICE CLS_DEVICE_MASTER
|
||||
|
||||
|
||||
void CLS_Init(void);
|
||||
64
CLSAddress.h
Normal file
64
CLSAddress.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
CLS_CODE_0 = 0, // 0b000
|
||||
CLS_CODE_FIMWARE = 1, // 0b001
|
||||
CLS_CODE_2 = 2, // 0b010
|
||||
CLS_CODE_MESSAGE = 3, // 0b011
|
||||
CLS_CODE_4 = 4, // 0b100
|
||||
CLS_CODE_5 = 5, // 0b101
|
||||
CLS_CODE_STATUS = 6, // 0b110
|
||||
CLS_CODE_CONFIG = 7 // 0b111
|
||||
} CLSMessageCode;
|
||||
|
||||
typedef enum {
|
||||
CLS_CHANNEL1 = 0, // 0b000
|
||||
CLS_CHANNEL2 = 1, // 0b001
|
||||
CLS_CHANNEL3 = 2, // 0b010
|
||||
CLS_CHANNEL4 = 3, // 0b011
|
||||
CLS_CHANNEL5 = 4, // 0b100
|
||||
CLS_CHANNEL6 = 5, // 0b101
|
||||
CLS_CHANNEL7 = 6, // 0b110
|
||||
CLS_CHANNEL8 = 7 // 0b111
|
||||
} CLSChannel;
|
||||
|
||||
|
||||
typedef enum {
|
||||
CLS_CH_FW_MOSI = 0, // 0b000
|
||||
CLS_CH_FW_MISO = 1, // 0b001
|
||||
CLS_CH_FW_MASTER_CONTROL = 2, // 0b010
|
||||
CLS_CH_FW_SLAVE_FEEDBACK = 3, // 0b011
|
||||
CLS_CH_FW_4 = 4, // 0b100
|
||||
CLS_CH_FW_5 = 5, // 0b101
|
||||
CLS_CH_FW_6 = 6, // 0b110
|
||||
CLS_CH_FW_BOOTCALL = 7 // 0b111
|
||||
} CLSChannelFirmware;
|
||||
|
||||
|
||||
typedef enum {
|
||||
CLS_CH_STA_HEATBEAT = 0, // 0b000
|
||||
CLS_CH_STA_1 = 1, // 0b001
|
||||
CLS_CH_STA_2 = 2, // 0b010
|
||||
CLS_CH_STA_3 = 3, // 0b011
|
||||
CLS_CH_STA_4 = 4, // 0b100
|
||||
CLS_CH_STA_5 = 5, // 0b101
|
||||
CLS_CH_STA_6 = 6, // 0b110
|
||||
CLS_CH_STA_7 = 7 // 0b111
|
||||
} CLSChannelStatus;
|
||||
|
||||
|
||||
typedef struct {
|
||||
CLSMessageCode code : 3;
|
||||
uint8_t device : 5;
|
||||
CLSChannel channel : 3;
|
||||
} CLSAddress;
|
||||
|
||||
|
||||
#define GENERATE_CLS_ADDRESS(type, device, channel) \
|
||||
((uint16_t)(((type) << 8) | ((device) << 3) | (channel)) & 0x7ff)
|
||||
|
||||
inline uint16_t generateCLSAddress(CLSMessageCode type, uint8_t device, CLSChannel channel) {
|
||||
return ((type << 8) | (device << 3) | channel) & 0x7ff;
|
||||
}
|
||||
110
CLSFirmware.c
Normal file
110
CLSFirmware.c
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "CanDataHandler.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
|
||||
// Memory for the task
|
||||
StaticTask_t CLS_FW_Task_cb;
|
||||
uint32_t CLS_FW_Task_stk[512];
|
||||
// Attributes for the task
|
||||
osThreadId_t CLS_FW_Task_id;
|
||||
const osThreadAttr_t CLS_FW_Task_attr = {
|
||||
.name = "CLS_FW_Task",
|
||||
.attr_bits = 0U,
|
||||
.cb_mem = &CLS_FW_Task_cb,
|
||||
.cb_size = sizeof(CLS_FW_Task_cb),
|
||||
.stack_mem = CLS_FW_Task_stk,
|
||||
.stack_size = sizeof(CLS_FW_Task_stk),
|
||||
.priority = osPriorityNormal,
|
||||
.reserved = 0U
|
||||
};
|
||||
|
||||
void wait_for_start_callback() {
|
||||
osThreadFlagsSet(CLS_FW_Task_id, 1);
|
||||
}
|
||||
|
||||
void wait_for_start_enter() {
|
||||
// CanData_regEventMsg(...) // wait_for_start_callback // MessageCode::Firmware(FirmwareChannel::SlaveOutMasterIn);
|
||||
}
|
||||
|
||||
|
||||
void wait_for_start() {
|
||||
//osWaitForNotify // add timeout with eeror
|
||||
//wait_for_start_exit()
|
||||
//goto running
|
||||
}
|
||||
|
||||
void wait_for_start_exit() {
|
||||
//CanData_removeEvent(...)
|
||||
//f_lseek(&SDFile,0); or Open file
|
||||
// frame.counter = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void running_callback_error() {
|
||||
// lock the file
|
||||
// reset the file
|
||||
// reset the packcount
|
||||
// unlock the filec
|
||||
}
|
||||
|
||||
void running_callback_ack() {
|
||||
//osNotify
|
||||
}
|
||||
|
||||
void running_enter() {
|
||||
// CanData_regEventMsg(...) // running_callback_error // MessageCode::Firmware(FirmwareChannel::SlaveOutMasterIn);
|
||||
// CanData_regEventMsg(...) //running_callback_ack // MessageCode::Firmware(FirmwareChannel::SlaveFeedback);
|
||||
}
|
||||
|
||||
|
||||
void running() {
|
||||
|
||||
//4x
|
||||
// -- read file upto 4 bytes
|
||||
// -- send bytes can
|
||||
// -- if eof -> exit()
|
||||
// wait for Notify ack and repeat ^^
|
||||
|
||||
}
|
||||
|
||||
void running_exit() {
|
||||
// send DONE PACK
|
||||
|
||||
//CanData_removeEvent(...)
|
||||
//CanData_removeEvent(...)
|
||||
|
||||
// we are done task exit
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
char name[16];
|
||||
uint8_t device;
|
||||
} CLSFirmwareUpdateArgs;
|
||||
|
||||
void CLSFirmwareUpdateTask_func(void *argument);
|
||||
|
||||
void CLSFirmwareUpdateTask_start(CLSFirmwareUpdateArgs args) {
|
||||
// Task functionality here
|
||||
|
||||
// check CLS_FW_Task_id is null or stopped
|
||||
// osThreadGetState
|
||||
CLS_FW_Task_id = osThreadNew(CLSFirmwareUpdateTask_func, NULL, &CLS_FW_Task_attr);
|
||||
}
|
||||
|
||||
|
||||
void CLSFirmwareUpdateTask_func(void *argument) {
|
||||
|
||||
wait_for_start_enter();
|
||||
wait_for_start();
|
||||
wait_for_start_exit();
|
||||
|
||||
running_enter();
|
||||
running();
|
||||
running_exit();
|
||||
|
||||
osThreadExit();
|
||||
}
|
||||
0
CLSFirmware.h
Normal file
0
CLSFirmware.h
Normal file
21
CMakeLists.txt
Normal file
21
CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(CLS C)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC "")
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/CLS.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/CLSFirmware.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/CanDataHandler.c
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/CLS.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/CLSAddress.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/CLSFirmware.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/CanDataHandler.h
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Tasks)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE CLS_BSP)
|
||||
345
CanDataHandler.c
Normal file
345
CanDataHandler.c
Normal file
@@ -0,0 +1,345 @@
|
||||
#include "CanDataHandler.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_StmCanFilter(const CanDataFilterSlot* filterSetting ) {
|
||||
size_t f_index = filterSetting - CanFilterSlots;// index of the filter in CanFilterSlots
|
||||
|
||||
CLS_BSP_CAN_UniversalFilter clsFilterConfig = {
|
||||
.filterIndex = f_index,
|
||||
.filterDestination = filterSetting->fifo,
|
||||
.filterMode = CLS_BSP_CAN_FILTER_LIST,
|
||||
.id0 = filterSetting->id[0],
|
||||
.id1 = filterSetting->id[1],
|
||||
};
|
||||
|
||||
CLS_BSP_CAN_SetUniversalFilter(&clsFilterConfig);
|
||||
}
|
||||
|
||||
// this will setup the canfilter using a custom defined filter
|
||||
void setup_StmCanFilterManual(const CanDataFilterSlot* filterSetting, CLS_BSP_CAN_UniversalFilter * filter ) {
|
||||
size_t f_index = filterSetting - CanFilterSlots;// index of the filter in CanFilterSlots
|
||||
filter->filterIndex = f_index;
|
||||
CLS_BSP_CAN_SetUniversalFilter(filter);
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
if (CanFilterSlots[i].fifo == CANDATA_FIFOX_UNDEFIEND) {
|
||||
CanFilterSlots[i].fifo = reqest_fifo;
|
||||
}
|
||||
|
||||
// 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_StmCanFilter(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_StmCanFilter(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;
|
||||
}
|
||||
|
||||
|
||||
// Function to register a Set of ID for Data Messages using a Manual filter
|
||||
size_t CanData_regDataManualMsg(const CanDataId* canid, size_t id_count, CLS_BSP_CAN_UniversalFilter * filter) {
|
||||
// first check all id to be new
|
||||
for (size_t i = 0; i < id_count; i++) {
|
||||
if(CanData_getDataMessage(canid[i]) != NULL) {
|
||||
return 0; // invalid operation one id is already used
|
||||
}
|
||||
}
|
||||
|
||||
// Find and configure one unused slot for the manual filter
|
||||
CanDataFilterRef filterRef = CanData_unusedFilterSlot(CANDATA_FIFOX_MANUAL);
|
||||
if (filterRef.ref == NULL) {
|
||||
return 0; // No unused filter slot available
|
||||
}
|
||||
|
||||
// setup the manual filters
|
||||
filterRef.ref->fifo = CANDATA_FIFOX_MANUAL;
|
||||
filterRef.ref->free = CANDATA_MANUAL;
|
||||
setup_StmCanFilterManual(filterRef.ref, filter);
|
||||
|
||||
|
||||
for (size_t i = 0; i < id_count; i++) {
|
||||
// Find an unused slot in the data store
|
||||
CanDataMessageSlot *dataSlot = CanData_unusedDataSlot();
|
||||
if (!dataSlot) {
|
||||
return i; // No unused data slot available
|
||||
}
|
||||
|
||||
dataSlot->filter = filterRef;
|
||||
dataSlot->filter.index = -1; // this idecates is a manual filter
|
||||
}
|
||||
|
||||
return id_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_StmCanFilter(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
118
CanDataHandler.h
Normal file
118
CanDataHandler.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @file CanDataHandler.h
|
||||
* @brief CanDataHandler Module
|
||||
*
|
||||
* The CanDataHandler module is responsible for managing CAN data messages and event messages.
|
||||
* It provides functionality to register CAN IDs for data and event messages, handle reception
|
||||
* of these messages from FIFO buffers, insert data messages into an array, and retrieve stored
|
||||
* data messages based on their CAN ID.
|
||||
*
|
||||
* The module maintains an internal data structure for data and event message slots, each of which
|
||||
* is associated with a filter reference that points to a filter slot. A filter slot stores the
|
||||
* CAN IDs and indicates the type of FIFO buffer and the number of free IDs in the slot.
|
||||
*
|
||||
* For event messages, a callback function can be registered to handle specific events associated
|
||||
* with a CAN ID.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CANDATAHANDLER_H
|
||||
#define CANDATAHANDLER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "CLS_BSP.h"
|
||||
// Define the maximum length of data for a Data Message
|
||||
#define MAX_DATA_LENGTH 8
|
||||
|
||||
typedef uint16_t CanDataId;
|
||||
|
||||
// Typedef for the event callback function
|
||||
typedef void (*EventCallback)(CanDataId canid, uint8_t* data, uint8_t len);
|
||||
|
||||
|
||||
// type of fifo that this slot uses
|
||||
typedef enum {
|
||||
CANDATA_FIFOX_UNDEFIEND = CLS_CAN_FILTER_DISABLE,
|
||||
CANDATA_FIFO0_DATA = CLS_CAN_FILTER_TO_RXFIFO0,
|
||||
CANDATA_FIFO1_EVENT = CLS_CAN_FILTER_TO_RXFIFO1,
|
||||
CANDATA_FIFOX_MANUAL = 0x0f,
|
||||
} CanDataSlotFifo;
|
||||
|
||||
// count of free ids in the slot
|
||||
typedef enum {
|
||||
CANDATA_ALLFREE = 0x00,
|
||||
CANDATA_FREE1 = 0x01,
|
||||
CANDATA_FREE0 = 0x02,
|
||||
CANDATA_FULL = 0x03,
|
||||
CANDATA_MANUAL = 0x0f,
|
||||
} CanDataSlotFree;
|
||||
|
||||
// Define s structer for a used filter slot
|
||||
typedef struct {
|
||||
CanDataSlotFree free; // Number of free IDs in the slot
|
||||
CanDataSlotFifo fifo; // Type of FIFO that this slot uses
|
||||
CanDataId id[2]; // Array to store the two CAN IDs associated with this filter slot
|
||||
} CanDataFilterSlot;
|
||||
|
||||
|
||||
|
||||
// Define a structure for a Data Message
|
||||
typedef struct {
|
||||
CanDataId canid;
|
||||
uint8_t data[MAX_DATA_LENGTH];
|
||||
uint8_t data_length;
|
||||
} CanDataMessage;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CanDataFilterSlot * ref; // Reference to the filter slot
|
||||
uint8_t index; // Index of the used CAN ID in the filter slot's id array
|
||||
} CanDataFilterRef;
|
||||
|
||||
|
||||
typedef struct {
|
||||
CanDataMessage msg;
|
||||
CanDataFilterRef filter; // Filter reference
|
||||
} CanDataMessageSlot;
|
||||
|
||||
|
||||
// Define a structure for a Event Message
|
||||
typedef struct {
|
||||
CanDataId canid;
|
||||
EventCallback eventCall;
|
||||
CanDataFilterRef filter; // Filter reference
|
||||
} CanDataEventSlot;
|
||||
|
||||
|
||||
// reset all internal structures
|
||||
// does not reset CAN HW
|
||||
void CanDataHandler_init(void);
|
||||
|
||||
// Function to register a CAN ID for Data Messages
|
||||
bool CanData_regDataMsg(CanDataId canid);
|
||||
|
||||
// Function to register a Set of ID for Data Messages using a Manual filter
|
||||
size_t CanData_regDataManualMsg(const CanDataId* canid, size_t id_count, CLS_BSP_CAN_UniversalFilter * filter);
|
||||
|
||||
// Function to register a CAN ID for Event Messages and associate it with a callback function
|
||||
bool CanData_regEventMsg(CanDataId canid, EventCallback event_callback);
|
||||
|
||||
// Function to remove a CAN ID from Event Messages Register
|
||||
bool CanData_removeEvent(CanDataId canid);
|
||||
|
||||
// Function to handle reception of Data Messages from FIFO0
|
||||
void CanData_canFifo0RxCallback(CanDataId canid, uint8_t* data, uint8_t len);
|
||||
|
||||
// Function to handle reception of Event Messages from FIFO1
|
||||
void CanData_canFifo1RxCallback(CanDataId canid, uint8_t* data, uint8_t len);
|
||||
|
||||
// Function to insert a Data Message into the array
|
||||
void CanData_insertDataMessage(CanDataId canid, uint8_t* data, uint8_t data_length);
|
||||
|
||||
// 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);
|
||||
|
||||
#endif // CANDATAHANDLER_H
|
||||
Reference in New Issue
Block a user