diff --git a/.gitmodules b/.gitmodules index 4b5e7c7a..b0e44b10 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,4 @@ [submodule "src/Middlewares/SUFST/can-defs"] path = src/Middlewares/SUFST/can-defs url = https://github.com/sufst/can-defs + branch = feat/vcu-power-save-mode diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 1da2201d..d38957f9 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,8 +1,54 @@ { "configurations": [ + { + "name": "arm-none-eabi-gcc (Linux)", + "compileCommands": [ + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/compile_commands.json" + ], + "includePath": [ + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/SUFST/Inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/SUFST/Inc/Functions", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Core/Inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/STM32F7xx_HAL_Driver/Inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/CMSIS/Device/ST/STM32F7xx/Include", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/CMSIS/**", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Middlewares/ST/threadx/common/inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Middlewares/ST/threadx/ports/cortex_m7/gnu/inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/STM32F7xx_HAL_Driver/Inc" + ], + "defines": [ + "TX_INCLUDE_USER_DEFINE_FILE", + "USE_HAL_DRIVER", + "STM32F746xx" + ], + "cStandard": "gnu11", + "intelliSenseMode": "gcc-arm", + "configurationProvider": "ms-vscode.makefile-tools", + "compileCommandsInCppPropertiesJson": [ + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/compile_commands.json" + ], + "configurationProviderInCppPropertiesJson": "ms-vscode.makefile-tools", + "mergeConfigurations": false, + "browse": { + "path": [ + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/SUFST/Inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Core/Inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/STM32F7xx_HAL_Driver/Inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/CMSIS/Device/ST/STM32F7xx/Include", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/CMSIS/**", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Middlewares/ST/threadx/common/inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Middlewares/ST/threadx/ports/cortex_m7/gnu/inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu/src/Drivers/STM32F7xx_HAL_Driver/Inc", + "/home/r_kirkbride/Documents/GitHub/sufst/vcu" + ], + "limitSymbolsToIncludedHeaders": true + }, + "compilerPath": "/usr/bin/arm-none-eabi-gcc", + "compilerPathInCppPropertiesJson": "/usr/bin/arm-none-eabi-gcc" + }, { "name": "arm-none-eabi-gcc (macOS)", - "compileCommands": "${workspaceFolder}/compile_commands.json", + "compileCommands": ["${workspaceFolder}/compile_commands.json"], "includePath": [ "${workspaceFolder}/src/SUFST/Inc", "${workspaceFolder}/src/Core/Inc", @@ -12,7 +58,12 @@ "${workspaceFolder}/src/Middlewares/ST/threadx/common/inc", "${workspaceFolder}/src/Middlewares/ST/threadx/ports/cortex_m7/gnu/inc", "${workspaceFolder}/src/SUFST/Inc/CAN", - "${workspaceFolder}/src/Drivers/STM32F7xx_HAL_Driver/Inc" + "${workspaceFolder}/src/Drivers/STM32F7xx_HAL_Driver/Inc", + "${workspaceFolder}/src/Middlewares/SUFST/rtcan/inc", + "${workspaceFolder}/src/SUFST/Inc/Interfaces", + "${workspaceFolder}/src/SUFST/Inc/Functions", + "${workspaceFolder}/src/SUFST/Inc/Services", + "${workspaceFolder}/src/Middlewares/SUFST/can-defs/out" ], "defines": [ "TX_INCLUDE_USER_DEFINE_FILE", @@ -21,11 +72,12 @@ ], "cStandard": "gnu11", "intelliSenseMode": "gcc-arm", - "configurationProvider": "ms-vscode.makefile-tools" + "configurationProvider": "ms-vscode.makefile-tools", + "compilerPath": "/usr/bin/arm-none-eabi-gcc" }, { "name": "arm-none-eabi-gcc (Windows)", - "compileCommands": "${workspaceFolder}/compile_commands.json", + "compileCommands": ["${workspaceFolder}/compile_commands.json"], "includePath": [ "${workspaceFolder}/**", "${workspaceFolder}/src/Drivers/**" diff --git a/.vscode/settings.json b/.vscode/settings.json index b8ef2af9..a0ccad76 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -49,9 +49,11 @@ "status.h": "c", "torque_map_funcs.h": "c", "rtds.h": "c", - "pm100.h": "c" + "pm100.h": "c", + "canrx.h": "c" }, "cortex-debug.variableUseNaturalFormat": true, - "C_Cpp.errorSquiggles": "Enabled", - "mcu-debug.rtos-views.showRTOS": false + "C_Cpp.errorSquiggles": "enabled", + "mcu-debug.rtos-views.showRTOS": false, + "C_Cpp.default.compilerPath": "arm-none-eabi-gcc" } diff --git a/Makefile b/Makefile index ea50757d..ad39531f 100644 --- a/Makefile +++ b/Makefile @@ -101,6 +101,7 @@ src/SUFST/Src/Interfaces/rtds.c \ src/SUFST/Src/Interfaces/scs.c \ src/SUFST/Src/Interfaces/trc.c \ src/SUFST/Src/Services/canbc.c \ +src/SUFST/Src/Services/canrx.c \ src/SUFST/Src/Services/ctrl.c \ src/SUFST/Src/Services/dash.c \ src/SUFST/Src/Services/pm100.c \ diff --git a/src/Middlewares/SUFST/can-defs b/src/Middlewares/SUFST/can-defs index f50171db..2c1e9c3e 160000 --- a/src/Middlewares/SUFST/can-defs +++ b/src/Middlewares/SUFST/can-defs @@ -1 +1 @@ -Subproject commit f50171dba2f1c196955db9003b73f4c42231bdb6 +Subproject commit 2c1e9c3eaefb5ae5d448d078295c1573ada043d1 diff --git a/src/SUFST/Inc/Functions/torque_map.h b/src/SUFST/Inc/Functions/torque_map.h index 9c3b268f..407b4d65 100644 --- a/src/SUFST/Inc/Functions/torque_map.h +++ b/src/SUFST/Inc/Functions/torque_map.h @@ -24,6 +24,11 @@ typedef struct _torque_map_t uint16_t deadzone_end; // end of deadzone float deadzone_scale; // scale factor for inputs const config_torque_map_t* config_ptr; // configuration + uint16_t output_max; + uint16_t + limit_min; // minimum Torque request at the end of the limit (Nm *10) + uint8_t limit_start; // BMS temp to start limiting torque (Celcius) + uint8_t limit_end; // BMS temp for maximum toque limiting (Celcius) } torque_map_t; /* @@ -31,6 +36,9 @@ typedef struct _torque_map_t */ status_t torque_map_init(torque_map_t* map_ptr, const config_torque_map_t* config_ptr); -uint16_t torque_map_apply(torque_map_t* map_ptr, uint16_t input); +uint16_t torque_map_apply(torque_map_t* map_ptr, + uint16_t input, + uint8_t bms_temp, + bool* power_saving); #endif \ No newline at end of file diff --git a/src/SUFST/Inc/Interfaces/scs.h b/src/SUFST/Inc/Interfaces/scs.h index 3f73b7ec..febedc0f 100644 --- a/src/SUFST/Inc/Interfaces/scs.h +++ b/src/SUFST/Inc/Interfaces/scs.h @@ -37,7 +37,7 @@ typedef struct uint32_t max_bounds_diff; // cached bounds difference for validation const config_scs_t* config_ptr; // configuration status_t status; - status_t status_verbose; + scs_status_t status_verbose; } scs_t; /* diff --git a/src/SUFST/Inc/Services/canrx.h b/src/SUFST/Inc/Services/canrx.h new file mode 100644 index 00000000..c3e812a5 --- /dev/null +++ b/src/SUFST/Inc/Services/canrx.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * @file canrx.h + * @author Robert Kirkbride (@r-kirkbride, rgak1g24@soton.ac.uk) + * @brief Can Listener Service + * @details This service is responsible for listening for CAN messages required + * by other services + *****************************************************************************/ + +#ifndef CANRX_H +#define CANRX_H + +#include +#include +#include +#include + +#include "config.h" +#include "log.h" +#include "status.h" + +#define CANRX_QUEUE_SIZE 10 // 10 items + +#define CANRX_ERROR_NONE 0x00 // no errors +#define CANRX_ERROR_INIT 0x01 // initialisation error +#define CANRX_ERROR_BROADCAST_TIMEOUT 0x02 // no broadcasts received +#define CANRX_ERROR_POST_FAULT 0x04 // power-on self-test fault +#define CANRX_ERROR_RUN_FAULT 0x08 // runtime fault + +/** + * @brief CANRX context + */ +typedef struct +{ + TX_THREAD thread; + rtcan_handle_t* rtcan_c_ptr; + rtcan_handle_t* rtcan_s_ptr; + TX_QUEUE can_c_rx_queue; + TX_QUEUE can_s_rx_queue; + ULONG can_rx_queue_mem[CANRX_QUEUE_SIZE]; + TX_MUTEX state_mutex; + bool broadcasts_valid; + struct can_s_msgid_0_x202_t msgid_x202; + uint16_t error; + const config_canrx_t* config_ptr; +} canrx_context_t; + +/* + * public functions + */ +status_t canrx_init(canrx_context_t* canrx_ptr, + rtcan_handle_t* rtcan_c_ptr, + rtcan_handle_t* rtcan_s_ptr, + TX_BYTE_POOL* stack_pool_ptr, + const config_canrx_t* config_ptr); + +#endif diff --git a/src/SUFST/Inc/Services/ctrl.h b/src/SUFST/Inc/Services/ctrl.h index e5724e0e..f85651ef 100644 --- a/src/SUFST/Inc/Services/ctrl.h +++ b/src/SUFST/Inc/Services/ctrl.h @@ -15,6 +15,7 @@ #include "apps.h" #include "bps.h" #include "canbc.h" +#include "canrx.h" #include "config.h" #include "dash.h" #include "log.h" @@ -67,10 +68,12 @@ typedef struct int16_t motor_temp; int16_t inv_temp; int8_t max_temp; + uint8_t bms_temp; bool inverter_pwr; bool pump_pwr; bool fan_pwr; + bool power_saving; uint32_t neg_air_start; uint32_t precharge_start; // precharge start time in ticks @@ -80,6 +83,7 @@ typedef struct dash_context_t* dash_ptr; // dash service pm100_context_t* pm100_ptr; // PM100 service canbc_context_t* canbc_ptr; // CANBC service + canrx_context_t* canrx_ptr; // CANRX service tick_context_t* tick_ptr; // tick thread (reads certain sensors) torque_map_t torque_map; // torque map (APPS -> torque request) @@ -98,6 +102,7 @@ status_t ctrl_init(ctrl_context_t* ctrl_ptr, pm100_context_t* pm100_ptr, tick_context_t* tick_ptr, canbc_context_t* canbc_ptr, + canrx_context_t* canrx_ptr, TX_BYTE_POOL* stack_pool_ptr, const config_ctrl_t* config_ptr, const config_rtds_t* rtds_config_ptr, diff --git a/src/SUFST/Inc/config.h b/src/SUFST/Inc/config.h index 1ca270c8..d8789033 100644 --- a/src/SUFST/Inc/config.h +++ b/src/SUFST/Inc/config.h @@ -107,6 +107,9 @@ typedef struct { uint16_t input_max; // maximum input value (range must be zero to max) uint16_t output_max; // maximum output value (Nm * 10) float deadzone_fraction; // fraction of input range for deadzone + uint16_t limit_min; // minimum Torque request at the end of the limit (Nm *10) + uint8_t limit_start; // BMS temp to start limiting torque (Celcius) + uint8_t limit_end; // BMS temp for maximum toque limiting (Celcius) } config_torque_map_t; /** @@ -128,6 +131,14 @@ typedef struct { uint32_t broadcast_period_ticks; // ticks between broadcasts } config_canbc_t; +/** + * @brief CAN recieving service + */ +typedef struct { + config_thread_t thread; // CANRX thread config + uint32_t broadcast_timeout_ticks; // maximum number of ticks to wait for a broadcast +} config_canrx_t; + typedef struct { config_thread_t thread; // thread config @@ -197,6 +208,7 @@ typedef struct { config_pm100_t pm100; config_tick_t tick; config_canbc_t canbc; + config_canrx_t canrx; config_heartbeat_t heartbeat; config_log_t log; config_rtos_t rtos; diff --git a/src/SUFST/Inc/vcu.h b/src/SUFST/Inc/vcu.h index dd6f2d10..03fae52f 100644 --- a/src/SUFST/Inc/vcu.h +++ b/src/SUFST/Inc/vcu.h @@ -20,8 +20,8 @@ #include "heartbeat.h" #include "log.h" #include "pm100.h" -#include "tick.h" #include "status.h" +#include "tick.h" /** * @brief VCU context @@ -30,17 +30,18 @@ */ typedef struct { - rtcan_handle_t rtcan_s; // RTCAN service for sensors CAN bus - rtcan_handle_t rtcan_c; // RTCAN service for critical systems CAN bus - canbc_context_t canbc; // CAN broadcasting service instance - dash_context_t dash; // dash service - ctrl_context_t ctrl; // control service - pm100_context_t pm100; // PM100 service - tick_context_t tick; - heartbeat_context_t heartbeat; // heartbeat service - log_context_t log; // logging service - uint32_t err; // current error code - const config_t* config_ptr; // pointer to global VCU configuration + rtcan_handle_t rtcan_s; // RTCAN service for sensors CAN bus + rtcan_handle_t rtcan_c; // RTCAN service for critical systems CAN bus + canbc_context_t canbc; // CAN broadcasting service instance + canrx_context_t canrx; // CAN recieving service instance + dash_context_t dash; // dash service + ctrl_context_t ctrl; // control service + pm100_context_t pm100; // PM100 service + tick_context_t tick; + heartbeat_context_t heartbeat; // heartbeat service + log_context_t log; // logging service + uint32_t err; // current error code + const config_t* config_ptr; // pointer to global VCU configuration } vcu_context_t; diff --git a/src/SUFST/Src/Functions/torque_map.c b/src/SUFST/Src/Functions/torque_map.c index 0f9e5277..c5beee00 100644 --- a/src/SUFST/Src/Functions/torque_map.c +++ b/src/SUFST/Src/Functions/torque_map.c @@ -6,6 +6,10 @@ static inline uint16_t apply_deadzone(torque_map_t* map_ptr, uint16_t input); static uint16_t null_torque_map(torque_map_t* map_ptr, uint16_t input); static uint16_t linear_torque_map(torque_map_t* map_ptr, uint16_t input); +static inline uint16_t apply_temp_limit(torque_map_t* map_ptr, + uint16_t input, + uint8_t bms_temp, + bool* power_saving); /** * @brief Initialises the torque map @@ -46,6 +50,10 @@ status_t torque_map_init(torque_map_t* map_ptr, break; }; + map_ptr->limit_min = config_ptr->limit_min; + map_ptr->limit_start = config_ptr->limit_start; + map_ptr->limit_end = config_ptr->limit_end; + return status; } @@ -55,12 +63,16 @@ status_t torque_map_init(torque_map_t* map_ptr, * @param[in] map_ptr Torque map * @param[in] input Input value */ -uint16_t torque_map_apply(torque_map_t* map_ptr, uint16_t input) +uint16_t torque_map_apply(torque_map_t* map_ptr, + uint16_t input, + uint8_t bms_temp, + bool* power_saving) { const uint16_t input_deadzone = apply_deadzone(map_ptr, input); const uint16_t torque = map_ptr->map_func(map_ptr, input_deadzone); - - return torque; + const uint16_t limited_torque + = apply_temp_limit(map_ptr, torque, bms_temp, power_saving); + return limited_torque; } /** @@ -110,4 +122,50 @@ uint16_t linear_torque_map(torque_map_t* map_ptr, uint16_t input) // TODO: clip to range return torque; +} + +uint16_t apply_temp_limit(torque_map_t* map_ptr, + uint16_t input, + uint8_t bms_temp, + bool* power_saving) +{ + uint16_t result = 0; + if (bms_temp < map_ptr->limit_start) + { + result = input; + *power_saving = false; + } + else if (bms_temp > map_ptr->limit_end) + { + if (input < map_ptr->limit_min) + { + result = input; + } + else + { + result = map_ptr->limit_min; + } + *power_saving = true; + } + else + { + uint16_t max_torque + = map_ptr->config_ptr->output_max + - (map_ptr->config_ptr->output_max - map_ptr->limit_min) + * (bms_temp - map_ptr->limit_start) + / (map_ptr->limit_end - map_ptr->limit_start); + + if (input < max_torque) + { + result = input; + } + else + { + result = max_torque; + } + + *power_saving = true; + } + + return result; } \ No newline at end of file diff --git a/src/SUFST/Src/Interfaces/scs.c b/src/SUFST/Src/Interfaces/scs.c index 48472a58..a3208401 100644 --- a/src/SUFST/Src/Interfaces/scs.c +++ b/src/SUFST/Src/Interfaces/scs.c @@ -74,7 +74,7 @@ status_t scs_read(scs_t* scs_ptr, uint16_t* reading_ptr) scs_ptr->config_ptr->min_adc, scs_ptr->max_bounds_diff); scs_ptr->is_valid - = scs_ptr->status_verbose == STATUS_OK + = scs_ptr->status_verbose == STATUS_THRESHOLD_OK || scs_ptr->status_verbose == STATUS_THRESHOLD_WARNING; if (scs_ptr->is_valid) @@ -166,7 +166,7 @@ scs_status_t validate(uint16_t adc_reading, uint16_t min_adc_reading, uint32_t max_diff) { - status_t status = STATUS_THRESHOLD_ERROR; + scs_status_t status = STATUS_THRESHOLD_ERROR; uint16_t low_diff = 0; uint16_t high_diff = 0; @@ -182,7 +182,7 @@ scs_status_t validate(uint16_t adc_reading, if (!low_diff && !high_diff) { - status = STATUS_OK; + status = STATUS_THRESHOLD_OK; } else if ((low_diff < max_diff) && (high_diff < max_diff)) { diff --git a/src/SUFST/Src/Services/canrx.c b/src/SUFST/Src/Services/canrx.c new file mode 100644 index 00000000..33576cca --- /dev/null +++ b/src/SUFST/Src/Services/canrx.c @@ -0,0 +1,224 @@ +#include "canrx.h" + +#include +#include + +/* + * internal function prototypes + */ +static void canrx_thread_entry(ULONG input); +static void process_broadcast(canrx_context_t* canrx_ptr, + const rtcan_msg_t* msg_ptr); + +/** + * @brief Initialises the CANRX service + * + * @param[in] canrx_ptr CANRX context + * @param[in] stack_pool_ptr Memory pool for service thread stack + * @param[in] rtcan_c_ptr RTCAN C instance for receiving broadcasts + * @param[in] rtcan_s_ptr RTCAN S instance for sending precharge cmd + * @param[in] config_ptr Configuration + */ +status_t canrx_init(canrx_context_t* canrx_ptr, + rtcan_handle_t* rtcan_c_ptr, + rtcan_handle_t* rtcan_s_ptr, + TX_BYTE_POOL* stack_pool_ptr, + const config_canrx_t* config_ptr) +{ + canrx_ptr->config_ptr = config_ptr; + canrx_ptr->rtcan_c_ptr = rtcan_c_ptr; + canrx_ptr->rtcan_s_ptr = rtcan_s_ptr; + canrx_ptr->error = CANRX_ERROR_NONE; + canrx_ptr->broadcasts_valid = false; + + status_t status = STATUS_OK; + + // create service thread + void* stack_ptr = NULL; + UINT tx_status = tx_byte_allocate(stack_pool_ptr, + &stack_ptr, + config_ptr->thread.stack_size, + TX_NO_WAIT); + + if (tx_status == TX_SUCCESS) + { + tx_status = tx_thread_create(&canrx_ptr->thread, + (CHAR*) config_ptr->thread.name, + canrx_thread_entry, + (ULONG) canrx_ptr, + stack_ptr, + config_ptr->thread.stack_size, + config_ptr->thread.priority, + config_ptr->thread.priority, + TX_NO_TIME_SLICE, + TX_AUTO_START); + } + + // create CAN receive queue + if (tx_status == TX_SUCCESS) + { + tx_status = tx_queue_create(&canrx_ptr->can_c_rx_queue, + NULL, + TX_1_ULONG, + canrx_ptr->can_rx_queue_mem, + sizeof(canrx_ptr->can_rx_queue_mem)); + } + + if (tx_status == TX_SUCCESS) + { + tx_status = tx_queue_create(&canrx_ptr->can_s_rx_queue, + NULL, + TX_1_ULONG, + canrx_ptr->can_rx_queue_mem, + sizeof(canrx_ptr->can_rx_queue_mem)); + } + + // create state mutex + if (tx_status == TX_SUCCESS) + { + tx_status = tx_mutex_create(&canrx_ptr->state_mutex, NULL, TX_INHERIT); + } + + if (tx_status != TX_SUCCESS) + { + status = STATUS_ERROR; + } + + // check all ok + if (status != STATUS_OK) + { + tx_thread_terminate(&canrx_ptr->thread); + } + + // turn off power + HAL_GPIO_WritePin(STATUS_GPIO_Port, // This pin used to be called STATUS + STATUS_Pin, + GPIO_PIN_RESET); + + return status; +} + +/** + * @brief CANRX service thread entry function + * + * @details This thread is responsible for receiving and processing broadcast + * messages from the CANRX + */ +void canrx_thread_entry(ULONG input) +{ + canrx_context_t* canrx_ptr = (canrx_context_t*) input; + const config_canrx_t* config_ptr = canrx_ptr->config_ptr; + + // set up RTCAN subscriptions + /* This is commented, as there are currently no can_c_subscriptions + Uncomment to add a can_c_subscription + + uint32_t can_c_subscriptions[0]; + + for (uint32_t i = 0; + i < sizeof(can_c_subscriptions) / sizeof(can_c_subscriptions[0]); + i++) + { + rtcan_status_t status = rtcan_subscribe(canrx_ptr->rtcan_c_ptr, + can_c_subscriptions[i], + &canrx_ptr->can_c_rx_queue); + + if (status != RTCAN_OK) + { + // TODO: update broadcast states with error + tx_thread_terminate(&canrx_ptr->thread); + } + } + */ + + uint32_t can_s_subscriptions[] = {CAN_S_MSGID_0_X202_FRAME_ID}; + + for (uint32_t i = 0; + i < sizeof(can_s_subscriptions) / sizeof(can_s_subscriptions[0]); + i++) + { + rtcan_status_t status = rtcan_subscribe(canrx_ptr->rtcan_c_ptr, + can_s_subscriptions[i], + &canrx_ptr->can_s_rx_queue); + + if (status != RTCAN_OK) + { + // TODO: update broadcast states with error + tx_thread_terminate(&canrx_ptr->thread); + } + } + + // process incoming messages, or timeout + while (1) + { + UINT status = TX_QUEUE_ERROR; + rtcan_msg_t* msg_ptr = NULL; + UINT can_s_status + = tx_queue_receive(&canrx_ptr->can_s_rx_queue, + &msg_ptr, + config_ptr->broadcast_timeout_ticks); + + if (can_s_status == TX_SUCCESS && msg_ptr != NULL) + { + canrx_ptr->broadcasts_valid = true; + process_broadcast(canrx_ptr, msg_ptr); + rtcan_msg_consumed(canrx_ptr->rtcan_s_ptr, msg_ptr); + status = TX_SUCCESS; + } + + msg_ptr = NULL; + UINT can_c_status + = tx_queue_receive(&canrx_ptr->can_c_rx_queue, + &msg_ptr, + config_ptr->broadcast_timeout_ticks); + + if (can_c_status == TX_SUCCESS && msg_ptr != NULL) + { + canrx_ptr->broadcasts_valid = true; + process_broadcast(canrx_ptr, msg_ptr); + rtcan_msg_consumed(canrx_ptr->rtcan_c_ptr, msg_ptr); + status = TX_SUCCESS; + } + + if (can_s_status == TX_QUEUE_EMPTY && can_c_status == TX_QUEUE_EMPTY) + { + canrx_ptr->broadcasts_valid = false; + LOG_ERROR("CANRX recieving timed out\n"); + } + else if (status == TX_SUCCESS) + { + canrx_ptr->broadcasts_valid = true; + process_broadcast(canrx_ptr, msg_ptr); + rtcan_msg_consumed(canrx_ptr->rtcan_c_ptr, msg_ptr); + } + else + { + LOG_ERROR("CANRX other error\n"); + } + } +} + +/** + * @brief Processes incoming broadcast messages + * + * @param[in] canrx_ptr CANRX context + * @param[in] msg_ptr Incoming message + */ +void process_broadcast(canrx_context_t* canrx_ptr, const rtcan_msg_t* msg_ptr) +{ + switch (msg_ptr->identifier) + { + + case CAN_S_MSGID_0_X202_FRAME_ID: + { + can_s_msgid_0_x202_unpack(&canrx_ptr->msgid_x202, + msg_ptr->data, + msg_ptr->length); + + break; + } + + default: + break; + } +} diff --git a/src/SUFST/Src/Services/ctrl.c b/src/SUFST/Src/Services/ctrl.c index 445fd0a3..59169b8f 100644 --- a/src/SUFST/Src/Services/ctrl.c +++ b/src/SUFST/Src/Services/ctrl.c @@ -41,6 +41,7 @@ status_t ctrl_init(ctrl_context_t* ctrl_ptr, pm100_context_t* pm100_ptr, tick_context_t* tick_ptr, canbc_context_t* canbc_ptr, + canrx_context_t* canrx_ptr, TX_BYTE_POOL* stack_pool_ptr, const config_ctrl_t* config_ptr, const config_rtds_t* rtds_config_ptr, @@ -51,6 +52,7 @@ status_t ctrl_init(ctrl_context_t* ctrl_ptr, ctrl_ptr->pm100_ptr = pm100_ptr; ctrl_ptr->tick_ptr = tick_ptr; ctrl_ptr->canbc_ptr = canbc_ptr; + ctrl_ptr->canrx_ptr = canrx_ptr; ctrl_ptr->config_ptr = config_ptr; ctrl_ptr->rtds_config_ptr = rtds_config_ptr; ctrl_ptr->error = CTRL_ERROR_NONE; @@ -63,6 +65,7 @@ status_t ctrl_init(ctrl_context_t* ctrl_ptr, ctrl_ptr->inverter_pwr = false; ctrl_ptr->pump_pwr = false; ctrl_ptr->fan_pwr = false; + ctrl_ptr->power_saving = false; // create the thread void* stack_ptr = NULL; @@ -353,9 +356,13 @@ void ctrl_state_machine_tick(ctrl_context_t* ctrl_ptr) { ctrl_ptr->apps_bps_start = tx_time_get(); } - - ctrl_ptr->torque_request = torque_map_apply(&ctrl_ptr->torque_map, - ctrl_ptr->apps_reading); + ctrl_ptr->bms_temp + = ctrl_ptr->canrx_ptr->msgid_x202.bms_high_temperature; + ctrl_ptr->torque_request + = torque_map_apply(&ctrl_ptr->torque_map, + ctrl_ptr->apps_reading, + ctrl_ptr->bms_temp, + &ctrl_ptr->power_saving); LOG_INFO("ADC: %d, Torque: %d\n", ctrl_ptr->apps_reading, @@ -528,6 +535,7 @@ void ctrl_update_canbc_states(ctrl_context_t* ctrl_ptr) states->temps.vcu_max_temp = (int8_t) ctrl_ptr->max_temp; states->state.vcu_ctrl_state = (uint8_t) ctrl_ptr->state; states->state.vcu_drs_active = ctrl_ptr->shdn_reading; + states->state.vcu_power_saving = (uint8_t) ctrl_ptr->power_saving; states->errors.vcu_ctrl_error = ctrl_ptr->error; states->pdm.inverter = ctrl_ptr->inverter_pwr; states->pdm.pump = ctrl_ptr->pump_pwr; diff --git a/src/SUFST/Src/config.c b/src/SUFST/Src/config.c index 43218b62..89eb2e25 100644 --- a/src/SUFST/Src/config.c +++ b/src/SUFST/Src/config.c @@ -111,7 +111,10 @@ static const config_t config_instance = { .function = TORQUE_MAP_LINEAR, .input_max = 100, .output_max = 1500, - .deadzone_fraction = 0.15f + .deadzone_fraction = 0.15f, + .limit_min = 300, + .limit_start = 50, + .limit_end = 60 }, .pm100 = { .thread = { @@ -140,6 +143,14 @@ static const config_t config_instance = { }, .broadcast_period_ticks = SECONDS_TO_TICKS(0.1) }, + .canrx = { + .thread = { + .name = "CANRX", + .priority = 3, + .stack_size = 1024 + }, + .broadcast_timeout_ticks = SECONDS_TO_TICKS(10), + }, .heartbeat = { .thread = { .name = "HEARTBEAT", diff --git a/src/SUFST/Src/vcu.c b/src/SUFST/Src/vcu.c index 00431df8..968ea9cf 100644 --- a/src/SUFST/Src/vcu.c +++ b/src/SUFST/Src/vcu.c @@ -83,6 +83,16 @@ status_t vcu_init(vcu_context_t* vcu_ptr, &vcu_ptr->config_ptr->canbc); } + // CAN recieve service + if (status == STATUS_OK) + { + status = canrx_init(&vcu_ptr->canrx, + &vcu_ptr->rtcan_c, + &vcu_ptr->rtcan_s, + app_mem_pool, + &vcu_ptr->config_ptr->canrx); + } + // dash if (status == STATUS_OK) { @@ -110,6 +120,7 @@ status_t vcu_init(vcu_context_t* vcu_ptr, &vcu_ptr->pm100, &vcu_ptr->tick, &vcu_ptr->canbc, + &vcu_ptr->canrx, app_mem_pool, &vcu_ptr->config_ptr->ctrl, &vcu_ptr->config_ptr->rtds,