added handling of CanData To Tasks
This commit is contained in:
@@ -7,9 +7,14 @@ add_library(${PROJECT_NAME} STATIC "")
|
|||||||
target_sources(${PROJECT_NAME}
|
target_sources(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.c
|
${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CanDataHandler.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CanDataTask.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/FirmwareHandler.c
|
${CMAKE_CURRENT_LIST_DIR}/FirmwareHandler.c
|
||||||
INTERFACE
|
INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.h
|
${CMAKE_CURRENT_LIST_DIR}/UsbDataHandler.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CanDataHandler.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CanDataTask.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|||||||
299
Application/Tasks/CanDataHandler.c
Normal file
299
Application/Tasks/CanDataHandler.c
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
Application/Tasks/CanDataHandler.h
Normal file
114
Application/Tasks/CanDataHandler.h
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/**
|
||||||
|
* @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 "fdcan.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 = FDCAN_FILTER_DISABLE,
|
||||||
|
CANDATA_FIFO0_DATA = FDCAN_FILTER_TO_RXFIFO0,
|
||||||
|
CANDATA_FIFO1_EVENT = FDCAN_FILTER_TO_RXFIFO1,
|
||||||
|
} CanDataSlotFifo;
|
||||||
|
|
||||||
|
// count of free ids in the slot
|
||||||
|
typedef enum {
|
||||||
|
CANDATA_ALLFREE = 0,
|
||||||
|
CANDATA_FREE1 = 1,
|
||||||
|
CANDATA_FREE0 = 2,
|
||||||
|
CANDATA_FULL = 3,
|
||||||
|
} 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 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
|
||||||
108
Application/Tasks/CanDataTask.c
Normal file
108
Application/Tasks/CanDataTask.c
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#include "cmsis_os2.h" // CMSIS-RTOS2 header file
|
||||||
|
#include "CanDataTask.h"
|
||||||
|
#include "fdcan.h"
|
||||||
|
#include "CanDataHandler.h"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Define thread flags
|
||||||
|
#define FLAG_FDCAN_RX_FIFO0 (1<<0)
|
||||||
|
#define FLAG_FDCAN_RX_FIFO1 (1<<1)
|
||||||
|
|
||||||
|
|
||||||
|
// Memory for the task
|
||||||
|
StaticTask_t CanDataTask_cb;
|
||||||
|
uint32_t CanDataTask_stk[512];
|
||||||
|
// Attributes for the task
|
||||||
|
osThreadId_t CanDataTask_id;
|
||||||
|
const osThreadAttr_t CanDataTask_attr = {
|
||||||
|
.name = "CanDataTask",
|
||||||
|
.attr_bits = 0U,
|
||||||
|
.cb_mem = &CanDataTask_cb,
|
||||||
|
.cb_size = sizeof(CanDataTask_cb),
|
||||||
|
.stack_mem = CanDataTask_stk,
|
||||||
|
.stack_size = sizeof(CanDataTask_stk),
|
||||||
|
.priority = osPriorityNormal,
|
||||||
|
.tz_module = 0U,
|
||||||
|
.reserved = 0U
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t dlcDecode(uint32_t dlcCode) {
|
||||||
|
switch(dlcCode) {
|
||||||
|
case FDCAN_DLC_BYTES_0: return 0;
|
||||||
|
case FDCAN_DLC_BYTES_1: return 1;
|
||||||
|
case FDCAN_DLC_BYTES_2: return 2;
|
||||||
|
case FDCAN_DLC_BYTES_3: return 3;
|
||||||
|
case FDCAN_DLC_BYTES_4: return 4;
|
||||||
|
case FDCAN_DLC_BYTES_5: return 5;
|
||||||
|
case FDCAN_DLC_BYTES_6: return 6;
|
||||||
|
case FDCAN_DLC_BYTES_7: return 7;
|
||||||
|
case FDCAN_DLC_BYTES_8: return 8;
|
||||||
|
case FDCAN_DLC_BYTES_12: return 12;
|
||||||
|
case FDCAN_DLC_BYTES_16: return 16;
|
||||||
|
case FDCAN_DLC_BYTES_20: return 20;
|
||||||
|
case FDCAN_DLC_BYTES_24: return 24;
|
||||||
|
case FDCAN_DLC_BYTES_32: return 32;
|
||||||
|
case FDCAN_DLC_BYTES_48: return 48;
|
||||||
|
case FDCAN_DLC_BYTES_64: return 64;
|
||||||
|
default: return 0; // Return 0 for unknown dlc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CanDataTask_func(void *argument);
|
||||||
|
|
||||||
|
void CanDataTask_start() {
|
||||||
|
// Task functionality here
|
||||||
|
CanDataTask_id = osThreadNew(CanDataTask_func, NULL, &CanDataTask_attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FDCAN_RxHeaderTypeDef RxHeader;
|
||||||
|
static uint8_t RxData[8];
|
||||||
|
void CanDataTask_HandleFifo(uint32_t fifo) {
|
||||||
|
while (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) > 0 ) {
|
||||||
|
if (HAL_FDCAN_GetRxMessage(&hfdcan1, fifo, &RxHeader, RxData) != HAL_OK) {
|
||||||
|
Error_Handler();
|
||||||
|
} else {
|
||||||
|
CanData_canFifo0RxCallback(RxHeader.Identifier,RxData, dlcDecode(RxHeader.DataLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function for the task
|
||||||
|
void CanDataTask_func(void *argument) {
|
||||||
|
/* Configure global filter on FDCAN instanc:
|
||||||
|
Filter all remote frames with STD and EXT ID
|
||||||
|
Reject non matching frames with STD ID and EXT ID */
|
||||||
|
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK) {
|
||||||
|
Error_Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the FDCAN module */
|
||||||
|
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK){
|
||||||
|
Error_Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
// wait for interrupt event on any fifo
|
||||||
|
uint32_t flags = osThreadFlagsWait(FLAG_FDCAN_RX_FIFO0 | FLAG_FDCAN_RX_FIFO1, osFlagsWaitAny, osWaitForever);
|
||||||
|
|
||||||
|
// check the fifos for data and handle it if nessessay
|
||||||
|
CanDataTask_HandleFifo(FDCAN_RX_FIFO0);
|
||||||
|
CanDataTask_HandleFifo(FDCAN_RX_FIFO1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) {
|
||||||
|
// Notify the thread
|
||||||
|
osThreadFlagsSet(CanDataTask_id, FLAG_FDCAN_RX_FIFO0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs) {
|
||||||
|
// Notify the thread
|
||||||
|
osThreadFlagsSet(CanDataTask_id, FLAG_FDCAN_RX_FIFO1);
|
||||||
|
}
|
||||||
0
Application/Tasks/CanDataTask.h
Normal file
0
Application/Tasks/CanDataTask.h
Normal file
@@ -8,7 +8,10 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
|||||||
add_executable(${CMAKE_PROJECT_NAME})
|
add_executable(${CMAKE_PROJECT_NAME})
|
||||||
target_sources(${CMAKE_PROJECT_NAME} PUBLIC
|
target_sources(${CMAKE_PROJECT_NAME} PUBLIC
|
||||||
tests.c
|
tests.c
|
||||||
|
usbdata_test.c
|
||||||
|
candata_test.c
|
||||||
mock_os/mock_os.c
|
mock_os/mock_os.c
|
||||||
|
mock_os/mock_hal.c
|
||||||
../lib/Unity/src/unity.c
|
../lib/Unity/src/unity.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
220
tests/native/candata_test.c
Normal file
220
tests/native/candata_test.c
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
#include "unity.h"
|
||||||
|
#include "CanDataHandler.h"
|
||||||
|
|
||||||
|
#define MAX_MESSAGE_SLOTS 100
|
||||||
|
#define MAX_EVENT_SLOTS 100
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t hfdcan1 =0;
|
||||||
|
|
||||||
|
// Test when you register a new canid, it should return true.
|
||||||
|
void test_CanDataRegDataMsg_insert_valid() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
bool result = CanData_regDataMsg(canid);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test when you register a canid when all slots are filled, it should return false.
|
||||||
|
void test_CanDataRegDataMsg_insert_full() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
|
||||||
|
// Fill all the slots
|
||||||
|
for (int i = 1; i < MAX_MESSAGE_SLOTS+1; i++) {
|
||||||
|
bool result = CanData_regDataMsg(i);
|
||||||
|
TEST_ASSERT_TRUE(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to register a new canid
|
||||||
|
CanDataId canid = MAX_MESSAGE_SLOTS + 2; // This canid should not fit in the slots
|
||||||
|
bool result = CanData_regDataMsg(canid);
|
||||||
|
TEST_ASSERT_FALSE(result); // Check that the function returned false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test when registering the same canid multible times there should be no error
|
||||||
|
void test_CanDataRegDataMsg_insert_duplicate() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
|
||||||
|
// Register the same canid multiple times
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
bool result = CanData_regDataMsg(canid);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true each time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A dummy event callback function for testing
|
||||||
|
void dummyEventCallback(CanDataId canid, uint8_t* data, uint8_t len) {
|
||||||
|
// This function doesn't need to do anything
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test when you register a new event callback, it should return true.
|
||||||
|
void test_CanDataRegEventMsg_insert_valid() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
bool result = CanData_regEventMsg(canid, dummyEventCallback);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test when you register an event callback when all slots are filled, it should return false.
|
||||||
|
void test_CanDataRegEventMsg_insert_full() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
|
||||||
|
// Fill all the slots
|
||||||
|
for (int i = 1; i < MAX_EVENT_SLOTS+1; i++) {
|
||||||
|
bool result = CanData_regEventMsg(i, dummyEventCallback);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to register a new event callback
|
||||||
|
CanDataId canid = MAX_EVENT_SLOTS + 2; // This canid should not fit in the slots
|
||||||
|
bool result = CanData_regEventMsg(canid, dummyEventCallback);
|
||||||
|
TEST_ASSERT_FALSE(result); // Check that the function returned false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test when you register a canid with a NULL callback, it should return false.
|
||||||
|
void test_CanDataRegEventMsg_NullCallback() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
bool result = CanData_regEventMsg(canid, NULL);
|
||||||
|
TEST_ASSERT_FALSE(result); // Check that the function returned false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test when you register a canid that has already been registered, it should return false.
|
||||||
|
void test_CanDataRegEventMsg_insert_duplicate() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
|
||||||
|
// Register the canid once
|
||||||
|
bool result = CanData_regEventMsg(canid, dummyEventCallback);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
|
||||||
|
// Try to register the same canid again
|
||||||
|
result = CanData_regEventMsg(canid, dummyEventCallback);
|
||||||
|
TEST_ASSERT_FALSE(result); // Check that the function returned false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test for CanData_canFifo0RxCallback(CanDataId canid, uint8_t* data, uint8_t len) function
|
||||||
|
void test_CanData_canFifo0RxCallback_data_valid() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
uint8_t data[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // Test with valid data
|
||||||
|
uint8_t len = 8; // Test with a valid length
|
||||||
|
|
||||||
|
// Register the canid
|
||||||
|
bool result = CanData_regDataMsg(canid);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
|
||||||
|
// Call the function with the test parameters
|
||||||
|
CanData_canFifo0RxCallback(canid, data, len);
|
||||||
|
|
||||||
|
// Get the message that was processed
|
||||||
|
const CanDataMessage* message = CanData_getDataMessage(canid);
|
||||||
|
|
||||||
|
// Check that the message was processed correctly
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(len, message->data_length);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8_ARRAY(data, message->data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for CanData_canFifo0RxCallback(CanDataId canid, uint8_t* data, uint8_t len) function
|
||||||
|
// Test with an invalid canid or NULL data, the function should handle the error correctly.
|
||||||
|
void test_CanData_canFifo0RxCallback_data_invalid() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
uint8_t* data = NULL; // Test with NULL data
|
||||||
|
uint8_t len = 8; // Test with a valid length
|
||||||
|
|
||||||
|
// Register the canid
|
||||||
|
bool result = CanData_regDataMsg(canid);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
|
||||||
|
// Call the function with the test parameters
|
||||||
|
CanData_canFifo0RxCallback(canid, data, len);
|
||||||
|
|
||||||
|
// Get the message that was processed
|
||||||
|
const CanDataMessage* message = CanData_getDataMessage(canid);
|
||||||
|
|
||||||
|
// Check that the message was not processed
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(0, message->data_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool test_CanData_canFifo1RxCallback_callbackCalled = false;
|
||||||
|
|
||||||
|
void test_CanData_canFifo1RxCallback_callback(CanDataId canid, uint8_t* data, uint8_t len) {
|
||||||
|
test_CanData_canFifo1RxCallback_callbackCalled = true;
|
||||||
|
TEST_ASSERT_EQUAL_UINT16(1,canid);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(8,len);
|
||||||
|
}
|
||||||
|
// Test for CanData_canFifo1RxCallback(CanDataId canid, uint8_t* data, uint8_t len) function
|
||||||
|
void test_CanData_canFifo1RxCallback_data_valid() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
uint8_t data[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // Test with valid data
|
||||||
|
uint8_t len = 8; // Test with a valid length
|
||||||
|
|
||||||
|
// Register the canid with the callback
|
||||||
|
bool result = CanData_regEventMsg(canid, test_CanData_canFifo1RxCallback_callback);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
|
||||||
|
// Call the function with the test parameters
|
||||||
|
CanData_canFifo1RxCallback(canid, data, len);
|
||||||
|
|
||||||
|
// Check that the callback was called
|
||||||
|
TEST_ASSERT_TRUE(test_CanData_canFifo1RxCallback_callbackCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool test_CanData_removeEvent_callbackCalled = false;
|
||||||
|
|
||||||
|
void test_CanData_removeEvent_callback(CanDataId canid, uint8_t* data, uint8_t len) {
|
||||||
|
test_CanData_removeEvent_callbackCalled = true;
|
||||||
|
TEST_ASSERT_EQUAL_UINT16(1,canid);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(8,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for CanData_removeEvent(CanDataId canid) function
|
||||||
|
void test_CanData_removeEvent() {
|
||||||
|
CanDataHandler_init(); // Reset the state of the module
|
||||||
|
CanDataId canid = 1; // Test with a valid canid
|
||||||
|
|
||||||
|
// Register the canid with the callback
|
||||||
|
bool result = CanData_regEventMsg(canid, test_CanData_removeEvent_callback);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
|
||||||
|
// Remove the canid
|
||||||
|
result = CanData_removeEvent(canid);
|
||||||
|
TEST_ASSERT_TRUE(result); // Check that the function returned true
|
||||||
|
|
||||||
|
// Call the function with the test parameters
|
||||||
|
uint8_t data[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // Test with valid data
|
||||||
|
uint8_t len = 8; // Test with a valid length
|
||||||
|
CanData_canFifo1RxCallback(canid, data, len);
|
||||||
|
|
||||||
|
// Check that the callback was not called
|
||||||
|
TEST_ASSERT_FALSE(test_CanData_removeEvent_callbackCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Create a test runner function
|
||||||
|
void test_CanData(void) {
|
||||||
|
RUN_TEST(test_CanDataRegDataMsg_insert_valid);
|
||||||
|
RUN_TEST(test_CanDataRegDataMsg_insert_full);
|
||||||
|
RUN_TEST(test_CanDataRegDataMsg_insert_duplicate);
|
||||||
|
RUN_TEST(test_CanDataRegEventMsg_insert_valid);
|
||||||
|
RUN_TEST(test_CanDataRegEventMsg_insert_full);
|
||||||
|
RUN_TEST(test_CanDataRegEventMsg_NullCallback);
|
||||||
|
RUN_TEST(test_CanDataRegEventMsg_insert_duplicate);
|
||||||
|
RUN_TEST(test_CanData_canFifo0RxCallback_data_valid);
|
||||||
|
RUN_TEST(test_CanData_canFifo0RxCallback_data_invalid);
|
||||||
|
RUN_TEST(test_CanData_canFifo1RxCallback_data_valid);
|
||||||
|
RUN_TEST(test_CanData_removeEvent);
|
||||||
|
}
|
||||||
1
tests/native/mock_os/FreeRTOS.h
Normal file
1
tests/native/mock_os/FreeRTOS.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
typedef unsigned long int StaticTask_t;
|
||||||
@@ -104,4 +104,9 @@ void Error_Handler();
|
|||||||
osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
|
osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
|
||||||
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
|
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
|
||||||
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
|
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
|
||||||
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) ;
|
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
osStatus_t osDelay (uint32_t ticks);
|
||||||
|
uint32_t osKernelGetSysTimerCount (void);
|
||||||
|
|||||||
4
tests/native/mock_os/crc.h
Normal file
4
tests/native/mock_os/crc.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
typedef uint32_t CRC_HandleTypeDef;
|
||||||
|
extern CRC_HandleTypeDef hcrc;
|
||||||
|
uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength);
|
||||||
15
tests/native/mock_os/fatfs.h
Normal file
15
tests/native/mock_os/fatfs.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
typedef unsigned int FRESULT;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void * ptr; /* data */
|
||||||
|
}FIL;
|
||||||
|
|
||||||
|
FRESULT f_open (FIL* fp, const char* path, uint8_t mode); /* Open or create a file */
|
||||||
|
FRESULT f_close (FIL* fp); /* Close an open file object */
|
||||||
|
FRESULT f_write (FIL* fp, const void* buff, uint32_t btw, uint32_t* bw); /* Write data to the file */
|
||||||
|
|
||||||
|
|
||||||
|
#define FA_CREATE_ALWAYS 0
|
||||||
|
#define FA_WRITE 0
|
||||||
1716
tests/native/mock_os/fdcan.h
Normal file
1716
tests/native/mock_os/fdcan.h
Normal file
File diff suppressed because it is too large
Load Diff
9
tests/native/mock_os/mock_hal.c
Normal file
9
tests/native/mock_os/mock_hal.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
#include "fdcan.h"
|
||||||
|
#include "crc.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
4
tests/native/mock_os/usbd_cdc_if.h
Normal file
4
tests/native/mock_os/usbd_cdc_if.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
uint8_t CDC_Transmit_HS(uint8_t* Buf, uint16_t Len);
|
||||||
|
|
||||||
|
#define USBD_BUSY 1
|
||||||
|
#define USBD_OK 0
|
||||||
@@ -1,166 +1,23 @@
|
|||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
|
|
||||||
#include "UsbDataHandler.h"
|
|
||||||
#include "pb_encode.h"
|
|
||||||
#include "firmware.pb.h"
|
|
||||||
|
|
||||||
void setUp() {
|
void setUp() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define START_PACKAES 10
|
|
||||||
#define START_SIZE 123456
|
|
||||||
#define START_CRC 0xffff
|
|
||||||
#define START_DEVICE 0x04
|
|
||||||
#define START_NAME "slave0x04.bin"
|
|
||||||
|
|
||||||
#define PACK_COUTNER 3
|
|
||||||
#define PACK_CRC 0xabcd
|
|
||||||
#define PACK_DEVICE 0x04
|
|
||||||
#define PACK_DATA_SIZE 50
|
|
||||||
|
|
||||||
#define ACK_COUTNER 43
|
|
||||||
#define ACK_CRC 0xabcdef
|
|
||||||
#define ACK_DEVICE 0x9
|
|
||||||
|
|
||||||
#define DONE_CRC 0xffffffff
|
|
||||||
#define DONE_DEVICE 0xf
|
|
||||||
#define DONE_SIZE 1024 * 65
|
|
||||||
|
|
||||||
uint16_t StartCounter = 0;
|
|
||||||
uint16_t PackageCounter = 0;
|
|
||||||
uint16_t AckCounter = 0;
|
|
||||||
uint16_t DoneCounter = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void transmit_package(uint16_t id, const pb_msgdesc_t *fields , const void* msg){
|
|
||||||
UsbDataPacket buffer = {0};
|
|
||||||
buffer.head.type = id;
|
|
||||||
pb_ostream_t ostream = pb_ostream_from_buffer(buffer.data, sizeof(buffer.data));
|
|
||||||
pb_encode(&ostream, fields, msg);
|
|
||||||
buffer.head.length= ostream.bytes_written;
|
|
||||||
|
|
||||||
buffer.head.check = UsbDataPacket_head_sum(&buffer);
|
|
||||||
|
|
||||||
UsbDataHandler_RxCallback((uint8_t*)(&buffer), buffer.head.length+sizeof(UsbDataPacketHead));
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_UsbDataHandler(void) {
|
|
||||||
// Set up the module
|
|
||||||
UsbDataHandler_Start();
|
|
||||||
|
|
||||||
// Call the runner with no messages this should do nothing
|
|
||||||
UsbDataHandler_Runner();
|
|
||||||
|
|
||||||
FirmwareStart start ={
|
|
||||||
.name=START_NAME,
|
|
||||||
.packages=START_PACKAES,
|
|
||||||
.size=START_SIZE,
|
|
||||||
.crc_fw=START_CRC,
|
|
||||||
.device_id=START_DEVICE,
|
|
||||||
};
|
|
||||||
transmit_package(UsbPackageType_FIRMWARESTART, FirmwareStart_fields, &start);
|
|
||||||
|
|
||||||
// Call the runner with start message in the queue
|
|
||||||
UsbDataHandler_Runner();
|
|
||||||
TEST_ASSERT_EQUAL(StartCounter,1);
|
|
||||||
|
|
||||||
|
|
||||||
//Put 2 packages in the buffer an parse them
|
|
||||||
transmit_package(UsbPackageType_FIRMWARESTART, FirmwareStart_fields, &start);
|
|
||||||
transmit_package(UsbPackageType_FIRMWARESTART, FirmwareStart_fields, &start);
|
|
||||||
UsbDataHandler_Runner();
|
|
||||||
UsbDataHandler_Runner();
|
|
||||||
TEST_ASSERT_EQUAL(StartCounter,3);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FirmwarePackage pack = {
|
|
||||||
.counter =PACK_COUTNER ,
|
|
||||||
.crc_pac = PACK_CRC,
|
|
||||||
.device_id= PACK_DEVICE,
|
|
||||||
.data={.size = PACK_DATA_SIZE,
|
|
||||||
.bytes={0}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
transmit_package(UsbPackageType_FIRMWAREPACKAGE, FirmwarePackage_fields, &pack);
|
|
||||||
UsbDataHandler_Runner();
|
|
||||||
TEST_ASSERT_EQUAL(PackageCounter,1);
|
|
||||||
|
|
||||||
FirmwarePackageAck ack = {
|
|
||||||
.ack =true,
|
|
||||||
.counter = ACK_COUTNER,
|
|
||||||
.crc_pac = ACK_CRC,
|
|
||||||
.device_id = ACK_DEVICE,
|
|
||||||
};
|
|
||||||
transmit_package(UsbPackageType_FIRMWAREPACKAGEACK, FirmwarePackageAck_fields, &ack);
|
|
||||||
UsbDataHandler_Runner();
|
|
||||||
TEST_ASSERT_EQUAL(PackageCounter,1);
|
|
||||||
|
|
||||||
|
|
||||||
FirmwareDone done = {
|
|
||||||
.crc_fw = DONE_CRC,
|
|
||||||
.device_id = DONE_DEVICE,
|
|
||||||
.size = DONE_SIZE,
|
|
||||||
};
|
|
||||||
|
|
||||||
transmit_package(UsbPackageType_FIRMWAREDONE, FirmwareDone_fields, &done);
|
|
||||||
UsbDataHandler_Runner();
|
|
||||||
TEST_ASSERT_EQUAL(DoneCounter,1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void tearDown() {
|
void tearDown() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void test_UsbDataHandler(void);
|
||||||
|
void test_CanData(void);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
RUN_TEST(test_UsbDataHandler);
|
RUN_TEST(test_UsbDataHandler);
|
||||||
|
RUN_TEST(test_CanData);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DataClbk_FirmwareStart(void * msg, uint32_t length) {
|
|
||||||
FirmwareStart start;
|
|
||||||
memcpy(&start,msg,sizeof(start));
|
|
||||||
TEST_ASSERT_EQUAL(START_SIZE, start.size);
|
|
||||||
TEST_ASSERT_EQUAL(START_PACKAES, start.packages);
|
|
||||||
TEST_ASSERT_EQUAL(START_CRC, start.crc_fw);
|
|
||||||
TEST_ASSERT_EQUAL(START_DEVICE, start.device_id);
|
|
||||||
TEST_ASSERT_EQUAL_STRING(START_NAME,start.name);
|
|
||||||
StartCounter++;
|
|
||||||
}
|
|
||||||
void DataClbk_FirmwarePackage(void * msg, uint32_t length) {
|
|
||||||
FirmwarePackage pack;
|
|
||||||
memcpy(&pack,msg,sizeof(pack));
|
|
||||||
TEST_ASSERT_EQUAL(FirmwarePackage_size, length);
|
|
||||||
TEST_ASSERT_EQUAL(PACK_COUTNER, pack.counter);
|
|
||||||
TEST_ASSERT_EQUAL(PACK_CRC, pack.crc_pac);
|
|
||||||
TEST_ASSERT_EQUAL(PACK_DEVICE, pack.device_id);
|
|
||||||
TEST_ASSERT_EQUAL(PACK_DATA_SIZE, pack.data.size);
|
|
||||||
PackageCounter++;
|
|
||||||
}
|
|
||||||
void DataClbk_FirmwarePackageAck(void * msg, uint32_t length) {
|
|
||||||
FirmwarePackageAck ack;
|
|
||||||
memcpy(&ack,msg,sizeof(ack));
|
|
||||||
TEST_ASSERT_EQUAL(FirmwarePackageAck_size, length);
|
|
||||||
TEST_ASSERT(ack.ack);
|
|
||||||
TEST_ASSERT_EQUAL(ACK_COUTNER, ack.counter);
|
|
||||||
TEST_ASSERT_EQUAL(ACK_CRC, ack.crc_pac);
|
|
||||||
TEST_ASSERT_EQUAL(ACK_DEVICE, ack.device_id);
|
|
||||||
|
|
||||||
AckCounter++;
|
|
||||||
}
|
|
||||||
void DataClbk_FirmwareDone(void * msg, uint32_t length) {
|
|
||||||
FirmwareDone done;
|
|
||||||
memcpy(&done,msg,sizeof(done));
|
|
||||||
TEST_ASSERT_EQUAL(FirmwareDone_size, length);
|
|
||||||
TEST_ASSERT_EQUAL(DONE_CRC,done.crc_fw);
|
|
||||||
TEST_ASSERT_EQUAL(DONE_DEVICE,done.device_id);
|
|
||||||
TEST_ASSERT_EQUAL(DONE_SIZE,done.size);
|
|
||||||
DoneCounter++;
|
|
||||||
}
|
|
||||||
150
tests/native/usbdata_test.c
Normal file
150
tests/native/usbdata_test.c
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#include "unity.h"
|
||||||
|
#include "UsbDataHandler.h"
|
||||||
|
#include "pb_encode.h"
|
||||||
|
#include "firmware.pb.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define START_PACKAES 10
|
||||||
|
#define START_SIZE 123456
|
||||||
|
#define START_CRC 0xffff
|
||||||
|
#define START_DEVICE 0x04
|
||||||
|
#define START_NAME "slave0x04.bin"
|
||||||
|
|
||||||
|
#define PACK_COUTNER 3
|
||||||
|
#define PACK_CRC 0xabcd
|
||||||
|
#define PACK_DEVICE 0x04
|
||||||
|
#define PACK_DATA_SIZE 50
|
||||||
|
|
||||||
|
#define ACK_COUTNER 43
|
||||||
|
#define ACK_CRC 0xabcdef
|
||||||
|
#define ACK_DEVICE 0x9
|
||||||
|
|
||||||
|
#define DONE_CRC 0xffffffff
|
||||||
|
#define DONE_DEVICE 0xf
|
||||||
|
#define DONE_SIZE 1024 * 65
|
||||||
|
|
||||||
|
uint16_t StartCounter = 0;
|
||||||
|
uint16_t PackageCounter = 0;
|
||||||
|
uint16_t AckCounter = 0;
|
||||||
|
uint16_t DoneCounter = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void transmit_package(uint16_t id, const pb_msgdesc_t *fields , const void* msg){
|
||||||
|
UsbDataPacket buffer = {0};
|
||||||
|
buffer.head.type = id;
|
||||||
|
pb_ostream_t ostream = pb_ostream_from_buffer(buffer.data, sizeof(buffer.data));
|
||||||
|
pb_encode(&ostream, fields, msg);
|
||||||
|
buffer.head.length= ostream.bytes_written;
|
||||||
|
|
||||||
|
buffer.head.check = UsbDataPacket_head_sum(&buffer);
|
||||||
|
|
||||||
|
UsbDataHandler_RxCallback((uint8_t*)(&buffer), buffer.head.length+sizeof(UsbDataPacketHead));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_UsbDataHandler(void) {
|
||||||
|
// Set up the module
|
||||||
|
UsbDataHandler_Start();
|
||||||
|
|
||||||
|
// Call the runner with no messages this should do nothing
|
||||||
|
UsbDataHandler_Runner();
|
||||||
|
|
||||||
|
FirmwareStart start ={
|
||||||
|
.name=START_NAME,
|
||||||
|
.packages=START_PACKAES,
|
||||||
|
.size=START_SIZE,
|
||||||
|
.crc_fw=START_CRC,
|
||||||
|
.device_id=START_DEVICE,
|
||||||
|
};
|
||||||
|
transmit_package(UsbPackageType_FIRMWARESTART, FirmwareStart_fields, &start);
|
||||||
|
|
||||||
|
// Call the runner with start message in the queue
|
||||||
|
UsbDataHandler_Runner();
|
||||||
|
TEST_ASSERT_EQUAL(StartCounter,1);
|
||||||
|
|
||||||
|
|
||||||
|
//Put 2 packages in the buffer an parse them
|
||||||
|
transmit_package(UsbPackageType_FIRMWARESTART, FirmwareStart_fields, &start);
|
||||||
|
transmit_package(UsbPackageType_FIRMWARESTART, FirmwareStart_fields, &start);
|
||||||
|
UsbDataHandler_Runner();
|
||||||
|
UsbDataHandler_Runner();
|
||||||
|
TEST_ASSERT_EQUAL(StartCounter,3);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FirmwarePackage pack = {
|
||||||
|
.counter =PACK_COUTNER ,
|
||||||
|
.crc_pac = PACK_CRC,
|
||||||
|
.device_id= PACK_DEVICE,
|
||||||
|
.data={.size = PACK_DATA_SIZE,
|
||||||
|
.bytes={0}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
transmit_package(UsbPackageType_FIRMWAREPACKAGE, FirmwarePackage_fields, &pack);
|
||||||
|
UsbDataHandler_Runner();
|
||||||
|
TEST_ASSERT_EQUAL(PackageCounter,1);
|
||||||
|
|
||||||
|
FirmwarePackageAck ack = {
|
||||||
|
.ack =true,
|
||||||
|
.counter = ACK_COUTNER,
|
||||||
|
.crc_pac = ACK_CRC,
|
||||||
|
.device_id = ACK_DEVICE,
|
||||||
|
};
|
||||||
|
transmit_package(UsbPackageType_FIRMWAREPACKAGEACK, FirmwarePackageAck_fields, &ack);
|
||||||
|
UsbDataHandler_Runner();
|
||||||
|
TEST_ASSERT_EQUAL(PackageCounter,1);
|
||||||
|
|
||||||
|
|
||||||
|
FirmwareDone done = {
|
||||||
|
.crc_fw = DONE_CRC,
|
||||||
|
.device_id = DONE_DEVICE,
|
||||||
|
.size = DONE_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
transmit_package(UsbPackageType_FIRMWAREDONE, FirmwareDone_fields, &done);
|
||||||
|
UsbDataHandler_Runner();
|
||||||
|
TEST_ASSERT_EQUAL(DoneCounter,1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DataClbk_FirmwareStart(void * msg, uint32_t length) {
|
||||||
|
FirmwareStart start;
|
||||||
|
memcpy(&start,msg,sizeof(start));
|
||||||
|
TEST_ASSERT_EQUAL(sizeof(FirmwareStart), length);
|
||||||
|
TEST_ASSERT_EQUAL(START_SIZE, start.size);
|
||||||
|
TEST_ASSERT_EQUAL(START_PACKAES, start.packages);
|
||||||
|
TEST_ASSERT_EQUAL(START_CRC, start.crc_fw);
|
||||||
|
TEST_ASSERT_EQUAL(START_DEVICE, start.device_id);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(START_NAME,start.name);
|
||||||
|
StartCounter++;
|
||||||
|
}
|
||||||
|
void DataClbk_FirmwarePackage(void * msg, uint32_t length) {
|
||||||
|
FirmwarePackage pack;
|
||||||
|
memcpy(&pack,msg,sizeof(pack));
|
||||||
|
TEST_ASSERT_EQUAL(sizeof(FirmwarePackage), length);
|
||||||
|
TEST_ASSERT_EQUAL(PACK_COUTNER, pack.counter);
|
||||||
|
TEST_ASSERT_EQUAL(PACK_CRC, pack.crc_pac);
|
||||||
|
TEST_ASSERT_EQUAL(PACK_DEVICE, pack.device_id);
|
||||||
|
TEST_ASSERT_EQUAL(PACK_DATA_SIZE, pack.data.size);
|
||||||
|
PackageCounter++;
|
||||||
|
}
|
||||||
|
void DataClbk_FirmwarePackageAck(void * msg, uint32_t length) {
|
||||||
|
FirmwarePackageAck ack;
|
||||||
|
memcpy(&ack,msg,sizeof(ack));
|
||||||
|
TEST_ASSERT_EQUAL(sizeof(FirmwarePackageAck), length);
|
||||||
|
TEST_ASSERT(ack.ack);
|
||||||
|
TEST_ASSERT_EQUAL(ACK_COUTNER, ack.counter);
|
||||||
|
TEST_ASSERT_EQUAL(ACK_CRC, ack.crc_pac);
|
||||||
|
TEST_ASSERT_EQUAL(ACK_DEVICE, ack.device_id);
|
||||||
|
|
||||||
|
AckCounter++;
|
||||||
|
}
|
||||||
|
void DataClbk_FirmwareDone(void * msg, uint32_t length) {
|
||||||
|
FirmwareDone done;
|
||||||
|
memcpy(&done,msg,sizeof(done));
|
||||||
|
TEST_ASSERT_EQUAL(sizeof(FirmwareDone), length);
|
||||||
|
TEST_ASSERT_EQUAL(DONE_CRC,done.crc_fw);
|
||||||
|
TEST_ASSERT_EQUAL(DONE_DEVICE,done.device_id);
|
||||||
|
TEST_ASSERT_EQUAL(DONE_SIZE,done.size);
|
||||||
|
DoneCounter++;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user