Skip to content

Commit

Permalink
Revisions to SendCarCAN and test file to allow messages to be inspect…
Browse files Browse the repository at this point in the history
…ed in GDB using variables instead of prints which were overwhelming UART.
  • Loading branch information
KnockbackNemo committed Nov 17, 2023
1 parent 8bdf6bb commit 362628e
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 57 deletions.
4 changes: 2 additions & 2 deletions Apps/Inc/SendCarCAN.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ void SendCarCAN_Init();
void SendCarCAN_Put(CANDATA_t message);

/**
* @brief print SendCarCAN_Q put/get for debug purposes
* @brief return the space left in SendCarCAN_Q for debug purposes
*/
void print_SendCarCAN_Q(void);
uint8_t get_SendCarCAN_Q_Space(void);

#endif
9 changes: 3 additions & 6 deletions Apps/Src/SendCarCAN.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,10 @@ static OS_MUTEX CarCAN_Mtx;
static void Task_PutIOState(void *p_arg);

/**
* @brief print SendCarCAN_Q put/get for debug purposes
* @brief return the space left in SendCarCAN_Q for debug purposes
*/
void print_SendCarCAN_Q(void) {
if(SendCarCAN_Q_is_full(&CANFifo)) {
printf("\n\rSendCarCAN_Q is full.");
}
printf("\n\rSendCarCAN_Q put: %d\n\rSendCarCAN_Q get: %d", CANFifo.put, CANFifo.get);
uint8_t get_SendCarCAN_Q_Space(void) {
return (CANFifo.get - CANFifo.put - 1) % (sizeof CANFifo.buffer / sizeof CANFifo.buffer[0]);
}

/**
Expand Down
155 changes: 106 additions & 49 deletions Tests/Test_App_SendCarCAN.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
*
* This test is intended to be run on hardware with CarCAN in LoopBack mode.
* It is also intended to be tested using the motor controller on to read motor messages.
* The idea is to use "display msgReadCount" in GDB so that the program can be stopped intermittently to view CAN stats.
* Alternatively, you can just use it to spin up tasks and then check output using a logic analyzer.
*
* If TEST_SOFTWARE is defined prior to compilation, then a task will be created to simulate the motor controller.
* In this case, MotorCAN should be in LoopBack mode.
*/

#include "Tasks.h"
Expand All @@ -22,23 +26,44 @@
#include "Display.h"
#include "UpdateDisplay.h"

#define NUM_MOTOR_MSGS 15 // Messages received from the motor controller
#define TEST_SOFTWARE // Uncomment to do a software test with a fake motor controller. (Motorcan must be in loopback mode)

#define NUM_MOTOR_MSGS 15 // Messages we forward from the motor controller
#define NUM_NONMOTOR_MSGS 2 // We also send IO_STATE and CONTROL_MODE
#define IO_STATE_IDX 0 // index in msgArray for tracking info
#define CONTROL_MODE_IDX 1
#define MOTOR_MSG_BASE_ADDRESS 0x240 // Offset to index into msgCount array

typedef struct {
CANDATA_t lastMsg;
uint16_t numReceived;
} msgInfo;

typedef struct {
uint32_t lastReceiveTime_ms;
uint16_t lastMsgReceived;
msgInfo msgArray[NUM_MOTOR_MSGS + NUM_NONMOTOR_MSGS + 1]; // Message types we send plus an extra space just in case
uint8_t SpaceLeftInQ;
} CANInfo;

static OS_TCB Task1TCB;

static OS_TCB Task1_TCB;
static CPU_STK Task1Stk[DEFAULT_STACK_SIZE];
#ifdef TEST_SOFTWARE
static OS_TCB TaskMC_TCB;
static CPU_STK TaskMC_Stk[DEFAULT_STACK_SIZE];
#endif
static OS_TCB TaskReadCAN_TCB;
static CPU_STK TaskReadCANStk[DEFAULT_STACK_SIZE];
static CPU_STK TaskReadCAN_Stk[DEFAULT_STACK_SIZE];

static uint32_t msgCount[20];
//static uint32_t msgCount[20];
static CANInfo msgReadCount = {0};

// Reads CarCAN and prints what we receive on UART
void Task_ReadCAN(void *arg)
{
//OS_ERR err;
OS_ERR err;
CANDATA_t dataBuf = {0};
//uint32_t ts;


while (1) {
Expand All @@ -47,69 +72,85 @@ void Task_ReadCAN(void *arg)
if (status == SUCCESS){
switch(dataBuf.ID) {
case IO_STATE: {
msgCount[0]++;
msgReadCount.msgArray[IO_STATE_IDX].numReceived++;
msgReadCount.msgArray[IO_STATE_IDX].lastMsg = dataBuf;
break;
}

case CONTROL_MODE: {
msgCount[1]++;
msgReadCount.msgArray[CONTROL_MODE_IDX].numReceived++;
memcpy((void *)&msgReadCount.msgArray[CONTROL_MODE_IDX].lastMsg, &dataBuf, sizeof dataBuf);
break;
}

default: {
uint8_t msgIdx = dataBuf.ID - MOTOR_MSG_BASE_ADDRESS;

if (msgIdx >= 0 && msgIdx < NUM_MOTOR_MSGS) { // Check if the message is from the motor controller
msgCount[msgIdx + 2]++; // If so, increment based on the ID
} else {
msgCount[20]++;
msgReadCount.msgArray[msgIdx + NUM_NONMOTOR_MSGS].numReceived++; // If so, increment based on the ID
memcpy((void *)&msgReadCount.msgArray[msgIdx + NUM_NONMOTOR_MSGS].lastMsg, &dataBuf, sizeof dataBuf);

} else { // In case we receive messages not otherwise accounted for
msgReadCount.msgArray[NUM_MOTOR_MSGS + NUM_NONMOTOR_MSGS].numReceived++;
memcpy((void *)(&msgReadCount.msgArray[NUM_MOTOR_MSGS + NUM_NONMOTOR_MSGS].lastMsg), &dataBuf, sizeof dataBuf);

}

}

}

// ts = (OSTimeGet(&err) / OS_CFG_TICK_RATE_HZ);

// printf("\n\r********* Received CANbus message **********");
// printf("\n\rAt: %5ld ms", ts);
// printf("\n\r Received %x %d", dataBuf.data[0], dataBuf.data[4]);

// switch(dataBuf.ID){

// case IO_STATE: {
// printf("\n\rReceived IO_STATE message of %x", dataBuf.data[0]);
// printf("\n\rAccelerator: %d", *((uint8_t*)(&dataBuf.data[0])));
// printf("\n\rBrake: %x", *((uint8_t*)(&dataBuf.data[1])));
// printf("\n\rPins: %x", dataBuf.data[2]);
// printf("\n\rContactors: %d", *((uint8_t*)(&dataBuf.data[3])));
// break;
msgReadCount.lastReceiveTime_ms = (OSTimeGet(&err) / OS_CFG_TICK_RATE_HZ);
msgReadCount.lastMsgReceived = dataBuf.ID;
msgReadCount.SpaceLeftInQ = get_SendCarCAN_Q_Space();

// }

// case CONTROL_MODE: {
// printf("\n\rReceived CONTROL_MODE message of %d", *((uint8_t*)(&dataBuf.data[0])));
// break;
// }



// default:{ // Some messages will only be received if CARCAN messages aren't filtered.
// printf("\n\rReceived an uncategorized message ID type of %x", dataBuf.ID);
// break; //for cases not handled currently
// }
// }
} else {
// CANbus read is unsuccessful
printf("\n\rCANbus_Read error of %x", status);
}

printf("\n\r**********************************");
}


}

#ifdef TEST_SOFTWARE
// Create a fake motor controller to send messages to the controls system via MotorCAN
void Task_MC(void *arg) {
OS_ERR err;
uint8_t loopCount = 0;
CANDATA_t motorMsg = {
.ID=VELOCITY,
.idx=0,
.data={0xD, 0xE, 0xA, 0xD, 0x0, 0x0, 0xE, 0xF},
};

while(1) {
if (++loopCount == 5) { // Only send these messages every 1000ms
loopCount = 0;
motorMsg.ID=TEMPERATURE;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
motorMsg.ID=ODOMETER_AMPHOURS;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
}
// Send these messages every 200ms
motorMsg.ID=MOTOR_STATUS;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
motorMsg.ID=MC_BUS;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
motorMsg.ID=MC_PHASE_CURRENT;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
motorMsg.ID=VOLTAGE_VEC;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
motorMsg.ID=CURRENT_VEC;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
motorMsg.ID=BACKEMF;
CANbus_Send(motorMsg, CAN_NON_BLOCKING, MOTORCAN);
OSTimeDlyHMSM(0, 0, 0, 200, OS_OPT_TIME_HMSM_STRICT, &err);
}

}
#endif



void Task1(void *arg)
Expand Down Expand Up @@ -175,11 +216,11 @@ void Task1(void *arg)
// Create task to read CANbus
OSTaskCreate(
(OS_TCB*)&TaskReadCAN_TCB,
(CPU_CHAR*)"Test_ReadCarCAN",
(CPU_CHAR*)"Task_ReadCAN",
(OS_TASK_PTR)Task_ReadCAN,
(void*)NULL,
(OS_PRIO)13, // Lower prio than other running tasks
(CPU_STK*)TaskReadCANStk,
(CPU_STK*)TaskReadCAN_Stk,
(CPU_STK_SIZE)WATERMARK_STACK_LIMIT,
(CPU_STK_SIZE)DEFAULT_STACK_SIZE,
(OS_MSG_QTY)0,
Expand Down Expand Up @@ -208,6 +249,26 @@ void Task1(void *arg)
);
assertOSError(err);

#ifdef TEST_SOFTWARE
// Create a task to simulate the motor controller
OSTaskCreate(
(OS_TCB*)&TaskMC_TCB,
(CPU_CHAR*)"Task_MC",
(OS_TASK_PTR)&Task_MC,
(void*)NULL,
(OS_PRIO)2, // The motor controller is "external" and shouldn't be delayed by other tasks
(CPU_STK*)TaskMC_Stk,
(CPU_STK_SIZE)WATERMARK_STACK_LIMIT,
(CPU_STK_SIZE)DEFAULT_STACK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK)0,
(void*)NULL,
(OS_OPT)(OS_OPT_TASK_STK_CLR),
(OS_ERR*)&err
);
assertOSError(err);
#endif


while (1) {
// SendTritium task will print Car State
Expand All @@ -228,10 +289,6 @@ void Task1(void *arg)
contactors |= contactorState << contactor;
}
printf("\n\rContactors: %x", contactors);
// Print how full CAN Queue is
printf("\n\r---- Queue data ----");
print_SendCarCAN_Q();

OSTimeDlyHMSM(0, 0, 0, 10 * FSM_PERIOD, OS_OPT_TIME_HMSM_STRICT, &err);
}

Expand All @@ -256,7 +313,7 @@ int main(void)
TaskSwHook_Init();

OSTaskCreate(
(OS_TCB *)&Task1TCB,
(OS_TCB *)&Task1_TCB,
(CPU_CHAR *)"Task 1",
(OS_TASK_PTR)Task1,
(void *)NULL,
Expand Down

0 comments on commit 362628e

Please sign in to comment.