From da4a67e016b49cc3ea306174cc0dd1c4bebbc65f Mon Sep 17 00:00:00 2001 From: ahoysal Date: Mon, 26 Jan 2026 20:58:15 -0800 Subject: [PATCH 01/44] added id to CAN RX callback --- Lib/Peripherals/CAN/Inc/can.h | 2 +- Lib/Peripherals/CAN/Src/can.c | 2 +- Lib/Peripherals/CAN/Test/can_tests.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index d37d614df..57f5dcd72 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -13,7 +13,7 @@ // RX Callback must perform a deep copy of the data // -typedef void (*CAN_RXCallback)(void *data, uint32_t size); +typedef void (*CAN_RXCallback)(uint32_t id, void *data, uint32_t size); typedef struct { // can baud rate is set by fdcan prescaler and RCC clock configurations FDCAN_GlobalTypeDef *fdcan_instance; // Base address of FDCAN peripheral in memory (FDCAN1, FDCAN2, FDCAN3 macros) diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 1bea5c95a..9663e1a31 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -398,7 +398,7 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) // stack allocation should be fine? Callback needs to terminate first before stack is popped // should switch this over to malloc at some point to avoid double copies? - handle->rx_callback(rx_data, rx_header.DataLength); + handle->rx_callback(rx_data, rx_header.DataLength, rx_header.Identifier); } /* whoopsie, don't need the rx buffer yet diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 6e436cc46..a3f3c5ffb 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -12,14 +12,14 @@ int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) return 0; } -void can_test_rx_callback2(void *data, uint32_t size) +void can_test_rx_callback2(void *data, uint32_t size, uint32_t id) { LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x\n", size, *(char *)data); // Is within an ISR, so needs to exit quickly return; } -void can_test_rx_callback1(void *data, uint32_t size) +void can_test_rx_callback1(void *data, uint32_t size, uint32_t id) { LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x\n", size, *(char *)data); From 05214b4da8018c9b1b1de846b0e76736a3b56978 Mon Sep 17 00:00:00 2001 From: ahoysal Date: Mon, 26 Jan 2026 21:12:02 -0800 Subject: [PATCH 02/44] Added enum as CAN identifier in RX --- CMakeLists.txt | 6 +++--- Lib/Peripherals/CAN/Inc/can.h | 3 ++- Lib/Peripherals/CAN/Test/can_tests.c | 9 +++++---- Lib/Peripherals/CAN/common.cmake | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bb3126aaf..09ef35697 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,9 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) set(lib_path "Lib") set(platform_path "${lib_path}/Platform") +# FIXME Temporary holdover for CAN messages until URCA is ready for merge +include("${lib_path}/FancyLayers-RENAME/GRCAN/TemporaryHoldover/temp.cmake") + # CMSIS and HAL/LL include("${lib_path}/Vendor/CMSIS_5/cmsis_5.cmake") include("${lib_path}/Vendor/STM32_HAL_LL/cube.cmake") @@ -44,9 +47,6 @@ include("${lib_path}/Peripherals/USART/common.cmake") include("${lib_path}/Peripherals/CAN/common.cmake") include("${lib_path}/FancyLayers-RENAME/ADC/adc.cmake") -# FIXME Temporary holdover for CAN messages until URCA is ready for merge -include("${lib_path}/FancyLayers-RENAME/GRCAN/TemporaryHoldover/temp.cmake") - message( STATUS "Build type: " diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index 57f5dcd72..e87e5e4e0 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -10,10 +10,11 @@ #include "can_platform_deps.h" #include "circularBuffer.h" +#include "GR_OLD_MSG_ID.h" // RX Callback must perform a deep copy of the data // -typedef void (*CAN_RXCallback)(uint32_t id, void *data, uint32_t size); +typedef void (*CAN_RXCallback)(void *data, uint32_t size, GR_OLD_MSG_ID ID); typedef struct { // can baud rate is set by fdcan prescaler and RCC clock configurations FDCAN_GlobalTypeDef *fdcan_instance; // Base address of FDCAN peripheral in memory (FDCAN1, FDCAN2, FDCAN3 macros) diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index a3f3c5ffb..2434c49f6 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -3,6 +3,7 @@ #include #include "can.h" +#include "GR_OLD_MSG_ID.h" // each family has a constant number of CAN peripherals @@ -12,16 +13,16 @@ int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) return 0; } -void can_test_rx_callback2(void *data, uint32_t size, uint32_t id) +void can_test_rx_callback2(void *data, uint32_t size, GR_OLD_MSG_ID id) { - LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x\n", size, *(char *)data); + LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %u\n", size, *(char *)data, id); // Is within an ISR, so needs to exit quickly return; } -void can_test_rx_callback1(void *data, uint32_t size, uint32_t id) +void can_test_rx_callback1(void *data, uint32_t size, GR_OLD_MSG_ID id) { - LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x\n", size, *(char *)data); + LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %u\n", size, *(char *)data, id); // Is within an ISR, so needs to exit quickly return; diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 120a4dcbe..5b56d3bc4 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -1,6 +1,6 @@ add_library(PERIPHERAL_CAN_LIB INTERFACE) -target_link_libraries(PERIPHERAL_CAN_LIB INTERFACE CircularBuffer_Lib) +target_link_libraries(PERIPHERAL_CAN_LIB INTERFACE CircularBuffer_Lib GR_OLD_CAN_MESSAGES) target_sources(PERIPHERAL_CAN_LIB INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Src/can.c) From 92619658782d668950c2992d509ca47f31ef6fba Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 05:17:08 +0000 Subject: [PATCH 03/44] Automatic CMake Format: Standardized formatting automatically --- Lib/Peripherals/CAN/common.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 5b56d3bc4..0f086ecf4 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -1,6 +1,11 @@ add_library(PERIPHERAL_CAN_LIB INTERFACE) -target_link_libraries(PERIPHERAL_CAN_LIB INTERFACE CircularBuffer_Lib GR_OLD_CAN_MESSAGES) +target_link_libraries( + PERIPHERAL_CAN_LIB + INTERFACE + CircularBuffer_Lib + GR_OLD_CAN_MESSAGES +) target_sources(PERIPHERAL_CAN_LIB INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Src/can.c) From f26d44fd85557718dd1cf19109accbad6d96ed99 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 05:18:10 +0000 Subject: [PATCH 04/44] Automatic Clang-Format: Standardized formatting automatically --- Lib/Peripherals/CAN/Inc/can.h | 2 +- Lib/Peripherals/CAN/Test/can_tests.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index e87e5e4e0..ce726981c 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -8,9 +8,9 @@ #error "Unsupported STM32 Family" #endif +#include "GR_OLD_MSG_ID.h" #include "can_platform_deps.h" #include "circularBuffer.h" -#include "GR_OLD_MSG_ID.h" // RX Callback must perform a deep copy of the data // diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 2434c49f6..6daf57cd1 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -2,8 +2,8 @@ #include -#include "can.h" #include "GR_OLD_MSG_ID.h" +#include "can.h" // each family has a constant number of CAN peripherals From d36a3ba39830135a0db9a6ea19dab07fa039ae27 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Tue, 27 Jan 2026 12:15:20 -0800 Subject: [PATCH 05/44] Changed CAN_RX_Callback to take in ID, data, size --- Lib/Peripherals/CAN/Inc/can.h | 4 ++-- Lib/Peripherals/CAN/Src/can.c | 8 ++++++-- Lib/Peripherals/CAN/Test/can_tests.c | 5 ++--- Lib/Peripherals/CAN/common.cmake | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index ce726981c..b0000b555 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -8,13 +8,13 @@ #error "Unsupported STM32 Family" #endif -#include "GR_OLD_MSG_ID.h" #include "can_platform_deps.h" #include "circularBuffer.h" + // RX Callback must perform a deep copy of the data // -typedef void (*CAN_RXCallback)(void *data, uint32_t size, GR_OLD_MSG_ID ID); +typedef void (*CAN_RXCallback)(uint32_t ID, void *data, uint32_t size); typedef struct { // can baud rate is set by fdcan prescaler and RCC clock configurations FDCAN_GlobalTypeDef *fdcan_instance; // Base address of FDCAN peripheral in memory (FDCAN1, FDCAN2, FDCAN3 macros) diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 9663e1a31..0a2545b81 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -389,16 +389,20 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) } // if (GR_CircularBuffer_IsFull(handle->rx_buffer)) return; - FDCAN_RxHeaderTypeDef rx_header; + + //TODO: Stack allocation may be unsafe uint8_t rx_data[64] = {0}; + //TODO: maybe also use a timer for this? while (HAL_FDCAN_GetRxFifoFillLevel(hfdcan, FDCAN_RX_FIFO0) > 0) { HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header, rx_data); // stack allocation should be fine? Callback needs to terminate first before stack is popped // should switch this over to malloc at some point to avoid double copies? - handle->rx_callback(rx_data, rx_header.DataLength, rx_header.Identifier); + //GR_OLD_NODE_ID sendingID = (rx_header.Identifier & (0xFF << 20)) >> 20; + //GR_OLD_MSG_ID messageID = (rx_header.Identifier & (0xFFF << 8)) >> 8; + handle->rx_callback(rx_header.Identifier, rx_data, rx_header.DataLength); } /* whoopsie, don't need the rx buffer yet diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 6daf57cd1..687ff85f5 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -2,7 +2,6 @@ #include -#include "GR_OLD_MSG_ID.h" #include "can.h" // each family has a constant number of CAN peripherals @@ -13,14 +12,14 @@ int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) return 0; } -void can_test_rx_callback2(void *data, uint32_t size, GR_OLD_MSG_ID id) +void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %u\n", size, *(char *)data, id); // Is within an ISR, so needs to exit quickly return; } -void can_test_rx_callback1(void *data, uint32_t size, GR_OLD_MSG_ID id) +void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) { LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %u\n", size, *(char *)data, id); diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 0f086ecf4..76e5b0268 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -4,7 +4,6 @@ target_link_libraries( PERIPHERAL_CAN_LIB INTERFACE CircularBuffer_Lib - GR_OLD_CAN_MESSAGES ) target_sources(PERIPHERAL_CAN_LIB INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Src/can.c) From 9e1af22c4653a50300d15c551d971655b8270876 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 20:17:43 +0000 Subject: [PATCH 06/44] Automatic Clang-Format: Standardized formatting automatically --- Lib/Peripherals/CAN/Inc/can.h | 1 - Lib/Peripherals/CAN/Src/can.c | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index b0000b555..c20cbedae 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -11,7 +11,6 @@ #include "can_platform_deps.h" #include "circularBuffer.h" - // RX Callback must perform a deep copy of the data // typedef void (*CAN_RXCallback)(uint32_t ID, void *data, uint32_t size); diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 0a2545b81..40cb18602 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -391,17 +391,17 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) // if (GR_CircularBuffer_IsFull(handle->rx_buffer)) return; FDCAN_RxHeaderTypeDef rx_header; - //TODO: Stack allocation may be unsafe + // TODO: Stack allocation may be unsafe uint8_t rx_data[64] = {0}; - //TODO: maybe also use a timer for this? + // TODO: maybe also use a timer for this? while (HAL_FDCAN_GetRxFifoFillLevel(hfdcan, FDCAN_RX_FIFO0) > 0) { HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header, rx_data); // stack allocation should be fine? Callback needs to terminate first before stack is popped // should switch this over to malloc at some point to avoid double copies? - //GR_OLD_NODE_ID sendingID = (rx_header.Identifier & (0xFF << 20)) >> 20; - //GR_OLD_MSG_ID messageID = (rx_header.Identifier & (0xFFF << 8)) >> 8; + // GR_OLD_NODE_ID sendingID = (rx_header.Identifier & (0xFF << 20)) >> 20; + // GR_OLD_MSG_ID messageID = (rx_header.Identifier & (0xFFF << 8)) >> 8; handle->rx_callback(rx_header.Identifier, rx_data, rx_header.DataLength); } From 499d15c040daac664b091faf419b98df9066deda Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 20:18:23 +0000 Subject: [PATCH 07/44] Automatic CMake Format: Standardized formatting automatically --- Lib/Peripherals/CAN/common.cmake | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 76e5b0268..120a4dcbe 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -1,10 +1,6 @@ add_library(PERIPHERAL_CAN_LIB INTERFACE) -target_link_libraries( - PERIPHERAL_CAN_LIB - INTERFACE - CircularBuffer_Lib -) +target_link_libraries(PERIPHERAL_CAN_LIB INTERFACE CircularBuffer_Lib) target_sources(PERIPHERAL_CAN_LIB INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Src/can.c) From 4337a58b061c41c06f40e6361fb76cc453bd6861 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Tue, 27 Jan 2026 12:34:59 -0800 Subject: [PATCH 08/44] added formatting for uint32_t id in can_tests.c --- Lib/Peripherals/CAN/Test/can_tests.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 687ff85f5..73b7c3a3c 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -3,6 +3,7 @@ #include #include "can.h" +#include // each family has a constant number of CAN peripherals @@ -14,14 +15,14 @@ int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { - LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %u\n", size, *(char *)data, id); + LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); // Is within an ISR, so needs to exit quickly return; } void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) { - LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %u\n", size, *(char *)data, id); + LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); // Is within an ISR, so needs to exit quickly return; From 2b004730bd063d4ccd2a04f68ad1df625656936b Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 20:36:07 +0000 Subject: [PATCH 09/44] Automatic Clang-Format: Standardized formatting automatically --- Lib/Peripherals/CAN/Test/can_tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 73b7c3a3c..e4f33000e 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -1,9 +1,9 @@ #include "can_tests.h" +#include #include #include "can.h" -#include // each family has a constant number of CAN peripherals From 98923cf16755e3c3c79d06e93739e32c5ea4c46a Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Tue, 27 Jan 2026 13:01:41 -0800 Subject: [PATCH 10/44] cleand up can.c --- Lib/Peripherals/CAN/Inc/can.h | 2 + Lib/Peripherals/CAN/Src/can.c | 1007 +++++++++++++++++---------------- 2 files changed, 528 insertions(+), 481 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index c20cbedae..8519237b2 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -44,7 +44,9 @@ typedef struct { // for release GPIO_TypeDef *rx_gpio; + uint32_t rx_pin; GPIO_TypeDef *tx_gpio; + uint32_t tx_pin; uint32_t Clock_Source; // state diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 40cb18602..50853b740 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -31,391 +31,365 @@ static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3}; #define CAT5(a, b,c,d,e) a##b##c##d##e #define ACTIVATE_FDCAN_HELPER(FDCANX, ITY, preirq, subirq) \ - do { \ - HAL_NVIC_SetPriority( CAT4(FDCANX##,_,ITY, _IRQn ) , preirq, subirq ); \ - HAL_NVIC_EnableIRQ( CAT4(FDCANX##,_,ITY, _IRQn ) ); \ - } while(0) + do { \ + HAL_NVIC_SetPriority( CAT4(FDCANX##,_,ITY, _IRQn ) , preirq, subirq ); \ + HAL_NVIC_EnableIRQ( CAT4(FDCANX##,_,ITY, _IRQn ) ); \ + } while(0) #define HAL_NVIC_ACTIVATE_FDCAN(FDCANX, ITY, preirq, subirq) \ do { \ - if (FDCANX == ##FDCAN1 && ITY == 0) { ACTIVATE_FDCAN_HELPER(FDCAN1, IT0, preirq, subirq); } \ - else if (FDCANX == FDCAN1 && ITY == 1) { ACTIVATE_FDCAN_HELPER(FDCAN1, IT1, preirq, subirq); } \ - else if (FDCANX == FDCAN2 && ITY == 0) { ACTIVATE_FDCAN_HELPER(FDCAN2, IT0, preirq, subirq); } \ - else if (FDCANX == FDCAN2 && ITY == 1) { ACTIVATE_FDCAN_HELPER(FDCAN2, IT1, preirq, subirq); } \ - else if (FDCANX == FDCAN3 && ITY == 0) { ACTIVATE_FDCAN_HELPER(FDCAN3, IT0, preirq, subirq); } \ - else if (FDCANX == FDCAN3 && ITY == 1) { ACTIVATE_FDCAN_HELPER(FDCAN3, IT1, preirq, subirq); } \ - else { LOGOMATIC("Unrecognized FDCAN and Interrupt Line combination"); } \ + if (FDCANX == ##FDCAN1 && ITY == 0) { ACTIVATE_FDCAN_HELPER(FDCAN1, IT0, preirq, subirq); } \ + else if (FDCANX == FDCAN1 && ITY == 1) { ACTIVATE_FDCAN_HELPER(FDCAN1, IT1, preirq, subirq); } \ + else if (FDCANX == FDCAN2 && ITY == 0) { ACTIVATE_FDCAN_HELPER(FDCAN2, IT0, preirq, subirq); } \ + else if (FDCANX == FDCAN2 && ITY == 1) { ACTIVATE_FDCAN_HELPER(FDCAN2, IT1, preirq, subirq); } \ + else if (FDCANX == FDCAN3 && ITY == 0) { ACTIVATE_FDCAN_HELPER(FDCAN3, IT0, preirq, subirq); } \ + else if (FDCANX == FDCAN3 && ITY == 1) { ACTIVATE_FDCAN_HELPER(FDCAN3, IT1, preirq, subirq); } \ + else { LOGOMATIC("Unrecognized FDCAN and Interrupt Line combination"); } \ } while(0) */ #define GPIOx_CLK_ENABLE(GPIOX) \ - do { \ - if (GPIOX == GPIOA) \ - __HAL_RCC_GPIOA_CLK_ENABLE(); \ - else if (GPIOX == GPIOB) \ - __HAL_RCC_GPIOB_CLK_ENABLE(); \ - else if (GPIOX == GPIOD) \ - __HAL_RCC_GPIOD_CLK_ENABLE(); \ - else \ - LOGOMATIC("BAD FDCAN GPIO Port"); \ - } while (0) + do { \ + if (GPIOX == GPIOA) \ + __HAL_RCC_GPIOA_CLK_ENABLE(); \ + else if (GPIOX == GPIOB) \ + __HAL_RCC_GPIOB_CLK_ENABLE(); \ + else if (GPIOX == GPIOD) \ + __HAL_RCC_GPIOD_CLK_ENABLE(); \ + else \ + LOGOMATIC("BAD FDCAN GPIO Port"); \ + } while (0) #define GPIOx_CLK_DISABLE(GPIOX) \ - do { \ - if (GPIOX == GPIOA) \ - __HAL_RCC_GPIOA_CLK_DISABLE(); \ - else if (GPIOX == GPIOB) \ - __HAL_RCC_GPIOB_CLK_DISABLE(); \ - else if (GPIOX == GPIOD) \ - __HAL_RCC_GPIOD_CLK_DISABLE(); \ - else \ - LOGOMATIC("BAD FDCAN GPIO Port"); \ - } while (0) + do { \ + if (GPIOX == GPIOA) \ + __HAL_RCC_GPIOA_CLK_DISABLE(); \ + else if (GPIOX == GPIOB) \ + __HAL_RCC_GPIOB_CLK_DISABLE(); \ + else if (GPIOX == GPIOD) \ + __HAL_RCC_GPIOD_CLK_DISABLE(); \ + else \ + LOGOMATIC("BAD FDCAN GPIO Port"); \ + } while (0) -static int fdcan_shared_clock_ref = 0; -static inline void fdcan_enable_shared_clock(void) -{ - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - - if (fdcan_shared_clock_ref == 0) { - __HAL_RCC_FDCAN_CLK_ENABLE(); - } - fdcan_shared_clock_ref++; - __set_PRIMASK(primask); -} -static inline void fdcan_disable_shared_clock(void) -{ - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - - if (fdcan_shared_clock_ref > 0) { - fdcan_shared_clock_ref--; - if (fdcan_shared_clock_ref == 0) { - __HAL_RCC_FDCAN_CLK_DISABLE(); - } - } - __set_PRIMASK(primask); -} - -static inline void gpio_clk_enable(GPIO_TypeDef *gpio) -{ - if (gpio == GPIOA) { - __HAL_RCC_GPIOA_CLK_ENABLE(); - } else if (gpio == GPIOB) { - __HAL_RCC_GPIOB_CLK_ENABLE(); - } else if (gpio == GPIOD) { - __HAL_RCC_GPIOD_CLK_ENABLE(); - } -} +//TODO: Modify helpers to work across families +//helpers ================= +static int fdcan_shared_clock_ref = 0; +static inline void fdcan_enable_shared_clock(void); +static inline void fdcan_disable_shared_clock(void); +static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan); +static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type *it1); +inline void can_set_clksource(uint32_t clksource) { LL_RCC_SetFDCANClockSource(clksource); } +// static const char *can_get_instance_name(FDCAN_GlobalTypeDef *instance) +//static inline void gpio_clk_enable(GPIO_TypeDef *gpio) +//static inline void gpio_clk_disable(GPIO_TypeDef *gpio) -static inline void gpio_clk_disable(GPIO_TypeDef *gpio) -{ - if (gpio == GPIOA) { - __HAL_RCC_GPIOA_CLK_DISABLE(); - } else if (gpio == GPIOB) { - __HAL_RCC_GPIOB_CLK_DISABLE(); - } else if (gpio == GPIOD) { - __HAL_RCC_GPIOD_CLK_DISABLE(); - } -} +static int can_msp_init(CANHandle *canHandle, CANConfig *config); +static int can_msp_deinit(CANHandle* canHandle); +static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan); -static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type *it1); -static int can_msp_init(CANHandle *handle, CANConfig *config); +//================================================= API ======================================== CANHandle *can_init(const CANConfig *config) { - // config validation? - // assert(config != 0) - - // #ifdef STM32G474xx - CANHandle *canHandle = 0; - // #ifdef USECAN1 - if (config->fdcan_instance == FDCAN1) { - if (CAN1.init) { - LOGOMATIC("CAN: CAN1 is already initialized\n"); - return 0; - } else { - canHandle = &CAN1; - } - } - // #endif - // #ifdef USECAN2 - else if (config->fdcan_instance == FDCAN2) { - if (CAN2.init) { - LOGOMATIC("CAN: CAN2 is already initialized\n"); - return 0; - } else { - canHandle = &CAN2; - } - } - // #ifdef USECAN3 - else if (config->fdcan_instance == FDCAN3) { - if (CAN3.init) { - LOGOMATIC("CAN: CAN3 is already initialized\n"); - return 0; - } else { - canHandle = &CAN3; - } - } - // #endif - // #elif defined(STM32L476xx) - // #else - // #error "Unsupported STM32 family" - // #endif - else { - LOGOMATIC("CAN: Unrecognized FDCAN instance"); - return 0; - } - canHandle->init = false; - canHandle->started = false; - - // Initialize handle - assert(config->hal_fdcan_init.TxFifoQueueMode == FDCAN_TX_FIFO_OPERATION); - - canHandle->hal_fdcanP->Init = config->hal_fdcan_init; // copy FDCAN parameters from user - // canHandle->hal_fdcanP->Instance = config->fdcan_instance //handles initialized with correct base instance addresses - - canHandle->rx_gpio = config->rx_gpio; - canHandle->tx_gpio = config->tx_gpio; - canHandle->rx_callback = config->rx_callback; - canHandle->tx_buffer_length = config->tx_buffer_length; - - // alternately -> have can_msp_init setup state for HAL_FDCAN_MspInit to work correctly - // have can_msp_deinit setup state for HAL_FDCAN_MspDeInit to work correctly - // Then call HAL_FDCAN_Init() and HAL_FDCAN_DeInit() - - // Current idea, redefine HAL_FDCAN_MspInit and MspDeInit do nothing at all, do all the work in can_msp_init() - if (can_msp_init(canHandle, (CANConfig *)config)) { - LOGOMATIC("CAN_init: could not initialize MSP resources"); - can_release(canHandle); - } - - // PROBLEM: HAL_FDCAN_Init expects HAL_FDCAN_MspInit() to be defined - if (HAL_FDCAN_Init(canHandle->hal_fdcanP) != HAL_OK) { - LOGOMATIC("CAN: HAL Could not initialize FDCAN peripheral"); - return NULL; - // Error_Handler(); - } - - // Active FDCAN callbacks - rxcalback uses line0, txcallback uses line1 - // uint32_t rxevents = FDCAN_IT_RX_FIFO0_NEW_MESSAGE; - uint32_t status = 0; - uint32_t rx_events = FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO0_FULL; - status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, rx_events, 0); - status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, rx_events, FDCAN_INTERRUPT_LINE0); - - // uint32_t txevents = FDCAN_IT_TX_COMPLETE; - uint32_t destinations = FDCAN_TX_BUFFER0; - uint32_t tx_events = FDCAN_IT_TX_COMPLETE | FDCAN_IT_TX_FIFO_EMPTY; - status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, tx_events, destinations); - status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, tx_events, FDCAN_INTERRUPT_LINE1); - // Callbacks redefined later - - if (status & HAL_ERROR) { - LOGOMATIC("CAN: Could not activate rx and tx interrupts\n"); - return NULL; - } - - // Circular Buffer - canHandle->tx_buffer = GR_CircularBuffer_Create(config->tx_buffer_length); - if (!canHandle->tx_buffer) { - LOGOMATIC("CAN: Could not allocate circular buffer\n"); - return 0; - } - - canHandle->init = true; - canHandle->started = false; - - return canHandle; + // config validation? + // assert(config != 0) + + // #ifdef STM32G474xx + CANHandle *canHandle = 0; + // #ifdef USECAN1 + if (config->fdcan_instance == FDCAN1) { + if (CAN1.init) { + LOGOMATIC("CAN: CAN1 is already initialized\n"); + return 0; + } else { + canHandle = &CAN1; + } + } + // #endif + // #ifdef USECAN2 + else if (config->fdcan_instance == FDCAN2) { + if (CAN2.init) { + LOGOMATIC("CAN: CAN2 is already initialized\n"); + return 0; + } else { + canHandle = &CAN2; + } + } + // #ifdef USECAN3 + else if (config->fdcan_instance == FDCAN3) { + if (CAN3.init) { + LOGOMATIC("CAN: CAN3 is already initialized\n"); + return 0; + } else { + canHandle = &CAN3; + } + } + // #endif + // #elif defined(STM32L476xx) + // #else + // #error "Unsupported STM32 family" + // #endif + else { + LOGOMATIC("CAN: Unrecognized FDCAN instance"); + return 0; + } + canHandle->init = false; + canHandle->started = false; + + // Initialize handle + assert(config->hal_fdcan_init.TxFifoQueueMode == FDCAN_TX_FIFO_OPERATION); + + canHandle->hal_fdcanP->Init = config->hal_fdcan_init; // copy FDCAN parameters from user + // canHandle->hal_fdcanP->Instance = config->fdcan_instance //handles initialized with correct base instance addresses + + canHandle->rx_gpio = config->rx_gpio; + canHandle->tx_gpio = config->tx_gpio; + canHandle->rx_pin = config->init_rx_gpio.Pin; + canHandle->tx_pin = config->init_tx_gpio.Pin; + + canHandle->rx_callback = config->rx_callback; + canHandle->tx_buffer_length = config->tx_buffer_length; + + // alternately -> have can_msp_init setup state for HAL_FDCAN_MspInit to work correctly + // have can_msp_deinit setup state for HAL_FDCAN_MspDeInit to work correctly + // Then call HAL_FDCAN_Init() and HAL_FDCAN_DeInit() + + // Current idea, redefine HAL_FDCAN_MspInit and MspDeInit do nothing at all, do all the work in can_msp_init() + if (can_msp_init(canHandle, (CANConfig *)config)) { + LOGOMATIC("CAN_init: could not initialize MSP resources"); + can_release(canHandle); + } + + // PROBLEM: HAL_FDCAN_Init expects HAL_FDCAN_MspInit() to be defined + if (HAL_FDCAN_Init(canHandle->hal_fdcanP) != HAL_OK) { + LOGOMATIC("CAN: HAL Could not initialize FDCAN peripheral"); + return NULL; + // Error_Handler(); + } + + // Active FDCAN callbacks - rxcalback uses line0, txcallback uses line1 + // uint32_t rxevents = FDCAN_IT_RX_FIFO0_NEW_MESSAGE; + uint32_t status = 0; + uint32_t rx_events = FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO0_FULL; + status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, rx_events, 0); + status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, rx_events, FDCAN_INTERRUPT_LINE0); + + // uint32_t txevents = FDCAN_IT_TX_COMPLETE; + uint32_t destinations = FDCAN_TX_BUFFER0; + uint32_t tx_events = FDCAN_IT_TX_COMPLETE | FDCAN_IT_TX_FIFO_EMPTY; + status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, tx_events, destinations); + status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, tx_events, FDCAN_INTERRUPT_LINE1); + // Callbacks redefined later + + if (status & HAL_ERROR) { + LOGOMATIC("CAN: Could not activate rx and tx interrupts\n"); + return NULL; + } + + // Circular Buffer + canHandle->tx_buffer = GR_CircularBuffer_Create(config->tx_buffer_length); + if (!canHandle->tx_buffer) { + LOGOMATIC("CAN: Could not allocate circular buffer\n"); + return 0; + } + + canHandle->init = true; + canHandle->started = false; + + return canHandle; } -inline void can_set_clksource(uint32_t clksource) { LL_RCC_SetFDCANClockSource(clksource); } -// only valid for #STM32G474x, must redefine for each family -static int can_msp_init(CANHandle *canHandle, CANConfig *config) +int can_release(CANHandle *canHandle) { - // MSP Init ------- This could be inside HAL_FDCAN_MspInit() instead - // FDCAN Clock Select + if (!canHandle) { + LOGOMATIC("CAN: Tried to release a null handle"); + return -1; + } - fdcan_enable_shared_clock(); - // Clock speed for FDCAN determined by APB1 clock speed and FDCAN prescaler + if (!canHandle->init) { + LOGOMATIC("CAN_release: can instance is already deinitialized"); + return -1; + } + can_stop(canHandle); // try to prevent more interrupts from firing - // GPIOs init - GPIOx_CLK_ENABLE(config->rx_gpio); - GPIOx_CLK_ENABLE(config->tx_gpio); + can_msp_deinit(canHandle); - HAL_GPIO_Init(config->rx_gpio, &(config->init_rx_gpio)); - HAL_GPIO_Init(config->tx_gpio, &(config->init_tx_gpio)); + // reset FDCANx instance and message RAM and filters, clear interrupts + // HAL_FDCAN_DeInit(canHandle->hal_fdcanP); resets a little too hard + FDCAN_InstanceDeInit(canHandle->hal_fdcanP); - IRQn_Type rxit = -1; - IRQn_Type txit = -1; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rxit, &txit); + __DSB(); // Data Synchronization Barrier + __ISB(); // Instruction Synchronization Barrier - // rxfifo0 - HAL_NVIC_SetPriority(rxit, config->rx_interrupt_priority, 0); - HAL_NVIC_EnableIRQ(rxit); + // free circular buffer contents + GR_CircularBuffer_Free(&(canHandle->tx_buffer)); - // tx - HAL_NVIC_SetPriority(txit, config->tx_interrupt_priority, 0); - HAL_NVIC_EnableIRQ(txit); - // End MSP Init -------------- + // reset can handle + FDCAN_HandleTypeDef *temp = canHandle->hal_fdcanP; + memset(canHandle, 0, sizeof(*canHandle)); + canHandle->hal_fdcanP = temp; - return 0; + return 0; } - -// valid only for STM32G4 -static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type *it1) +//TODO: ISR DANGER +//TODO: Implement timer +//lock access to Circular Buffer when sending and dequeuing +static void can_tx_dequeue_helper(CANHandle *handle) { - if (instance == FDCAN1) { - *it0 = FDCAN1_IT0_IRQn; - *it1 = FDCAN1_IT1_IRQn; - return 0; - } - if (instance == FDCAN2) { - *it0 = FDCAN2_IT0_IRQn; - *it1 = FDCAN2_IT1_IRQn; - return 0; - } - if (instance == FDCAN3) { - *it0 = FDCAN3_IT0_IRQn; - *it1 = FDCAN3_IT1_IRQn; - return 0; - } - - return -1; // invalid instance -} + if (!handle || !handle->tx_buffer) { + LOGOMATIC("can_tx_buffer_helper: handle is invalid"); + return; + } -// valid only for STM32G4 -// static const char *can_get_instance_name(FDCAN_GlobalTypeDef *instance) -// { -// if (instance == FDCAN1) { -// return "FDCAN1"; -// } else if (instance == FDCAN2) { -// return "FDCAN2"; -// } else if (instance == FDCAN3) { -// return "FDCAN3"; -// } -// return "UNKNOWN"; -// } + if (GR_CircularBuffer_IsEmpty(handle->tx_buffer)) { + return; + } -// valid only for STM32G4 -static CANHandle *can_get_buffer_handle(FDCAN_HandleTypeDef *hfdcan) -{ - // #ifdef STM32G474xx - if (hfdcan->Instance == FDCAN1) { - return &CAN1; - } else if (hfdcan->Instance == FDCAN2) { - return &CAN2; - } else if (hfdcan->Instance == FDCAN3) { - return &CAN3; - } else { - LOGOMATIC("CAN_get_buffer_handle: was given invalid FDCAN instance\n"); - return 0; - } -} + uint32_t primask = __get_PRIMASK(); + __disable_irq(); + if (!GR_CircularBuffer_IsEmpty(handle->tx_buffer)) { -static void can_tx_buffer_helper(CANHandle *handle) -{ - while (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP) && !GR_CircularBuffer_IsEmpty(handle->tx_buffer)) { - FDCANTxMessage *msg = GR_CircularBuffer_Pop(handle->tx_buffer); + //Can Add to Fifo Q + if (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP)) { - if (!msg) { - break; - } + //lock the Circular Buffer + FDCANTxMessage *msg = GR_CircularBuffer_Pop(handle->tx_buffer); + if (!msg) { + return ; + } - HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(handle->hal_fdcanP, &msg->tx_header, msg->data); + //should call Tx Buffer Callback once complete + HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(handle->hal_fdcanP, &msg->tx_header, msg->data); - if (status != HAL_OK) { - LOGOMATIC("CAN_tx_helper: failed to add message to FIFO\n"); - free(msg); // Free the message we couldn't send - break; // Stop trying to send more - } + if (status != HAL_OK) { + LOGOMATIC("CAN_tx_helper: failed to add message to FIFO\n"); + //free(msg); // Free the message we couldn't send + return; // Stop trying to send more + } + free(msg); // Successfully sent, free the memory - free(msg); // Successfully sent, free the memory - } -} + } else { //try again later with a timer /? -void FDCAN1_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); } -void FDCAN1_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); } + } + } -void FDCAN2_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); } -void FDCAN2_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); } + __set_PRIMASK(primask); +} + +//Use to directly send +int can_send(CANHandle *canHandle, FDCANTxMessage *message) +{ + if (!canHandle || !message) { + LOGOMATIC("CAN_send: received null pointer\n"); + return -1; + } + + if (!canHandle->init || !canHandle->started) { + LOGOMATIC("CAN_send: CAN not initialized or started\n"); + return -1; + } + + uint32_t primask = __get_PRIMASK(); + __disable_irq(); + // IF TX Fifos are not full, send directly to them + // If TX Fifos are full, append to circular buffer + // If circular buffer is full, return an error code + uint32_t free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP); + + if (free > 0) { + HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), + message->data // Not &message->data if data is array + ); + + __set_PRIMASK(primask); + + if (status != HAL_OK) { + LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); + return -1; + } + return 0; + } + + // Hardware FIFO full, try software buffer + if (!GR_CircularBuffer_IsFull(canHandle->tx_buffer)) { + int result = GR_CircularBuffer_Push(canHandle->tx_buffer, message, sizeof(FDCANTxMessage)); + + __set_PRIMASK(primask); + + if (result != 0) { + LOGOMATIC("CAN_send: buffer push failed\n"); + return -1; + } + return 0; + } + + // Both buffers full + __set_PRIMASK(primask); + LOGOMATIC("CAN_send: all buffers full\n"); + return -1; +} -void FDCAN3_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); } -void FDCAN3_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); } void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes) { - UNUSED(BufferIndexes); - // If circular buffer has elements, send to queue - // Otherwise do nothing - // #ifdef USECAN1 - CANHandle *handle = can_get_buffer_handle(hfdcan); - - if (!handle || !handle->tx_buffer) { - return; - } - - if (GR_CircularBuffer_IsEmpty(handle->tx_buffer)) { - return; - } - - // see if you can pop any more from the buffer - can_tx_buffer_helper(handle); + UNUSED(BufferIndexes); + // If circular buffer has elements, send to queue + // Otherwise do nothing + // #ifdef USECAN1 + CANHandle *handle = can_get_handle(hfdcan); + // see if you can pop any more from the buffer + can_tx_dequeue_helper(handle); } void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) { - CANHandle *handle = can_get_buffer_handle(hfdcan); - - if (!handle || !handle->init || !handle->rx_callback) { - return; - } - - /*if (!handle->rx_buffer) { - LOGOMATIC("CAN: RX Complete, but %s Buffer was released\n", can_get_instance_name(hfdcan->Instance)); - return; - } */ // no rx buffer at the moment - - /*if (RxFifo0ITs & FDCAN_IT_RX_FIFO0_MESSAGE_LOST) { - lost_rx++; - }*/ - - if (!(RxFifo0ITs & ~FDCAN_IT_RX_FIFO0_MESSAGE_LOST)) { - return; - } - - // if (GR_CircularBuffer_IsFull(handle->rx_buffer)) return; - FDCAN_RxHeaderTypeDef rx_header; - - // TODO: Stack allocation may be unsafe - uint8_t rx_data[64] = {0}; - - // TODO: maybe also use a timer for this? - while (HAL_FDCAN_GetRxFifoFillLevel(hfdcan, FDCAN_RX_FIFO0) > 0) { - HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header, rx_data); - - // stack allocation should be fine? Callback needs to terminate first before stack is popped - // should switch this over to malloc at some point to avoid double copies? - // GR_OLD_NODE_ID sendingID = (rx_header.Identifier & (0xFF << 20)) >> 20; - // GR_OLD_MSG_ID messageID = (rx_header.Identifier & (0xFFF << 8)) >> 8; - handle->rx_callback(rx_header.Identifier, rx_data, rx_header.DataLength); - } - - /* whoopsie, don't need the rx buffer yet - while (HAL_FDCAN_GetRxFifoFillLevel(hfdcan, FDCAN_RX_FIFO0) & !GR_CircularBuffer_IsFull(handle->rx_buffer)) { - FDCAN_RxHeaderTypeDef rx_header; - uint8_t rx_data[64] = {0}; - HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header, &rx_data); - - if (GR_CircularBuffer_IsEmpty(handle->rx_buffer)) handle->rx_callback(rx_data, rx_header.DataLength); - else { - GR_CircularBuffer_Push(handle->rx_buffer, rx_data, rx_header.DataLength); - } - }*/ + CANHandle *handle = can_get_handle(hfdcan); + + if (!handle || !handle->init || !handle->rx_callback) { + return; + } + + /*if (!handle->rx_buffer) { + LOGOMATIC("CAN: RX Complete, but %s Buffer was released\n", can_get_instance_name(hfdcan->Instance)); + return; + } */ // no rx buffer at the moment + + /*if (RxFifo0ITs & FDCAN_IT_RX_FIFO0_MESSAGE_LOST) { + lost_rx++; + }*/ + + if (!(RxFifo0ITs & ~FDCAN_IT_RX_FIFO0_MESSAGE_LOST)) { + return; + } + + // if (GR_CircularBuffer_IsFull(handle->rx_buffer)) return; + FDCAN_RxHeaderTypeDef rx_header; + uint8_t rx_data[64] = {0}; + + //if goign to declare on stack, might as well + while (HAL_FDCAN_GetRxFifoFillLevel(hfdcan, FDCAN_RX_FIFO0) > 0) { + HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header, rx_data); + + // stack allocation should be fine? Callback needs to terminate first before stack is popped + // should switch this over to malloc at some point to avoid double copies? + handle->rx_callback(rx_header.Identifier, rx_data, rx_header.DataLength); + } + + /* whoopsie, don't need the rx buffer yet + while (HAL_FDCAN_GetRxFifoFillLevel(hfdcan, FDCAN_RX_FIFO0) & !GR_CircularBuffer_IsFull(handle->rx_buffer)) { + FDCAN_RxHeaderTypeDef rx_header; + uint8_t rx_data[64] = {0}; + HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header, &rx_data); + + if (GR_CircularBuffer_IsEmpty(handle->rx_buffer)) handle->rx_callback(rx_data, rx_header.DataLength); + else { + GR_CircularBuffer_Push(handle->rx_buffer, rx_data, rx_header.DataLength); + } + }*/ } /* @@ -433,189 +407,260 @@ void can_read_rx_buffer(CANHandle* canHandle) { // Just alternatively just use the HAL_FDCAN_ConfigFilter directly with the canHandle->hal_fdcan int can_add_filter(CANHandle *canHandle, FDCAN_FilterTypeDef *filter) { - if (!canHandle) { - LOGOMATIC("CAN_add_filter: handle is null"); - return -1; - } - - if (!canHandle->init || canHandle->started) { - LOGOMATIC("CAN_add_filter: can instance is not initialized or already started"); - return -1; - } - - if (HAL_FDCAN_ConfigFilter(canHandle->hal_fdcanP, filter) != HAL_OK) { - LOGOMATIC("CAN_add_filter: failed to configure filter"); - return -1; - } - return 0; - // check that # of filters isn't exceeding max value + if (!canHandle) { + LOGOMATIC("CAN_add_filter: handle is null"); + return -1; + } + + if (!canHandle->init || canHandle->started) { + LOGOMATIC("CAN_add_filter: can instance is not initialized or already started"); + return -1; + } + + if (HAL_FDCAN_ConfigFilter(canHandle->hal_fdcanP, filter) != HAL_OK) { + LOGOMATIC("CAN_add_filter: failed to configure filter"); + return -1; + } + return 0; + // check that # of filters isn't exceeding max value } -// Need to int can_start(CANHandle *canHandle) { - if (!canHandle || !canHandle->init) { - return -1; - } + if (!canHandle || !canHandle->init) { + return -1; + } - GPIOx_CLK_ENABLE(canHandle->rx_gpio); - GPIOx_CLK_ENABLE(canHandle->tx_gpio); + GPIOx_CLK_ENABLE(canHandle->rx_gpio); + GPIOx_CLK_ENABLE(canHandle->tx_gpio); - HAL_FDCAN_Start(canHandle->hal_fdcanP); - canHandle->started = true; + HAL_FDCAN_Start(canHandle->hal_fdcanP); + canHandle->started = true; - return 0; + return 0; } int can_stop(CANHandle *canHandle) { - if (!canHandle || !canHandle->init) { - return -1; - } - if (!canHandle->started) { - return 0; - } + if (!canHandle || !canHandle->init) { + return -1; + } + if (!canHandle->started) { + return 0; + } - HAL_FDCAN_Stop(canHandle->hal_fdcanP); + HAL_FDCAN_Stop(canHandle->hal_fdcanP); - GPIOx_CLK_DISABLE(canHandle->rx_gpio); - GPIOx_CLK_DISABLE(canHandle->tx_gpio); + GPIOx_CLK_DISABLE(canHandle->rx_gpio); + GPIOx_CLK_DISABLE(canHandle->tx_gpio); - canHandle->started = false; + canHandle->started = false; - return 0; + return 0; } -// Valid only for STM32G474xE -/*int can_msp_deinit(CANHandle* canHandle) { - //MSP DeInit - //turn off gpio clocks - can only turn off GPIOs if no other instances are using them - return 0; -}*/ + // ==================================== HELPER FUNCTIONS =============================================== +//TODO: Abstract across families +static inline void fdcan_enable_shared_clock(void) +{ + uint32_t primask = __get_PRIMASK(); + __disable_irq(); -static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) + if (fdcan_shared_clock_ref == 0) { + __HAL_RCC_FDCAN_CLK_ENABLE(); + } + fdcan_shared_clock_ref++; + + __set_PRIMASK(primask); +} + +static inline void fdcan_disable_shared_clock(void) { - // Enter INIT mode - hfdcan->Instance->CCCR |= FDCAN_CCCR_INIT; - while (!(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT)) - ; + uint32_t primask = __get_PRIMASK(); + __disable_irq(); + + if (fdcan_shared_clock_ref > 0) { + fdcan_shared_clock_ref--; + if (fdcan_shared_clock_ref == 0) { + __HAL_RCC_FDCAN_CLK_DISABLE(); + } + } + __set_PRIMASK(primask); +} - // Clear filters - // TODO: fix magic numbers - memset((void *)hfdcan->msgRam.StandardFilterSA, 0, 0x0070); - memset((void *)hfdcan->msgRam.ExtendedFilterSA, 0, 0x0050); +// valid only for STM32G4 +static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type *it1) +{ + if (instance == FDCAN1) { + *it0 = FDCAN1_IT0_IRQn; + *it1 = FDCAN1_IT1_IRQn; + return 0; + } + if (instance == FDCAN2) { + *it0 = FDCAN2_IT0_IRQn; + *it1 = FDCAN2_IT1_IRQn; + return 0; + } + if (instance == FDCAN3) { + *it0 = FDCAN3_IT0_IRQn; + *it1 = FDCAN3_IT1_IRQn; + return 0; + } + + return -1; // invalid instance +} - // Optionally reset FIFOs / buffers - // Disable interrupts - __HAL_FDCAN_DISABLE_IT(hfdcan, FDCAN_IT_LIST_RX_FIFO0 | FDCAN_IT_LIST_RX_FIFO1 | FDCAN_IT_LIST_SMSG | FDCAN_IT_LIST_TX_FIFO_ERROR | FDCAN_IT_LIST_MISC | FDCAN_IT_LIST_BIT_LINE_ERROR | - FDCAN_IT_LIST_PROTOCOL_ERROR); +// valid only for STM32G4 +static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan) +{ + // #ifdef STM32G474xx + if (hfdcan->Instance == FDCAN1) { + return &CAN1; + } else if (hfdcan->Instance == FDCAN2) { + return &CAN2; + } else if (hfdcan->Instance == FDCAN3) { + return &CAN3; + } else { + LOGOMATIC("CAN_get_handle: was given invalid FDCAN instance\n"); + return 0; + } +} - // Exit INIT mode - hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT; - while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) - ; - // Update handle state - hfdcan->State = HAL_FDCAN_STATE_RESET; +/* +static inline void gpio_clk_enable(GPIO_TypeDef *gpio) +{ + if (gpio == GPIOA) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + } else if (gpio == GPIOB) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + } else if (gpio == GPIOD) { + __HAL_RCC_GPIOD_CLK_ENABLE(); + } } -int can_release(CANHandle *canHandle) +static inline void gpio_clk_disable(GPIO_TypeDef *gpio) { - if (!canHandle) { - LOGOMATIC("CAN: Tried to release a null handle"); - return -1; - } + if (gpio == GPIOA) { + __HAL_RCC_GPIOA_CLK_DISABLE(); + } else if (gpio == GPIOB) { + __HAL_RCC_GPIOB_CLK_DISABLE(); + } else if (gpio == GPIOD) { + __HAL_RCC_GPIOD_CLK_DISABLE(); + } +}*/ + +// only valid for #STM32G474x, must redefine for each family +static int can_msp_init(CANHandle *canHandle, CANConfig *config) +{ + // MSP Init ------- This could be inside HAL_FDCAN_MspInit() instead + // FDCAN Clock Select + + fdcan_enable_shared_clock(); + //__HAL_RCC_FDCAN_CLK_ENABLE(); - if (!canHandle->init) { - LOGOMATIC("CAN_release: can instance is already deinitialized"); - return -1; - } - can_stop(canHandle); // try to prevent more interrupts from firing + // Clock speed for FDCAN determined by APB1 clock speed and FDCAN prescaler - // must disable NVIC IRQs before freeing circular buffer + // GPIOs init + GPIOx_CLK_ENABLE(config->rx_gpio); + GPIOx_CLK_ENABLE(config->tx_gpio); - // turn off NVIC resources - IRQn_Type rx0it = -1; - IRQn_Type txit = -1; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); - HAL_NVIC_DisableIRQ(rx0it); - HAL_NVIC_DisableIRQ(txit); + HAL_GPIO_Init(config->rx_gpio, &(config->init_rx_gpio)); + HAL_GPIO_Init(config->tx_gpio, &(config->init_tx_gpio)); - // need to check if other pins are using before disabling - do this after mvp - // GPIOx_CLK_DISABLE(canHandle->rx_gpio); - // GPIOx_CLK_DISABLE(canHandle->tx_gpio); + IRQn_Type rxit = -1; + IRQn_Type txit = -1; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rxit, &txit); - // reset FDCANx instance and message RAM and filters, clear interrupts - // HAL_FDCAN_DeInit(canHandle->hal_fdcanP); resets a little too hard - FDCAN_InstanceDeInit(canHandle->hal_fdcanP); + // rxfifo0 + HAL_NVIC_SetPriority(rxit, config->rx_interrupt_priority, 0); + HAL_NVIC_EnableIRQ(rxit); - __DSB(); // Data Synchronization Barrier - __ISB(); // Instruction Synchronization Barrier + // tx + HAL_NVIC_SetPriority(txit, config->tx_interrupt_priority, 0); + HAL_NVIC_EnableIRQ(txit); + // End MSP Init -------------- - // free circular buffer contents - GR_CircularBuffer_Free(&(canHandle->tx_buffer)); + return 0; +} + +// Valid only for STM32G474xE +static int can_msp_deinit(CANHandle* canHandle) { + //MSP DeInit + // must disable NVIC IRQs before freeing circular buffer + + //NVIC + IRQn_Type rx0it = -1; + IRQn_Type txit = -1; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); + HAL_NVIC_DisableIRQ(rx0it); + HAL_NVIC_DisableIRQ(txit); + + //TODO: turn off gpio clocks if no other peripherals are using them??? Could implement a shared GPIO layer + HAL_GPIO_DeInit(canHandle->rx_gpio, canHandle->rx_pin); + HAL_GPIO_DeInit(canHandle->tx_gpio, canHandle->tx_pin); - // reset can instance - FDCAN_HandleTypeDef *temp = canHandle->hal_fdcanP; - memset(canHandle, 0, sizeof(*canHandle)); - canHandle->hal_fdcanP = temp; + //MSP shared layer for GPIOs - fdcan_disable_shared_clock(); // only turns off clock if no other instances are running. + //RCC + fdcan_disable_shared_clock(); - return 0; + return 0; } -int can_send(CANHandle *canHandle, FDCANTxMessage *message) +static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) { - if (!canHandle || !message) { - LOGOMATIC("CAN_send: received null pointer\n"); - return -1; - } - - if (!canHandle->init || !canHandle->started) { - LOGOMATIC("CAN_send: CAN not initialized or started\n"); - return -1; - } - - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - // IF TX Fifos are not full, send directly to them - // If TX Fifos are full, append to circular buffer - // If circular buffer is full, return an error code - uint32_t free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP); - - if (free > 0) { - HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), - message->data // Not &message->data if data is array - ); - - __set_PRIMASK(primask); - - if (status != HAL_OK) { - LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); - return -1; - } - return 0; - } - - // Hardware FIFO full, try software buffer - if (!GR_CircularBuffer_IsFull(canHandle->tx_buffer)) { - int result = GR_CircularBuffer_Push(canHandle->tx_buffer, message, sizeof(FDCANTxMessage)); - - __set_PRIMASK(primask); - - if (result != 0) { - LOGOMATIC("CAN_send: buffer push failed\n"); - return -1; - } - return 0; - } - - // Both buffers full - __set_PRIMASK(primask); - LOGOMATIC("CAN_send: all buffers full\n"); - return -1; + // Enter INIT mode + hfdcan->Instance->CCCR |= FDCAN_CCCR_INIT; + while (!(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT)) + ; + + // Disable interrupts + __HAL_FDCAN_DISABLE_IT(hfdcan, FDCAN_IT_LIST_RX_FIFO0 | FDCAN_IT_LIST_RX_FIFO1 | FDCAN_IT_LIST_SMSG | FDCAN_IT_LIST_TX_FIFO_ERROR | FDCAN_IT_LIST_MISC | FDCAN_IT_LIST_BIT_LINE_ERROR | + FDCAN_IT_LIST_PROTOCOL_ERROR); + + // Clear filters + // TODO: fix magic numbers + memset((void *)hfdcan->msgRam.StandardFilterSA, 0, 0x0070); + memset((void *)hfdcan->msgRam.ExtendedFilterSA, 0, 0x0050); + + // Optionally clear FIFOs / buffers + + // Exit INIT mode + hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT; + while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT); + + // Update handle state + hfdcan->State = HAL_FDCAN_STATE_RESET; } + + +// valid only for STM32G4 +/*static const char *can_get_instance_name(FDCAN_GlobalTypeDef *instance) +{ + if (instance == FDCAN1) { + return "FDCAN1"; + } else if (instance == FDCAN2) { + return "FDCAN2"; + } else if (instance == FDCAN3) { + return "FDCAN3"; + } + return "UNKNOWN"; +}*/ + + +// ===================================== HAL Callbacks ================================ + +//TODO: Implement Family Checks +//Probably is safe from races +void FDCAN1_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); HAL_NVIC_ClearPendingIRQ(FDCAN1_IT0_IRQn);} +void FDCAN1_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); HAL_NVIC_ClearPendingIRQ(FDCAN1_IT1_IRQn);} + +void FDCAN2_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); HAL_NVIC_ClearPendingIRQ(FDCAN2_IT0_IRQn);} +void FDCAN2_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); HAL_NVIC_ClearPendingIRQ(FDCAN2_IT1_IRQn);} + +void FDCAN3_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); HAL_NVIC_ClearPendingIRQ(FDCAN3_IT0_IRQn);} +void FDCAN3_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); HAL_NVIC_ClearPendingIRQ(FDCAN3_IT1_IRQn);} From 82e770988e4cdff1d8af2730164ebbfab7338f42 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Thu, 29 Jan 2026 00:47:57 -0800 Subject: [PATCH 11/44] added basepri masking, also tried to prevent spurious NVIC interrupts in can_start and can_stop --- Lib/Peripherals/CAN/Inc/can.h | 3 + Lib/Peripherals/CAN/README.md | 51 +++++---------- Lib/Peripherals/CAN/Src/can.c | 120 ++++++++++++++++++++-------------- 3 files changed, 93 insertions(+), 81 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index 8519237b2..1ce0f19bc 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -42,6 +42,9 @@ typedef struct { CAN_RXCallback rx_callback; + uint32_t rx_interrupt_priority; + uint32_t tx_interrupt_priority; + // for release GPIO_TypeDef *rx_gpio; uint32_t rx_pin; diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index 012ab1a1a..7f05e8130 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -6,54 +6,42 @@ void can_set_clksource(uint32_t LL_RCC_FDCAN_CLKSOURCE); //ex LL_RCC_FDCAN_CLKSO int can_start(CANHandle*handle); int can_stop(CANHandle*handle); -int can_send(CANHandle*handle, FDCANMessage* buffer, size_t send); +int can_send(CANHandle*handle, FDCANMessage* buffer, size_t send); int can_release(CANHandle* handle); //deinit circular buffer and turn off can peripheral and gpios int can_add_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef * filter); -int can_add_global_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef* filter); +int can_add_global_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef* filter); //alternatively instead use the HAL filter functions -//HAL_FDCAN_ConfigGlobalFilter(canHandle->hal_fdcanP, filterTypeDef) +//HAL_FDCAN_ConfigGlobalFilter(canHandle->hal_fdcanP, filterTypeDef) //HAL_FDCAN_ConfigFilter(ca) If no filters are set, the default behaviour is to accept all standard and extended frames into the RXFIFO0 +CHANGES: +- with a single producer, single consumer tx buffer, can instead use a fixed-size ring buffer instead of the circular buffer +- avoids free issues inside the ISR +- can also use the ISR to drain the tx buffer, can_send only adds to it - - - -PROBLEMS: -Verify ISR safety, no race conditions, atomic read/writes - - Interrupts keep firing while trying to can_release() - - Could try to set the NVIC register to selectively disable interrupts (preferably using a bitmask) -- Need to discuss expected behaviour of API - - particularly can_start, can_stop - - can_release +PROBLEMS: - Freeing within ISRs whenever popping from CircularBuffer (yes its faster, than stack copies, but heap is getting fragmented) -- ISRS might take too long to resolve because popping and freeing circular buffer. +- ISRS might take too long to resolve because popping and freeing circular buffer. - HARDCODE Platform Usage Flag for compiler definitions -- CAN.H expects #STM32G4 to be defined, - - +- CAN.H expects #STM32G4 to be defined, - RX Callback must perform deep copy of data supplied to it - could also malloc, but not safe to do inside ISRs -- - - --Shouldn't disable GPIOs in the MSP layers when releasing, might affect other peripherals - IDEAS for other features: +- - DMA support for copying from circular buffer +- Circular buffer should be fixed size anyways - abstract to different STM families besides STM32G4 - Rx Buffering - TX Buffering policy, do we spread them out over multiple TX buffers -- DMA support for copying from circular buffer, circular buffer could then be stack allocated -- Smaller can headers for tx and rx (right now its just use the TXHeaderTypeDef) +- Smaller can headers for tx and rx (right now its just use the HAL TXHeaderTypeDef) - TX FIFO vs Queue policy (only allow FIFOS) - Add support for RXFifo1 - TESTING- ---------------------------------------------- -USE LOGOMATIC for return status - +USE LOGOMATIC for return status - either returns through semihosting or debug cores LOGOMATIC is defined platform by platform @@ -63,21 +51,18 @@ Testing framework - All tests are run from the top level function in can_test.c - can_test.c should initialize everything properly. -- May have to create platform specific asserts when testing state - use LOGOMATIC to return errors or throw asserts - Platform testing, such as in G4PERTESTING just needs include "can_test.h" and call top level function -in main. +in main. Two approaches: Platform centric - In G4PERTesting, include "can_tests.h" and call the top level function in can_test.c - This approach is better because we can abstract the logging and debug method -Library Centric Testing: -- Test the implementation in each library. - HAL_Rewrite: -- Alternatively, rewrite without using HAL, just use CMSIS definitions. -- PROS: Would look good on your Github. +- Alternatively, rewrite without using HAL, just use CMSIS definitions. +- There isn't actually that much going on underneath HAL, it just looks painful because of CMSIS +- PROS: Would look good on your Github. - CONS: takes too long diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 50853b740..f5382c86b 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -10,19 +10,21 @@ // HAL handles // #ifdef USECAN1 static FDCAN_HandleTypeDef hal_fdcan1 = {.Instance = FDCAN1}; -static CANHandle CAN1 = {.hal_fdcanP = &hal_fdcan1}; +volatile static CANHandle CAN1 = {.hal_fdcanP = &hal_fdcan1}; // #endif // #ifdef USECAN2 static FDCAN_HandleTypeDef hal_fdcan2 = {.Instance = FDCAN2}; -static CANHandle CAN2 = {.hal_fdcanP = &hal_fdcan2}; +volatile static CANHandle CAN2 = {.hal_fdcanP = &hal_fdcan2}; // #endif // #ifdef USECAN3 static FDCAN_HandleTypeDef hal_fdcan3 = {.Instance = FDCAN3}; -static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3}; +volatile static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3}; // #endif +#define MIN(A,B) ((A < B) ? A : B) + // macro lore /* #define CAT(a,b) a##b @@ -77,7 +79,7 @@ static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3}; //TODO: Modify helpers to work across families //helpers ================= -static int fdcan_shared_clock_ref = 0; +volatile static int fdcan_shared_clock_ref = 0; static inline void fdcan_enable_shared_clock(void); static inline void fdcan_disable_shared_clock(void); static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan); @@ -150,6 +152,9 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_gpio = config->tx_gpio; canHandle->rx_pin = config->init_rx_gpio.Pin; canHandle->tx_pin = config->init_tx_gpio.Pin; + canHandle->rx_interrupt_priority = config->rx_interrupt_priority; + canHandle->tx_interrupt_priority = config->tx_interrupt_priority; + canHandle->rx_callback = config->rx_callback; canHandle->tx_buffer_length = config->tx_buffer_length; @@ -223,8 +228,9 @@ int can_release(CANHandle *canHandle) // HAL_FDCAN_DeInit(canHandle->hal_fdcanP); resets a little too hard FDCAN_InstanceDeInit(canHandle->hal_fdcanP); - __DSB(); // Data Synchronization Barrier - __ISB(); // Instruction Synchronization Barrier + //TODO: Not sure these actually do anything + //__DSB(); // Data Synchronization Barrier + //__ISB(); // Instruction Synchronization Barrier // free circular buffer contents GR_CircularBuffer_Free(&(canHandle->tx_buffer)); @@ -236,7 +242,7 @@ int can_release(CANHandle *canHandle) return 0; } -//TODO: ISR DANGER +//TODO: prevent races conditions on the circular buffer //TODO: Implement timer //lock access to Circular Buffer when sending and dequeuing static void can_tx_dequeue_helper(CANHandle *handle) @@ -250,8 +256,9 @@ static void can_tx_dequeue_helper(CANHandle *handle) return; } - uint32_t primask = __get_PRIMASK(); - __disable_irq(); + //uint32_t primask = __get_PRIMASK(); + //__disable_irq(); + //TODO: No need to lock circular buffer, as this ISR cannot interrupt the thread mode (can_send) if (!GR_CircularBuffer_IsEmpty(handle->tx_buffer)) { //Can Add to Fifo Q @@ -271,17 +278,14 @@ static void can_tx_dequeue_helper(CANHandle *handle) //free(msg); // Free the message we couldn't send return; // Stop trying to send more } - free(msg); // Successfully sent, free the memory + free(msg); // Successfully sent, free the entry in the circular buffer - } else { //try again later with a timer /? + } else { //TODO: call can_tx_dequeue_helper later with a timer? } } - - __set_PRIMASK(primask); } -//Use to directly send int can_send(CANHandle *canHandle, FDCANTxMessage *message) { if (!canHandle || !message) { @@ -294,11 +298,12 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) return -1; } - uint32_t primask = __get_PRIMASK(); - __disable_irq(); // IF TX Fifos are not full, send directly to them // If TX Fifos are full, append to circular buffer // If circular buffer is full, return an error code + uint32_t primask = __get_BASEPRI(); + __set_BASEPRI(canHandle->tx_interrupt_priority); //acquire the lock on the circular buffer + uint32_t free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP); if (free > 0) { @@ -306,8 +311,6 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) message->data // Not &message->data if data is array ); - __set_PRIMASK(primask); - if (status != HAL_OK) { LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); return -1; @@ -315,26 +318,26 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) return 0; } + // Hardware FIFO full, try software buffer if (!GR_CircularBuffer_IsFull(canHandle->tx_buffer)) { int result = GR_CircularBuffer_Push(canHandle->tx_buffer, message, sizeof(FDCANTxMessage)); - __set_PRIMASK(primask); + __set_BASEPRI(primask); if (result != 0) { LOGOMATIC("CAN_send: buffer push failed\n"); return -1; + } else { + return 0; } - return 0; } - + __set_BASEPRI(primask); // Both buffers full - __set_PRIMASK(primask); LOGOMATIC("CAN_send: all buffers full\n"); return -1; } - void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes) { UNUSED(BufferIndexes); @@ -345,6 +348,7 @@ void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t Bu // see if you can pop any more from the buffer can_tx_dequeue_helper(handle); } + void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) { CANHandle *handle = can_get_handle(hfdcan); @@ -358,9 +362,9 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) return; } */ // no rx buffer at the moment - /*if (RxFifo0ITs & FDCAN_IT_RX_FIFO0_MESSAGE_LOST) { - lost_rx++; - }*/ + if (RxFifo0ITs & FDCAN_IT_RX_FIFO0_MESSAGE_LOST) { + //lost_rx++; + } if (!(RxFifo0ITs & ~FDCAN_IT_RX_FIFO0_MESSAGE_LOST)) { return; @@ -370,7 +374,6 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) FDCAN_RxHeaderTypeDef rx_header; uint8_t rx_data[64] = {0}; - //if goign to declare on stack, might as well while (HAL_FDCAN_GetRxFifoFillLevel(hfdcan, FDCAN_RX_FIFO0) > 0) { HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header, rx_data); @@ -390,6 +393,7 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) GR_CircularBuffer_Push(handle->rx_buffer, rx_data, rx_header.DataLength); } }*/ + //__set_BASEPRI(prev_priority); } /* @@ -431,12 +435,26 @@ int can_start(CANHandle *canHandle) return -1; } + if (canHandle->started) return 0; + + IRQn_Type rx0it, txit; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); + + HAL_NVIC_ClearPendingIRQ(rx0it); //prevent a spurious interrupt + HAL_NVIC_ClearPendingIRQ(txit); + GPIOx_CLK_ENABLE(canHandle->rx_gpio); GPIOx_CLK_ENABLE(canHandle->tx_gpio); HAL_FDCAN_Start(canHandle->hal_fdcanP); + canHandle->started = true; + __set_PRIMASK(1); + HAL_NVIC_EnableIRQ(rx0it); + HAL_NVIC_EnableIRQ(txit); + __set_PRIMASK(0); + return 0; } @@ -445,12 +463,29 @@ int can_stop(CANHandle *canHandle) if (!canHandle || !canHandle->init) { return -1; } + if (!canHandle->started) { return 0; } + //stop can interrupts from activating + __set_PRIMASK(1); + uint32_t prev_priority = __get_BASEPRI(); + __set_PRIMASK(0); + __set_BASEPRI( MIN(canHandle->rx_interrupt_priority, canHandle->tx_interrupt_priority) ); + HAL_FDCAN_Stop(canHandle->hal_fdcanP); + IRQn_Type rx0it, txit; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); + + HAL_NVIC_DisableIRQ(rx0it); + HAL_NVIC_DisableIRQ(txit); + HAL_NVIC_ClearPendingIRQ(rx0it); + HAL_NVIC_ClearPendingIRQ(txit); + + __set_BASEPRI(prev_priority); + GPIOx_CLK_DISABLE(canHandle->rx_gpio); GPIOx_CLK_DISABLE(canHandle->tx_gpio); @@ -463,31 +498,23 @@ int can_stop(CANHandle *canHandle) // ==================================== HELPER FUNCTIONS =============================================== //TODO: Abstract across families + static inline void fdcan_enable_shared_clock(void) { - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - if (fdcan_shared_clock_ref == 0) { __HAL_RCC_FDCAN_CLK_ENABLE(); } fdcan_shared_clock_ref++; - - __set_PRIMASK(primask); } static inline void fdcan_disable_shared_clock(void) { - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - if (fdcan_shared_clock_ref > 0) { fdcan_shared_clock_ref--; if (fdcan_shared_clock_ref == 0) { __HAL_RCC_FDCAN_CLK_DISABLE(); } } - __set_PRIMASK(primask); } // valid only for STM32G4 @@ -529,7 +556,6 @@ static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan) } } - /* static inline void gpio_clk_enable(GPIO_TypeDef *gpio) { @@ -560,7 +586,6 @@ static int can_msp_init(CANHandle *canHandle, CANConfig *config) // FDCAN Clock Select fdcan_enable_shared_clock(); - //__HAL_RCC_FDCAN_CLK_ENABLE(); // Clock speed for FDCAN determined by APB1 clock speed and FDCAN prescaler @@ -577,13 +602,13 @@ static int can_msp_init(CANHandle *canHandle, CANConfig *config) // rxfifo0 HAL_NVIC_SetPriority(rxit, config->rx_interrupt_priority, 0); - HAL_NVIC_EnableIRQ(rxit); // tx HAL_NVIC_SetPriority(txit, config->tx_interrupt_priority, 0); - HAL_NVIC_EnableIRQ(txit); // End MSP Init -------------- + //Call can_start() to enable interrupts + return 0; } @@ -604,6 +629,7 @@ static int can_msp_deinit(CANHandle* canHandle) { HAL_GPIO_DeInit(canHandle->tx_gpio, canHandle->tx_pin); //MSP shared layer for GPIOs + //TODO: used to disable GPIOs clocks, but that might affect other peripherals //RCC fdcan_disable_shared_clock(); @@ -651,16 +677,14 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) return "UNKNOWN"; }*/ - // ===================================== HAL Callbacks ================================ - //TODO: Implement Family Checks //Probably is safe from races -void FDCAN1_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); HAL_NVIC_ClearPendingIRQ(FDCAN1_IT0_IRQn);} -void FDCAN1_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); HAL_NVIC_ClearPendingIRQ(FDCAN1_IT1_IRQn);} +void FDCAN1_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); } +void FDCAN1_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); } -void FDCAN2_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); HAL_NVIC_ClearPendingIRQ(FDCAN2_IT0_IRQn);} -void FDCAN2_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); HAL_NVIC_ClearPendingIRQ(FDCAN2_IT1_IRQn);} +void FDCAN2_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); } +void FDCAN2_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); } -void FDCAN3_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); HAL_NVIC_ClearPendingIRQ(FDCAN3_IT0_IRQn);} -void FDCAN3_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); HAL_NVIC_ClearPendingIRQ(FDCAN3_IT1_IRQn);} +void FDCAN3_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); } +void FDCAN3_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); } From 6d6d9ffa2c73ef46b5f2ff5faa85145a08282ed2 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Thu, 29 Jan 2026 01:12:57 -0800 Subject: [PATCH 12/44] added basepri masking, also tried to prevent spurious NVIC interrupts in can_start and can_stop --- Lib/Peripherals/CAN/Src/can.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index f5382c86b..6c6682fdc 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -301,8 +301,11 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) // IF TX Fifos are not full, send directly to them // If TX Fifos are full, append to circular buffer // If circular buffer is full, return an error code + //stop can interrupts from activating + __set_PRIMASK(1); uint32_t primask = __get_BASEPRI(); - __set_BASEPRI(canHandle->tx_interrupt_priority); //acquire the lock on the circular buffer + __set_PRIMASK(0); + __set_BASEPRI( canHandle->tx_interrupt_priority ); uint32_t free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP); From 18af90b400f838b3734e040e10678bd30ad7b5d8 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Fri, 30 Jan 2026 00:43:45 -0800 Subject: [PATCH 13/44] Refactored to use statically sized spsc buffer --- Lib/Peripherals/CAN/Inc/can.h | 13 ++- Lib/Peripherals/CAN/README.md | 4 + Lib/Peripherals/CAN/Src/can.c | 167 +++++++++++++++++---------- Lib/Peripherals/CAN/Test/can_tests.c | 1 + 4 files changed, 119 insertions(+), 66 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index 1ce0f19bc..bde1aef50 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -24,7 +24,7 @@ typedef struct { uint32_t tx_interrupt_priority; // Circular Buffer - uint32_t tx_buffer_length; + //uint32_t tx_buffer_capacity; GPIO_TypeDef *rx_gpio; // Instance name, like GPIOA, GPIOB, etc. GPIO_InitTypeDef init_rx_gpio; // GPIO Parameters - set correct Alternate Function, no pullup/pulldown, high/very_high frequency @@ -36,10 +36,15 @@ typedef struct { // FDCAN peripheral for STM32G4 typedef struct { - FDCAN_HandleTypeDef *hal_fdcanP; - CircularBuffer *tx_buffer; - uint32_t tx_buffer_length; + FDCAN_HandleTypeDef *hal_fdcanP; //DO NOT REORDER THIS + //TX buffer + volatile FDCANTxMessage *tx_buffer; + volatile uint32_t tx_capacity; + volatile uint32_t tx_tail; + volatile uint32_t tx_elements; + + //RX Callback CAN_RXCallback rx_callback; uint32_t rx_interrupt_priority; diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index 7f05e8130..c26bf2f38 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -19,8 +19,12 @@ If no filters are set, the default behaviour is to accept all standard and exten CHANGES: - with a single producer, single consumer tx buffer, can instead use a fixed-size ring buffer instead of the circular buffer +- DMA support for copying from circular buffer +- Timer Support for continously dequeuing, or call can_tx_dequeue_helper after every hardware enqueue - avoids free issues inside the ISR - can also use the ISR to drain the tx buffer, can_send only adds to it +- + PROBLEMS: - Freeing within ISRs whenever popping from CircularBuffer (yes its faster, than stack copies, but heap is getting fragmented) diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 6c6682fdc..f206c25db 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -9,18 +9,24 @@ // HAL handles // #ifdef USECAN1 +#define TX_BUFFER_1_SIZE 10 static FDCAN_HandleTypeDef hal_fdcan1 = {.Instance = FDCAN1}; -volatile static CANHandle CAN1 = {.hal_fdcanP = &hal_fdcan1}; +FDCANTxMessage tx_buffer_1[TX_BUFFER_1_SIZE] = {0}; +static CANHandle CAN1 = {.hal_fdcanP = &hal_fdcan1, .tx_buffer = tx_buffer_1}; // #endif // #ifdef USECAN2 +#define TX_BUFFER_2_SIZE 10 static FDCAN_HandleTypeDef hal_fdcan2 = {.Instance = FDCAN2}; -volatile static CANHandle CAN2 = {.hal_fdcanP = &hal_fdcan2}; +FDCANTxMessage tx_buffer_2[TX_BUFFER_2_SIZE] = {0}; +static CANHandle CAN2 = {.hal_fdcanP = &hal_fdcan2, .tx_buffer = tx_buffer_2}; // #endif // #ifdef USECAN3 +#define TX_BUFFER_3_SIZE 10 static FDCAN_HandleTypeDef hal_fdcan3 = {.Instance = FDCAN3}; -volatile static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3}; +FDCANTxMessage tx_buffer_3[TX_BUFFER_3_SIZE] = {0}; +static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3, .tx_buffer = tx_buffer_3}; // #endif #define MIN(A,B) ((A < B) ? A : B) @@ -79,7 +85,7 @@ volatile static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3}; //TODO: Modify helpers to work across families //helpers ================= -volatile static int fdcan_shared_clock_ref = 0; +static int fdcan_shared_clock_ref = 0; static inline void fdcan_enable_shared_clock(void); static inline void fdcan_disable_shared_clock(void); static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan); @@ -109,6 +115,8 @@ CANHandle *can_init(const CANConfig *config) return 0; } else { canHandle = &CAN1; + canHandle->tx_capacity = TX_BUFFER_1_SIZE; + } } // #endif @@ -119,6 +127,8 @@ CANHandle *can_init(const CANConfig *config) return 0; } else { canHandle = &CAN2; + canHandle->tx_capacity = TX_BUFFER_2_SIZE; + } } // #ifdef USECAN3 @@ -128,6 +138,7 @@ CANHandle *can_init(const CANConfig *config) return 0; } else { canHandle = &CAN3; + canHandle->tx_capacity = TX_BUFFER_3_SIZE; } } // #endif @@ -155,27 +166,31 @@ CANHandle *can_init(const CANConfig *config) canHandle->rx_interrupt_priority = config->rx_interrupt_priority; canHandle->tx_interrupt_priority = config->tx_interrupt_priority; - canHandle->rx_callback = config->rx_callback; - canHandle->tx_buffer_length = config->tx_buffer_length; + + //tx buffer + //canHandle->tx_capacity = TX_BUFFER_SIZE_1; //dependent on can instance + canHandle->tx_tail = 0; + canHandle->tx_elements = 0; // alternately -> have can_msp_init setup state for HAL_FDCAN_MspInit to work correctly // have can_msp_deinit setup state for HAL_FDCAN_MspDeInit to work correctly // Then call HAL_FDCAN_Init() and HAL_FDCAN_DeInit() // Current idea, redefine HAL_FDCAN_MspInit and MspDeInit do nothing at all, do all the work in can_msp_init() - if (can_msp_init(canHandle, (CANConfig *)config)) { + uint32_t failure = 0; + if ( failure |= (can_msp_init(canHandle, (CANConfig *)config))) { LOGOMATIC("CAN_init: could not initialize MSP resources"); - can_release(canHandle); } // PROBLEM: HAL_FDCAN_Init expects HAL_FDCAN_MspInit() to be defined if (HAL_FDCAN_Init(canHandle->hal_fdcanP) != HAL_OK) { + failure |= HAL_ERROR; LOGOMATIC("CAN: HAL Could not initialize FDCAN peripheral"); - return NULL; // Error_Handler(); } + // Active FDCAN callbacks - rxcalback uses line0, txcallback uses line1 // uint32_t rxevents = FDCAN_IT_RX_FIFO0_NEW_MESSAGE; uint32_t status = 0; @@ -192,23 +207,35 @@ CANHandle *can_init(const CANConfig *config) if (status & HAL_ERROR) { LOGOMATIC("CAN: Could not activate rx and tx interrupts\n"); - return NULL; + failure |= status; } // Circular Buffer - canHandle->tx_buffer = GR_CircularBuffer_Create(config->tx_buffer_length); + //canHandle->tx_buffer = GR_CircularBuffer_Create(config->tx_buffer_length); + //canHandle->tx_buffer = malloc(sizeof(FDCANTxMessage)*canHandle->tx_buffer_length); if (!canHandle->tx_buffer) { - LOGOMATIC("CAN: Could not allocate circular buffer\n"); + LOGOMATIC("tx_buffer isn't valid?"); + failure |= 1; + } + + if (failure) { + can_msp_deinit(canHandle); + FDCAN_InstanceDeInit(canHandle->hal_fdcanP); + memset(canHandle+sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); //FIXME: Make sure instance is not being overwritten (FDCANx) return 0; } + /*if (!canHandle->tx_buffer) { + LOGOMATIC("CAN: Could not allocate circular buffer\n"); + return 0; + }*/ + canHandle->init = true; canHandle->started = false; return canHandle; } - int can_release(CANHandle *canHandle) { if (!canHandle) { @@ -222,6 +249,8 @@ int can_release(CANHandle *canHandle) } can_stop(canHandle); // try to prevent more interrupts from firing + //No more interrupts should be firing that modify canHandle + can_msp_deinit(canHandle); // reset FDCANx instance and message RAM and filters, clear interrupts @@ -233,12 +262,13 @@ int can_release(CANHandle *canHandle) //__ISB(); // Instruction Synchronization Barrier // free circular buffer contents - GR_CircularBuffer_Free(&(canHandle->tx_buffer)); + //GR_CircularBuffer_Free(&(canHandle->tx_buffer)); + memset(canHandle->tx_buffer, 0, canHandle->tx_capacity*sizeof(FDCANTxMessage)); + canHandle->tx_elements = 0; + canHandle->tx_tail = 0; // reset can handle - FDCAN_HandleTypeDef *temp = canHandle->hal_fdcanP; - memset(canHandle, 0, sizeof(*canHandle)); - canHandle->hal_fdcanP = temp; + memset( (void*)canHandle+sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); return 0; } @@ -252,38 +282,45 @@ static void can_tx_dequeue_helper(CANHandle *handle) return; } - if (GR_CircularBuffer_IsEmpty(handle->tx_buffer)) { + + //TODO: use interrupt masking in case any other ISRs need to lock the circular buffer + uint32_t basepri = __get_BASEPRI(); + + __set_BASEPRI(handle->tx_interrupt_priority); + //single consumer shouldn't affect state of circular buffer too closely + if (handle->tx_elements == 0) { + __set_BASEPRI(basepri); return; } - //uint32_t primask = __get_PRIMASK(); + //uint32_t basepri = __get_basepri(); //__disable_irq(); //TODO: No need to lock circular buffer, as this ISR cannot interrupt the thread mode (can_send) - if (!GR_CircularBuffer_IsEmpty(handle->tx_buffer)) { - //Can Add to Fifo Q - if (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP)) { + //Can Add to Fifo Q + if (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP)) { + //lock the Circular Buffer + FDCANTxMessage *msg = &handle->tx_buffer[handle->tx_tail]; - //lock the Circular Buffer - FDCANTxMessage *msg = GR_CircularBuffer_Pop(handle->tx_buffer); - if (!msg) { - return ; - } + //should call Tx Buffer Callback once complete + HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(handle->hal_fdcanP, &msg->tx_header, msg->data); - //should call Tx Buffer Callback once complete - HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(handle->hal_fdcanP, &msg->tx_header, msg->data); + if (status != HAL_OK) { + //LOGOMATIC("CAN_tx_helper: failed to add message to FIFO\n"); //FIXME: Logomatic may not work with interrupts disabled + __set_BASEPRI(basepri); + return; // Stop trying to send more + } + //free(msg); // Successfully sent, free the entry in the circular buffer (which is pointed to by tail) + handle->tx_tail = ++handle->tx_tail % handle->tx_capacity; + handle->tx_elements--; - if (status != HAL_OK) { - LOGOMATIC("CAN_tx_helper: failed to add message to FIFO\n"); - //free(msg); // Free the message we couldn't send - return; // Stop trying to send more - } - free(msg); // Successfully sent, free the entry in the circular buffer + } else { //FIXME: call can_tx_dequeue_helper later with a timer, if this gets implemented, need to mask timer interrupts to allow atomic access + + } //alternatively, if fifo is full, tx_dequeue should get called anyways, and we don't need the else statement + + __set_BASEPRI(basepri); - } else { //TODO: call can_tx_dequeue_helper later with a timer? - } - } } int can_send(CANHandle *canHandle, FDCANTxMessage *message) @@ -301,43 +338,47 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) // IF TX Fifos are not full, send directly to them // If TX Fifos are full, append to circular buffer // If circular buffer is full, return an error code - //stop can interrupts from activating - __set_PRIMASK(1); - uint32_t primask = __get_BASEPRI(); - __set_PRIMASK(0); - __set_BASEPRI( canHandle->tx_interrupt_priority ); - uint32_t free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP); + //stop can_tx_dequeue_helper from from interleaving + uint32_t basepri = __get_BASEPRI(); + __set_BASEPRI( canHandle->tx_interrupt_priority ); - if (free > 0) { - HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), - message->data // Not &message->data if data is array - ); + if (HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP) > 0) { + HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), message->data); + uint32_t val = 0; if (status != HAL_OK) { LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); - return -1; + val = -1; + } else { + val = 0; } - return 0; + __set_BASEPRI( basepri ); + return val; } - // Hardware FIFO full, try software buffer - if (!GR_CircularBuffer_IsFull(canHandle->tx_buffer)) { - int result = GR_CircularBuffer_Push(canHandle->tx_buffer, message, sizeof(FDCANTxMessage)); + if (canHandle->tx_elements < canHandle->tx_capacity) { + //int result = GR_CircularBuffer_Push(canHandle->tx_buffer, message, sizeof(FDCANTxMessage)); + + uint32_t idx = (canHandle->tx_tail + canHandle->tx_elements) % canHandle->tx_capacity; + canHandle->tx_buffer[idx] = *message; + canHandle->tx_elements++; + //memcpy(&canHandle->tx_buffer[idx], message , sizeof(FDCANTxMessage) ); - __set_BASEPRI(primask); + //__set_BASEPRI(primask); - if (result != 0) { + /*if (result != 0) { LOGOMATIC("CAN_send: buffer push failed\n"); return -1; } else { return 0; - } + }*/ + } else { + LOGOMATIC("CAN_send: all buffers full\n"); } - __set_BASEPRI(primask); + __set_BASEPRI(basepri); // Both buffers full - LOGOMATIC("CAN_send: all buffers full\n"); return -1; } @@ -352,6 +393,12 @@ void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t Bu can_tx_dequeue_helper(handle); } +void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef *hfdcan) +{ + CANHandle *handle = can_get_handle(hfdcan); + can_tx_dequeue_helper(handle); +} + void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) { CANHandle *handle = can_get_handle(hfdcan); @@ -453,10 +500,8 @@ int can_start(CANHandle *canHandle) canHandle->started = true; - __set_PRIMASK(1); HAL_NVIC_EnableIRQ(rx0it); HAL_NVIC_EnableIRQ(txit); - __set_PRIMASK(0); return 0; } @@ -472,9 +517,7 @@ int can_stop(CANHandle *canHandle) } //stop can interrupts from activating - __set_PRIMASK(1); uint32_t prev_priority = __get_BASEPRI(); - __set_PRIMASK(0); __set_BASEPRI( MIN(canHandle->rx_interrupt_priority, canHandle->tx_interrupt_priority) ); HAL_FDCAN_Stop(canHandle->hal_fdcanP); diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index e4f33000e..c968dbbe9 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -28,6 +28,7 @@ void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) return; } +//TODO: G4 tests are dependent on the System clock configuration int can_test(void) { From ebc37b8cab7f54d94f5d97e20692efda1c519749 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:57:23 -0800 Subject: [PATCH 14/44] passed human testing --- .vscode/launch.json | 4 ++-- Lib/Peripherals/CAN/Inc/can.h | 22 ++++++++++------- Lib/Peripherals/CAN/README.md | 2 +- Lib/Peripherals/CAN/Src/can.c | 35 ++++++++++++++++------------ Lib/Peripherals/CAN/Test/can_tests.c | 23 +++++++++++------- 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index cdb5115c9..2b606146c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -222,7 +222,7 @@ }, { "cwd": "${workspaceFolder}", - "executable": "${command:cmake.buildDirectory}/G4ADCTESTING.elf", + "executable": "${command:cmake.buildDirectory}/G4CANTESTING.elf", "name": "G4CANTESTING", "request": "launch", "type": "cortex-debug", @@ -232,7 +232,7 @@ "target/stm32g4x.cfg" ], "searchDir": [], - "preLaunchTask": "CMake: configure and build G4ADCTESTING", + "preLaunchTask": "CMake: configure and build G4CANTESTING", "showDevDebugOutput": "raw", "svdPath": "${workspaceFolder}/Lib/Platform/STM32G474xE/CompileDependencies/STM32G474.svd", "swoConfig": { diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index bde1aef50..7b7ccb1f6 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -34,6 +34,18 @@ typedef struct { // additional parameters } CANConfig; + +#define FDCAN_MAX_DATA_BYTES 64 +typedef struct { + FDCAN_TxHeaderTypeDef tx_header; + uint8_t data[FDCAN_MAX_DATA_BYTES]; +} FDCANTxMessage; +typedef struct { + FDCAN_RxHeaderTypeDef rx_header; + uint8_t data[FDCAN_MAX_DATA_BYTES]; +} FDCANRxMessage; + + // FDCAN peripheral for STM32G4 typedef struct { FDCAN_HandleTypeDef *hal_fdcanP; //DO NOT REORDER THIS @@ -64,15 +76,7 @@ typedef struct { // error states } CANHandle; -#define FDCAN_MAX_DATA_BYTES 64 -typedef struct { - FDCAN_TxHeaderTypeDef tx_header; - uint8_t data[FDCAN_MAX_DATA_BYTES]; -} FDCANTxMessage; -typedef struct { - FDCAN_RxHeaderTypeDef rx_header; - uint8_t data[FDCAN_MAX_DATA_BYTES]; -} FDCANRxMessage; + CANHandle *can_init(const CANConfig *config); // user must supply an rx callback function int can_start(CANHandle *handle); diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index c26bf2f38..41ec73f52 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -23,7 +23,7 @@ CHANGES: - Timer Support for continously dequeuing, or call can_tx_dequeue_helper after every hardware enqueue - avoids free issues inside the ISR - can also use the ISR to drain the tx buffer, can_send only adds to it -- + PROBLEMS: diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index f206c25db..1ef7c9015 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -9,21 +9,21 @@ // HAL handles // #ifdef USECAN1 -#define TX_BUFFER_1_SIZE 10 +#define TX_BUFFER_1_SIZE 3 static FDCAN_HandleTypeDef hal_fdcan1 = {.Instance = FDCAN1}; FDCANTxMessage tx_buffer_1[TX_BUFFER_1_SIZE] = {0}; static CANHandle CAN1 = {.hal_fdcanP = &hal_fdcan1, .tx_buffer = tx_buffer_1}; // #endif // #ifdef USECAN2 -#define TX_BUFFER_2_SIZE 10 +#define TX_BUFFER_2_SIZE 3 static FDCAN_HandleTypeDef hal_fdcan2 = {.Instance = FDCAN2}; FDCANTxMessage tx_buffer_2[TX_BUFFER_2_SIZE] = {0}; static CANHandle CAN2 = {.hal_fdcanP = &hal_fdcan2, .tx_buffer = tx_buffer_2}; // #endif // #ifdef USECAN3 -#define TX_BUFFER_3_SIZE 10 +#define TX_BUFFER_3_SIZE 3 static FDCAN_HandleTypeDef hal_fdcan3 = {.Instance = FDCAN3}; FDCANTxMessage tx_buffer_3[TX_BUFFER_3_SIZE] = {0}; static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3, .tx_buffer = tx_buffer_3}; @@ -31,6 +31,8 @@ static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3, .tx_buffer = tx_buffer_3}; #define MIN(A,B) ((A < B) ? A : B) +bool hardwareEnabled = false; + // macro lore /* #define CAT(a,b) a##b @@ -343,19 +345,22 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) uint32_t basepri = __get_BASEPRI(); __set_BASEPRI( canHandle->tx_interrupt_priority ); - if (HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP) > 0) { - HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), message->data); - - uint32_t val = 0; - if (status != HAL_OK) { - LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); - val = -1; - } else { - val = 0; + //FIXME: get rid of this jank + //if (hardwareEnabled) { + if (HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP) > 0) { + HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), message->data); + + uint32_t val = 0; + if (status != HAL_OK) { + LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); + val = -1; + } else { + val = 0; + } + __set_BASEPRI( basepri ); + return val; } - __set_BASEPRI( basepri ); - return val; - } + //} // Hardware FIFO full, try software buffer if (canHandle->tx_elements < canHandle->tx_capacity) { diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index c968dbbe9..7df7142b6 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -31,14 +31,13 @@ void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) //TODO: G4 tests are dependent on the System clock configuration int can_test(void) { - CANConfig canCfg; // canCfg.fdcan_instance = FDCAN2; canCfg.hal_fdcan_init.ClockDivider = FDCAN_CLOCK_DIV1; canCfg.hal_fdcan_init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; canCfg.hal_fdcan_init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; - canCfg.hal_fdcan_init.Mode = FDCAN_MODE_NORMAL; + canCfg.hal_fdcan_init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK; canCfg.hal_fdcan_init.AutoRetransmission = ENABLE; canCfg.hal_fdcan_init.TransmitPause = DISABLE; canCfg.hal_fdcan_init.ProtocolException = ENABLE; @@ -54,9 +53,8 @@ int can_test(void) canCfg.hal_fdcan_init.ExtFiltersNbr = 0; canCfg.rx_callback = NULL; // PLEASE SET - canCfg.rx_interrupt_priority = 0; // PLEASE SET - canCfg.tx_interrupt_priority = 0; // PLEASE SET - canCfg.tx_buffer_length = 3; // PLEASE SET + canCfg.rx_interrupt_priority = 5; // PLEASE SET + canCfg.tx_interrupt_priority = 5; // PLEASE SET // canCfg.rx_gpio = GPIOB; // canCfg.init_rx_gpio.Pin = GPIO_PIN_12; @@ -92,14 +90,13 @@ int can_test(void) }; FDCANTxMessage msg; - msg.data[0] = 0x80; memset(&(msg.data), 0, sizeof(msg.data)); + msg.data[0] = 0x80; msg.tx_header = TxHeader; can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); #ifdef FDCAN1 - canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; canCfg.init_rx_gpio.Pin = GPIO_PIN_11; @@ -114,11 +111,15 @@ int can_test(void) CANHandle *can1Handle = can_init(&canCfg); HAL_FDCAN_ConfigGlobalFilter(can1Handle->hal_fdcanP, 0, 0, 0, 0); + //can1Handle->tx_buffer[0] = msg; + //can1Handle->tx_buffer[1] = msg; + //can1Handle->tx_buffer[2] = msg; + //can1Handle->tx_elements = 3; + can_start(can1Handle); #endif #ifdef FDCAN2 - canCfg.fdcan_instance = FDCAN2; canCfg.rx_gpio = GPIOB; canCfg.init_rx_gpio.Pin = GPIO_PIN_12; @@ -149,11 +150,15 @@ int can_test(void) // API Testing // can_init(&canCfg); + //can2Handle->tx_buffer[0] = msg; + //can2Handle->tx_buffer[1] = msg; + //can2Handle->tx_buffer[2] = msg; + //can2Handle->tx_elements = 3; + can_start(can2Handle); can_send(can2Handle, &msg); // can_release(can2Handle); - #endif #ifdef FDCAN3 From 7245169d4a3ad2e3b6ad7c79dbb8ba54e1c5d25d Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Wed, 11 Feb 2026 10:55:33 -0800 Subject: [PATCH 15/44] added notes in readme --- Lib/Peripherals/CAN/README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index 41ec73f52..4cb128ff5 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -20,23 +20,22 @@ If no filters are set, the default behaviour is to accept all standard and exten CHANGES: - with a single producer, single consumer tx buffer, can instead use a fixed-size ring buffer instead of the circular buffer - DMA support for copying from circular buffer -- Timer Support for continously dequeuing, or call can_tx_dequeue_helper after every hardware enqueue -- avoids free issues inside the ISR -- can also use the ISR to drain the tx buffer, can_send only adds to it +- Timer Support for continously dequeuing between API calls, + - call can_tx_dequeue_helper after every successful hardware enqueue. + - avoids free issues inside the ISR +- Error counter handling, waiting for more stable CAN bus state????? PROBLEMS: -- Freeing within ISRs whenever popping from CircularBuffer (yes its faster, than stack copies, but heap is getting fragmented) - ISRS might take too long to resolve because popping and freeing circular buffer. - - HARDCODE Platform Usage Flag for compiler definitions - CAN.H expects #STM32G4 to be defined, - RX Callback must perform deep copy of data supplied to it - could also malloc, but not safe to do inside ISRs IDEAS for other features: -- - DMA support for copying from circular buffer -- Circular buffer should be fixed size anyways +- +- DMA support for copying 64 bytes from circular buffer - abstract to different STM families besides STM32G4 - Rx Buffering - TX Buffering policy, do we spread them out over multiple TX buffers From 1b2addea8614cd23a6a9a8a5415cfcdc4912a83f Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Wed, 18 Feb 2026 17:22:38 -0800 Subject: [PATCH 16/44] tried to fix CAN data baud rate in ECU/Core/Src/main.c --- ECU/Core/Src/main.c | 8 ++++---- Lib/Peripherals/CAN/Src/can.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index cf127901c..708fd6d1d 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -266,17 +266,17 @@ void CAN_Configure() canCfg.hal_fdcan_init.NominalSyncJumpWidth = 16; canCfg.hal_fdcan_init.NominalTimeSeg1 = 127; // Updated for 170MHz: (1+127+42)*1 = 170 ticks -> 1 Mbps canCfg.hal_fdcan_init.NominalTimeSeg2 = 42; - canCfg.hal_fdcan_init.DataPrescaler = 8; + canCfg.hal_fdcan_init.DataPrescaler = 2; canCfg.hal_fdcan_init.DataSyncJumpWidth = 16; - canCfg.hal_fdcan_init.DataTimeSeg1 = 15; // Updated for 170MHz: (1+15+5)*8 = 168 ticks -> ~5 Mbps - canCfg.hal_fdcan_init.DataTimeSeg2 = 5; + canCfg.hal_fdcan_init.DataTimeSeg1 = 12; // Updated for 170MHz: 170 MHz/((1+12+4)*2) = 5 Mbps + canCfg.hal_fdcan_init.DataTimeSeg2 = 4; canCfg.hal_fdcan_init.StdFiltersNbr = 1; canCfg.hal_fdcan_init.ExtFiltersNbr = 0; canCfg.rx_callback = NULL; canCfg.rx_interrupt_priority = 15; // TODO: Maybe make these not hardcoded canCfg.tx_interrupt_priority = 15; - canCfg.tx_buffer_length = CAN_TX_BUFFER_LENGTH; + //canCfg.tx_buffer_length = CAN_TX_BUFFER_LENGTH; // RX shared settings canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 8a72e24c0..e20593700 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -265,7 +265,7 @@ int can_release(CANHandle *canHandle) // free circular buffer contents //GR_CircularBuffer_Free(&(canHandle->tx_buffer)); - memset(canHandle->tx_buffer, 0, canHandle->tx_capacity*sizeof(FDCANTxMessage)); + memset( (void*) canHandle->tx_buffer, 0, canHandle->tx_capacity*sizeof(FDCANTxMessage)); canHandle->tx_elements = 0; canHandle->tx_tail = 0; @@ -380,7 +380,7 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) return 0; }*/ } else { - LOGOMATIC("CAN_send: all buffers full\n"); + LOGOMATIC("CAN_send: all buffers full\n"); //p } __set_BASEPRI(basepri); // Both buffers full @@ -441,7 +441,7 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) // GR_OLD_MSG_ID messageID = (rx_header.Identifier & (0xFFF << 8)) >> 8; handle->rx_callback(rx_header.Identifier, rx_data, rx_header.DataLength); } - + /* if (GR_CircularBuffer_IsEmpty(handle->rx_buffer)) handle->rx_callback(rx_data, rx_header.DataLength); else { GR_CircularBuffer_Push(handle->rx_buffer, rx_data, rx_header.DataLength); From 6afe33a605d392a116d598412ea9e731ef0cb8b6 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 03:45:32 +0000 Subject: [PATCH 17/44] Automatic Clang-Format: Standardized formatting automatically --- ECU/Core/Src/main.c | 2 +- Lib/Peripherals/CAN/Inc/can.h | 12 +- Lib/Peripherals/CAN/Src/can.c | 928 ++++++++++++++------------- Lib/Peripherals/CAN/Test/can_tests.c | 2 +- 4 files changed, 476 insertions(+), 468 deletions(-) diff --git a/ECU/Core/Src/main.c b/ECU/Core/Src/main.c index 468f4fe53..c17e9d1d3 100644 --- a/ECU/Core/Src/main.c +++ b/ECU/Core/Src/main.c @@ -280,7 +280,7 @@ void CAN_Configure() canCfg.rx_callback = NULL; canCfg.rx_interrupt_priority = 15; // TODO: Maybe make these not hardcoded canCfg.tx_interrupt_priority = 15; - //canCfg.tx_buffer_length = CAN_TX_BUFFER_LENGTH; + // canCfg.tx_buffer_length = CAN_TX_BUFFER_LENGTH; // RX shared settings canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index 7b7ccb1f6..dbdae9863 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -24,7 +24,7 @@ typedef struct { uint32_t tx_interrupt_priority; // Circular Buffer - //uint32_t tx_buffer_capacity; + // uint32_t tx_buffer_capacity; GPIO_TypeDef *rx_gpio; // Instance name, like GPIOA, GPIOB, etc. GPIO_InitTypeDef init_rx_gpio; // GPIO Parameters - set correct Alternate Function, no pullup/pulldown, high/very_high frequency @@ -34,7 +34,6 @@ typedef struct { // additional parameters } CANConfig; - #define FDCAN_MAX_DATA_BYTES 64 typedef struct { FDCAN_TxHeaderTypeDef tx_header; @@ -45,18 +44,17 @@ typedef struct { uint8_t data[FDCAN_MAX_DATA_BYTES]; } FDCANRxMessage; - // FDCAN peripheral for STM32G4 typedef struct { - FDCAN_HandleTypeDef *hal_fdcanP; //DO NOT REORDER THIS + FDCAN_HandleTypeDef *hal_fdcanP; // DO NOT REORDER THIS - //TX buffer + // TX buffer volatile FDCANTxMessage *tx_buffer; volatile uint32_t tx_capacity; volatile uint32_t tx_tail; volatile uint32_t tx_elements; - //RX Callback + // RX Callback CAN_RXCallback rx_callback; uint32_t rx_interrupt_priority; @@ -76,8 +74,6 @@ typedef struct { // error states } CANHandle; - - CANHandle *can_init(const CANConfig *config); // user must supply an rx callback function int can_start(CANHandle *handle); int can_stop(CANHandle *handle); diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index e20593700..4de7d6c87 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -29,7 +29,7 @@ FDCANTxMessage tx_buffer_3[TX_BUFFER_3_SIZE] = {0}; static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3, .tx_buffer = tx_buffer_3}; // #endif -#define MIN(A,B) ((A < B) ? A : B) +#define MIN(A, B) ((A < B) ? A : B) bool hardwareEnabled = false; @@ -42,8 +42,8 @@ bool hardwareEnabled = false; #define ACTIVATE_FDCAN_HELPER(FDCANX, ITY, preirq, subirq) \ do { \ - HAL_NVIC_SetPriority( CAT4(FDCANX##,_,ITY, _IRQn ) , preirq, subirq ); \ - HAL_NVIC_EnableIRQ( CAT4(FDCANX##,_,ITY, _IRQn ) ); \ + HAL_NVIC_SetPriority( CAT4(FDCANX##,_,ITY, _IRQn ) , preirq, subirq ); \ + HAL_NVIC_EnableIRQ( CAT4(FDCANX##,_,ITY, _IRQn ) ); \ } while(0) #define HAL_NVIC_ACTIVATE_FDCAN(FDCANX, ITY, preirq, subirq) \ @@ -60,370 +60,364 @@ bool hardwareEnabled = false; */ #define GPIOx_CLK_ENABLE(GPIOX) \ - do { \ - if (GPIOX == GPIOA) \ - __HAL_RCC_GPIOA_CLK_ENABLE(); \ - else if (GPIOX == GPIOB) \ - __HAL_RCC_GPIOB_CLK_ENABLE(); \ - else if (GPIOX == GPIOD) \ - __HAL_RCC_GPIOD_CLK_ENABLE(); \ - else \ - LOGOMATIC("BAD FDCAN GPIO Port"); \ - } while (0) + do { \ + if (GPIOX == GPIOA) \ + __HAL_RCC_GPIOA_CLK_ENABLE(); \ + else if (GPIOX == GPIOB) \ + __HAL_RCC_GPIOB_CLK_ENABLE(); \ + else if (GPIOX == GPIOD) \ + __HAL_RCC_GPIOD_CLK_ENABLE(); \ + else \ + LOGOMATIC("BAD FDCAN GPIO Port"); \ + } while (0) #define GPIOx_CLK_DISABLE(GPIOX) \ - do { \ - if (GPIOX == GPIOA) \ - __HAL_RCC_GPIOA_CLK_DISABLE(); \ - else if (GPIOX == GPIOB) \ - __HAL_RCC_GPIOB_CLK_DISABLE(); \ - else if (GPIOX == GPIOD) \ - __HAL_RCC_GPIOD_CLK_DISABLE(); \ - else \ - LOGOMATIC("BAD FDCAN GPIO Port"); \ - } while (0) - - - -//TODO: Modify helpers to work across families -//helpers ================= + do { \ + if (GPIOX == GPIOA) \ + __HAL_RCC_GPIOA_CLK_DISABLE(); \ + else if (GPIOX == GPIOB) \ + __HAL_RCC_GPIOB_CLK_DISABLE(); \ + else if (GPIOX == GPIOD) \ + __HAL_RCC_GPIOD_CLK_DISABLE(); \ + else \ + LOGOMATIC("BAD FDCAN GPIO Port"); \ + } while (0) + +// TODO: Modify helpers to work across families +// helpers ================= static int fdcan_shared_clock_ref = 0; static inline void fdcan_enable_shared_clock(void); static inline void fdcan_disable_shared_clock(void); static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan); static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type *it1); -inline void can_set_clksource(uint32_t clksource) { LL_RCC_SetFDCANClockSource(clksource); } +inline void can_set_clksource(uint32_t clksource) +{ + LL_RCC_SetFDCANClockSource(clksource); +} // static const char *can_get_instance_name(FDCAN_GlobalTypeDef *instance) -//static inline void gpio_clk_enable(GPIO_TypeDef *gpio) -//static inline void gpio_clk_disable(GPIO_TypeDef *gpio) +// static inline void gpio_clk_enable(GPIO_TypeDef *gpio) +// static inline void gpio_clk_disable(GPIO_TypeDef *gpio) static int can_msp_init(CANHandle *canHandle, CANConfig *config); -static int can_msp_deinit(CANHandle* canHandle); +static int can_msp_deinit(CANHandle *canHandle); static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan); - //================================================= API ======================================== CANHandle *can_init(const CANConfig *config) { - // config validation? - // assert(config != 0) - - // #ifdef STM32G474xx - CANHandle *canHandle = 0; - // #ifdef USECAN1 - if (config->fdcan_instance == FDCAN1) { - if (CAN1.init) { - LOGOMATIC("CAN: CAN1 is already initialized\n"); - return 0; - } else { - canHandle = &CAN1; - canHandle->tx_capacity = TX_BUFFER_1_SIZE; - - } - } - // #endif - // #ifdef USECAN2 - else if (config->fdcan_instance == FDCAN2) { - if (CAN2.init) { - LOGOMATIC("CAN: CAN2 is already initialized\n"); - return 0; - } else { - canHandle = &CAN2; - canHandle->tx_capacity = TX_BUFFER_2_SIZE; - - } - } - // #ifdef USECAN3 - else if (config->fdcan_instance == FDCAN3) { - if (CAN3.init) { - LOGOMATIC("CAN: CAN3 is already initialized\n"); - return 0; - } else { - canHandle = &CAN3; - canHandle->tx_capacity = TX_BUFFER_3_SIZE; - } - } - // #endif - // #elif defined(STM32L476xx) - // #else - // #error "Unsupported STM32 family" - // #endif - else { - LOGOMATIC("CAN: Unrecognized FDCAN instance"); - return 0; - } - canHandle->init = false; - canHandle->started = false; - - // Initialize handle - assert(config->hal_fdcan_init.TxFifoQueueMode == FDCAN_TX_FIFO_OPERATION); - - canHandle->hal_fdcanP->Init = config->hal_fdcan_init; // copy FDCAN parameters from user - // canHandle->hal_fdcanP->Instance = config->fdcan_instance //handles initialized with correct base instance addresses - - canHandle->rx_gpio = config->rx_gpio; - canHandle->tx_gpio = config->tx_gpio; - canHandle->rx_pin = config->init_rx_gpio.Pin; - canHandle->tx_pin = config->init_tx_gpio.Pin; - canHandle->rx_interrupt_priority = config->rx_interrupt_priority; - canHandle->tx_interrupt_priority = config->tx_interrupt_priority; + // config validation? + // assert(config != 0) + + // #ifdef STM32G474xx + CANHandle *canHandle = 0; + // #ifdef USECAN1 + if (config->fdcan_instance == FDCAN1) { + if (CAN1.init) { + LOGOMATIC("CAN: CAN1 is already initialized\n"); + return 0; + } else { + canHandle = &CAN1; + canHandle->tx_capacity = TX_BUFFER_1_SIZE; + } + } + // #endif + // #ifdef USECAN2 + else if (config->fdcan_instance == FDCAN2) { + if (CAN2.init) { + LOGOMATIC("CAN: CAN2 is already initialized\n"); + return 0; + } else { + canHandle = &CAN2; + canHandle->tx_capacity = TX_BUFFER_2_SIZE; + } + } + // #ifdef USECAN3 + else if (config->fdcan_instance == FDCAN3) { + if (CAN3.init) { + LOGOMATIC("CAN: CAN3 is already initialized\n"); + return 0; + } else { + canHandle = &CAN3; + canHandle->tx_capacity = TX_BUFFER_3_SIZE; + } + } + // #endif + // #elif defined(STM32L476xx) + // #else + // #error "Unsupported STM32 family" + // #endif + else { + LOGOMATIC("CAN: Unrecognized FDCAN instance"); + return 0; + } + canHandle->init = false; + canHandle->started = false; - canHandle->rx_callback = config->rx_callback; + // Initialize handle + assert(config->hal_fdcan_init.TxFifoQueueMode == FDCAN_TX_FIFO_OPERATION); - //tx buffer - //canHandle->tx_capacity = TX_BUFFER_SIZE_1; //dependent on can instance - canHandle->tx_tail = 0; - canHandle->tx_elements = 0; + canHandle->hal_fdcanP->Init = config->hal_fdcan_init; // copy FDCAN parameters from user + // canHandle->hal_fdcanP->Instance = config->fdcan_instance //handles initialized with correct base instance addresses - // alternately -> have can_msp_init setup state for HAL_FDCAN_MspInit to work correctly - // have can_msp_deinit setup state for HAL_FDCAN_MspDeInit to work correctly - // Then call HAL_FDCAN_Init() and HAL_FDCAN_DeInit() + canHandle->rx_gpio = config->rx_gpio; + canHandle->tx_gpio = config->tx_gpio; + canHandle->rx_pin = config->init_rx_gpio.Pin; + canHandle->tx_pin = config->init_tx_gpio.Pin; + canHandle->rx_interrupt_priority = config->rx_interrupt_priority; + canHandle->tx_interrupt_priority = config->tx_interrupt_priority; - // Current idea, redefine HAL_FDCAN_MspInit and MspDeInit do nothing at all, do all the work in can_msp_init() - uint32_t failure = 0; - if ( failure |= (can_msp_init(canHandle, (CANConfig *)config))) { - LOGOMATIC("CAN_init: could not initialize MSP resources"); - } + canHandle->rx_callback = config->rx_callback; - // PROBLEM: HAL_FDCAN_Init expects HAL_FDCAN_MspInit() to be defined - if (HAL_FDCAN_Init(canHandle->hal_fdcanP) != HAL_OK) { - failure |= HAL_ERROR; - LOGOMATIC("CAN: HAL Could not initialize FDCAN peripheral"); - // Error_Handler(); - } + // tx buffer + // canHandle->tx_capacity = TX_BUFFER_SIZE_1; //dependent on can instance + canHandle->tx_tail = 0; + canHandle->tx_elements = 0; + // alternately -> have can_msp_init setup state for HAL_FDCAN_MspInit to work correctly + // have can_msp_deinit setup state for HAL_FDCAN_MspDeInit to work correctly + // Then call HAL_FDCAN_Init() and HAL_FDCAN_DeInit() - // Active FDCAN callbacks - rxcalback uses line0, txcallback uses line1 - // uint32_t rxevents = FDCAN_IT_RX_FIFO0_NEW_MESSAGE; - uint32_t status = 0; - uint32_t rx_events = FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO0_FULL; - status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, rx_events, 0); - status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, rx_events, FDCAN_INTERRUPT_LINE0); + // Current idea, redefine HAL_FDCAN_MspInit and MspDeInit do nothing at all, do all the work in can_msp_init() + uint32_t failure = 0; + if (failure |= (can_msp_init(canHandle, (CANConfig *)config))) { + LOGOMATIC("CAN_init: could not initialize MSP resources"); + } - // uint32_t txevents = FDCAN_IT_TX_COMPLETE; - uint32_t destinations = FDCAN_TX_BUFFER0; - uint32_t tx_events = FDCAN_IT_TX_COMPLETE | FDCAN_IT_TX_FIFO_EMPTY; - status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, tx_events, destinations); - status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, tx_events, FDCAN_INTERRUPT_LINE1); - // Callbacks redefined later + // PROBLEM: HAL_FDCAN_Init expects HAL_FDCAN_MspInit() to be defined + if (HAL_FDCAN_Init(canHandle->hal_fdcanP) != HAL_OK) { + failure |= HAL_ERROR; + LOGOMATIC("CAN: HAL Could not initialize FDCAN peripheral"); + // Error_Handler(); + } - if (status & HAL_ERROR) { - LOGOMATIC("CAN: Could not activate rx and tx interrupts\n"); - failure |= status; - } + // Active FDCAN callbacks - rxcalback uses line0, txcallback uses line1 + // uint32_t rxevents = FDCAN_IT_RX_FIFO0_NEW_MESSAGE; + uint32_t status = 0; + uint32_t rx_events = FDCAN_IT_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_RX_FIFO0_FULL; + status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, rx_events, 0); + status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, rx_events, FDCAN_INTERRUPT_LINE0); + + // uint32_t txevents = FDCAN_IT_TX_COMPLETE; + uint32_t destinations = FDCAN_TX_BUFFER0; + uint32_t tx_events = FDCAN_IT_TX_COMPLETE | FDCAN_IT_TX_FIFO_EMPTY; + status |= HAL_FDCAN_ActivateNotification(canHandle->hal_fdcanP, tx_events, destinations); + status |= HAL_FDCAN_ConfigInterruptLines(canHandle->hal_fdcanP, tx_events, FDCAN_INTERRUPT_LINE1); + // Callbacks redefined later + + if (status & HAL_ERROR) { + LOGOMATIC("CAN: Could not activate rx and tx interrupts\n"); + failure |= status; + } - // Circular Buffer - //canHandle->tx_buffer = GR_CircularBuffer_Create(config->tx_buffer_length); - //canHandle->tx_buffer = malloc(sizeof(FDCANTxMessage)*canHandle->tx_buffer_length); - if (!canHandle->tx_buffer) { - LOGOMATIC("tx_buffer isn't valid?"); - failure |= 1; - } + // Circular Buffer + // canHandle->tx_buffer = GR_CircularBuffer_Create(config->tx_buffer_length); + // canHandle->tx_buffer = malloc(sizeof(FDCANTxMessage)*canHandle->tx_buffer_length); + if (!canHandle->tx_buffer) { + LOGOMATIC("tx_buffer isn't valid?"); + failure |= 1; + } - if (failure) { - can_msp_deinit(canHandle); - FDCAN_InstanceDeInit(canHandle->hal_fdcanP); - memset(canHandle+sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); //FIXME: Make sure instance is not being overwritten (FDCANx) - return 0; - } + if (failure) { + can_msp_deinit(canHandle); + FDCAN_InstanceDeInit(canHandle->hal_fdcanP); + memset(canHandle + sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); // FIXME: Make sure instance is not being overwritten (FDCANx) + return 0; + } - /*if (!canHandle->tx_buffer) { - LOGOMATIC("CAN: Could not allocate circular buffer\n"); - return 0; - }*/ + /*if (!canHandle->tx_buffer) { + LOGOMATIC("CAN: Could not allocate circular buffer\n"); + return 0; + }*/ - canHandle->init = true; - canHandle->started = false; + canHandle->init = true; + canHandle->started = false; - return canHandle; + return canHandle; } int can_release(CANHandle *canHandle) { - if (!canHandle) { - LOGOMATIC("CAN: Tried to release a null handle"); - return -1; - } + if (!canHandle) { + LOGOMATIC("CAN: Tried to release a null handle"); + return -1; + } - if (!canHandle->init) { - LOGOMATIC("CAN_release: can instance is already deinitialized"); - return -1; - } - can_stop(canHandle); // try to prevent more interrupts from firing + if (!canHandle->init) { + LOGOMATIC("CAN_release: can instance is already deinitialized"); + return -1; + } + can_stop(canHandle); // try to prevent more interrupts from firing - //No more interrupts should be firing that modify canHandle + // No more interrupts should be firing that modify canHandle - can_msp_deinit(canHandle); + can_msp_deinit(canHandle); - // reset FDCANx instance and message RAM and filters, clear interrupts - // HAL_FDCAN_DeInit(canHandle->hal_fdcanP); resets a little too hard - FDCAN_InstanceDeInit(canHandle->hal_fdcanP); + // reset FDCANx instance and message RAM and filters, clear interrupts + // HAL_FDCAN_DeInit(canHandle->hal_fdcanP); resets a little too hard + FDCAN_InstanceDeInit(canHandle->hal_fdcanP); - //TODO: Not sure these actually do anything - //__DSB(); // Data Synchronization Barrier - //__ISB(); // Instruction Synchronization Barrier + // TODO: Not sure these actually do anything + //__DSB(); // Data Synchronization Barrier + //__ISB(); // Instruction Synchronization Barrier - // free circular buffer contents - //GR_CircularBuffer_Free(&(canHandle->tx_buffer)); - memset( (void*) canHandle->tx_buffer, 0, canHandle->tx_capacity*sizeof(FDCANTxMessage)); - canHandle->tx_elements = 0; - canHandle->tx_tail = 0; + // free circular buffer contents + // GR_CircularBuffer_Free(&(canHandle->tx_buffer)); + memset((void *)canHandle->tx_buffer, 0, canHandle->tx_capacity * sizeof(FDCANTxMessage)); + canHandle->tx_elements = 0; + canHandle->tx_tail = 0; - // reset can handle - memset( (void*)canHandle+sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); + // reset can handle + memset((void *)canHandle + sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); - return 0; + return 0; } -//TODO: prevent races conditions on the circular buffer -//TODO: Implement timer -//lock access to Circular Buffer when sending and dequeuing +// TODO: prevent races conditions on the circular buffer +// TODO: Implement timer +// lock access to Circular Buffer when sending and dequeuing static void can_tx_dequeue_helper(CANHandle *handle) { - if (!handle || !handle->tx_buffer) { - LOGOMATIC("can_tx_buffer_helper: handle is invalid"); - return; - } - - - //TODO: use interrupt masking in case any other ISRs need to lock the circular buffer - uint32_t basepri = __get_BASEPRI(); - - __set_BASEPRI(handle->tx_interrupt_priority); - //single consumer shouldn't affect state of circular buffer too closely - if (handle->tx_elements == 0) { - __set_BASEPRI(basepri); - return; - } + if (!handle || !handle->tx_buffer) { + LOGOMATIC("can_tx_buffer_helper: handle is invalid"); + return; + } - //uint32_t basepri = __get_basepri(); - //__disable_irq(); - //TODO: No need to lock circular buffer, as this ISR cannot interrupt the thread mode (can_send) + // TODO: use interrupt masking in case any other ISRs need to lock the circular buffer + uint32_t basepri = __get_BASEPRI(); - //Can Add to Fifo Q - if (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP)) { - //lock the Circular Buffer - FDCANTxMessage *msg = &handle->tx_buffer[handle->tx_tail]; + __set_BASEPRI(handle->tx_interrupt_priority); + // single consumer shouldn't affect state of circular buffer too closely + if (handle->tx_elements == 0) { + __set_BASEPRI(basepri); + return; + } - //should call Tx Buffer Callback once complete - HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(handle->hal_fdcanP, &msg->tx_header, msg->data); + // uint32_t basepri = __get_basepri(); + //__disable_irq(); + // TODO: No need to lock circular buffer, as this ISR cannot interrupt the thread mode (can_send) - if (status != HAL_OK) { - //LOGOMATIC("CAN_tx_helper: failed to add message to FIFO\n"); //FIXME: Logomatic may not work with interrupts disabled - __set_BASEPRI(basepri); - return; // Stop trying to send more - } - //free(msg); // Successfully sent, free the entry in the circular buffer (which is pointed to by tail) - handle->tx_tail = ++handle->tx_tail % handle->tx_capacity; - handle->tx_elements--; + // Can Add to Fifo Q + if (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP)) { + // lock the Circular Buffer + FDCANTxMessage *msg = &handle->tx_buffer[handle->tx_tail]; - } else { //FIXME: call can_tx_dequeue_helper later with a timer, if this gets implemented, need to mask timer interrupts to allow atomic access + // should call Tx Buffer Callback once complete + HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(handle->hal_fdcanP, &msg->tx_header, msg->data); - } //alternatively, if fifo is full, tx_dequeue should get called anyways, and we don't need the else statement + if (status != HAL_OK) { + // LOGOMATIC("CAN_tx_helper: failed to add message to FIFO\n"); //FIXME: Logomatic may not work with interrupts disabled + __set_BASEPRI(basepri); + return; // Stop trying to send more + } + // free(msg); // Successfully sent, free the entry in the circular buffer (which is pointed to by tail) + handle->tx_tail = ++handle->tx_tail % handle->tx_capacity; + handle->tx_elements--; - __set_BASEPRI(basepri); + } else { // FIXME: call can_tx_dequeue_helper later with a timer, if this gets implemented, need to mask timer interrupts to allow atomic access + } // alternatively, if fifo is full, tx_dequeue should get called anyways, and we don't need the else statement + __set_BASEPRI(basepri); } int can_send(CANHandle *canHandle, FDCANTxMessage *message) { - if (!canHandle || !message) { - LOGOMATIC("CAN_send: received null pointer\n"); - return -1; - } + if (!canHandle || !message) { + LOGOMATIC("CAN_send: received null pointer\n"); + return -1; + } - if (!canHandle->init || !canHandle->started) { - LOGOMATIC("CAN_send: CAN not initialized or started\n"); - return -1; - } + if (!canHandle->init || !canHandle->started) { + LOGOMATIC("CAN_send: CAN not initialized or started\n"); + return -1; + } - // IF TX Fifos are not full, send directly to them - // If TX Fifos are full, append to circular buffer - // If circular buffer is full, return an error code - - //stop can_tx_dequeue_helper from from interleaving - uint32_t basepri = __get_BASEPRI(); - __set_BASEPRI( canHandle->tx_interrupt_priority ); - - //FIXME: get rid of this jank - //if (hardwareEnabled) { - if (HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP) > 0) { - HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), message->data); - - uint32_t val = 0; - if (status != HAL_OK) { - LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); - val = -1; - } else { - val = 0; - } - __set_BASEPRI( basepri ); - return val; - } - //} - - // Hardware FIFO full, try software buffer - if (canHandle->tx_elements < canHandle->tx_capacity) { - //int result = GR_CircularBuffer_Push(canHandle->tx_buffer, message, sizeof(FDCANTxMessage)); - - uint32_t idx = (canHandle->tx_tail + canHandle->tx_elements) % canHandle->tx_capacity; - canHandle->tx_buffer[idx] = *message; - canHandle->tx_elements++; - //memcpy(&canHandle->tx_buffer[idx], message , sizeof(FDCANTxMessage) ); - - //__set_BASEPRI(primask); - - /*if (result != 0) { - LOGOMATIC("CAN_send: buffer push failed\n"); - return -1; - } else { - return 0; - }*/ - } else { - LOGOMATIC("CAN_send: all buffers full\n"); //p - } - __set_BASEPRI(basepri); - // Both buffers full - return -1; + // IF TX Fifos are not full, send directly to them + // If TX Fifos are full, append to circular buffer + // If circular buffer is full, return an error code + + // stop can_tx_dequeue_helper from from interleaving + uint32_t basepri = __get_BASEPRI(); + __set_BASEPRI(canHandle->tx_interrupt_priority); + + // FIXME: get rid of this jank + // if (hardwareEnabled) { + if (HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP) > 0) { + HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), message->data); + + uint32_t val = 0; + if (status != HAL_OK) { + LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); + val = -1; + } else { + val = 0; + } + __set_BASEPRI(basepri); + return val; + } + //} + + // Hardware FIFO full, try software buffer + if (canHandle->tx_elements < canHandle->tx_capacity) { + // int result = GR_CircularBuffer_Push(canHandle->tx_buffer, message, sizeof(FDCANTxMessage)); + + uint32_t idx = (canHandle->tx_tail + canHandle->tx_elements) % canHandle->tx_capacity; + canHandle->tx_buffer[idx] = *message; + canHandle->tx_elements++; + // memcpy(&canHandle->tx_buffer[idx], message , sizeof(FDCANTxMessage) ); + + //__set_BASEPRI(primask); + + /*if (result != 0) { + LOGOMATIC("CAN_send: buffer push failed\n"); + return -1; + } else { + return 0; + }*/ + } else { + LOGOMATIC("CAN_send: all buffers full\n"); // p + } + __set_BASEPRI(basepri); + // Both buffers full + return -1; } void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes) { - UNUSED(BufferIndexes); - // If circular buffer has elements, send to queue - // Otherwise do nothing - // #ifdef USECAN1 - CANHandle *handle = can_get_handle(hfdcan); - // see if you can pop any more from the buffer - can_tx_dequeue_helper(handle); + UNUSED(BufferIndexes); + // If circular buffer has elements, send to queue + // Otherwise do nothing + // #ifdef USECAN1 + CANHandle *handle = can_get_handle(hfdcan); + // see if you can pop any more from the buffer + can_tx_dequeue_helper(handle); } void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef *hfdcan) { - CANHandle *handle = can_get_handle(hfdcan); - can_tx_dequeue_helper(handle); + CANHandle *handle = can_get_handle(hfdcan); + can_tx_dequeue_helper(handle); } void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) { - CANHandle *handle = can_get_handle(hfdcan); + CANHandle *handle = can_get_handle(hfdcan); - if (!handle || !handle->init || !handle->rx_callback) { - return; - } + if (!handle || !handle->init || !handle->rx_callback) { + return; + } - /*if (!handle->rx_buffer) { - LOGOMATIC("CAN: RX Complete, but %s Buffer was released\n", can_get_instance_name(hfdcan->Instance)); - return; - } */ // no rx buffer at the moment + /*if (!handle->rx_buffer) { + LOGOMATIC("CAN: RX Complete, but %s Buffer was released\n", can_get_instance_name(hfdcan->Instance)); + return; + } */ // no rx buffer at the moment - if (RxFifo0ITs & FDCAN_IT_RX_FIFO0_MESSAGE_LOST) { - //lost_rx++; - } + if (RxFifo0ITs & FDCAN_IT_RX_FIFO0_MESSAGE_LOST) { + // lost_rx++; + } - if (!(RxFifo0ITs & ~FDCAN_IT_RX_FIFO0_MESSAGE_LOST)) { - return; - } + if (!(RxFifo0ITs & ~FDCAN_IT_RX_FIFO0_MESSAGE_LOST)) { + return; + } // if (GR_CircularBuffer_IsFull(handle->rx_buffer)) return; FDCAN_RxHeaderTypeDef rx_header; @@ -441,12 +435,12 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) // GR_OLD_MSG_ID messageID = (rx_header.Identifier & (0xFFF << 8)) >> 8; handle->rx_callback(rx_header.Identifier, rx_data, rx_header.DataLength); } - /* - if (GR_CircularBuffer_IsEmpty(handle->rx_buffer)) handle->rx_callback(rx_data, rx_header.DataLength); - else { - GR_CircularBuffer_Push(handle->rx_buffer, rx_data, rx_header.DataLength); - } - }*/ + /* + if (GR_CircularBuffer_IsEmpty(handle->rx_buffer)) handle->rx_callback(rx_data, rx_header.DataLength); + else { + GR_CircularBuffer_Push(handle->rx_buffer, rx_data, rx_header.DataLength); + } + }*/ //__set_BASEPRI(prev_priority); } @@ -465,255 +459,255 @@ void can_read_rx_buffer(CANHandle* canHandle) { // Just alternatively just use the HAL_FDCAN_ConfigFilter directly with the canHandle->hal_fdcan int can_add_filter(CANHandle *canHandle, FDCAN_FilterTypeDef *filter) { - if (!canHandle) { - LOGOMATIC("CAN_add_filter: handle is null"); - return -1; - } + if (!canHandle) { + LOGOMATIC("CAN_add_filter: handle is null"); + return -1; + } - if (!canHandle->init || canHandle->started) { - LOGOMATIC("CAN_add_filter: can instance is not initialized or already started"); - return -1; - } + if (!canHandle->init || canHandle->started) { + LOGOMATIC("CAN_add_filter: can instance is not initialized or already started"); + return -1; + } - if (HAL_FDCAN_ConfigFilter(canHandle->hal_fdcanP, filter) != HAL_OK) { - LOGOMATIC("CAN_add_filter: failed to configure filter"); - return -1; - } - return 0; - // check that # of filters isn't exceeding max value + if (HAL_FDCAN_ConfigFilter(canHandle->hal_fdcanP, filter) != HAL_OK) { + LOGOMATIC("CAN_add_filter: failed to configure filter"); + return -1; + } + return 0; + // check that # of filters isn't exceeding max value } int can_start(CANHandle *canHandle) { - if (!canHandle || !canHandle->init) { - return -1; - } + if (!canHandle || !canHandle->init) { + return -1; + } - if (canHandle->started) return 0; + if (canHandle->started) { + return 0; + } - IRQn_Type rx0it, txit; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); + IRQn_Type rx0it, txit; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); - HAL_NVIC_ClearPendingIRQ(rx0it); //prevent a spurious interrupt - HAL_NVIC_ClearPendingIRQ(txit); + HAL_NVIC_ClearPendingIRQ(rx0it); // prevent a spurious interrupt + HAL_NVIC_ClearPendingIRQ(txit); - GPIOx_CLK_ENABLE(canHandle->rx_gpio); - GPIOx_CLK_ENABLE(canHandle->tx_gpio); + GPIOx_CLK_ENABLE(canHandle->rx_gpio); + GPIOx_CLK_ENABLE(canHandle->tx_gpio); - HAL_FDCAN_Start(canHandle->hal_fdcanP); + HAL_FDCAN_Start(canHandle->hal_fdcanP); - canHandle->started = true; + canHandle->started = true; - HAL_NVIC_EnableIRQ(rx0it); - HAL_NVIC_EnableIRQ(txit); + HAL_NVIC_EnableIRQ(rx0it); + HAL_NVIC_EnableIRQ(txit); - return 0; + return 0; } int can_stop(CANHandle *canHandle) { - if (!canHandle || !canHandle->init) { - return -1; - } + if (!canHandle || !canHandle->init) { + return -1; + } - if (!canHandle->started) { - return 0; - } + if (!canHandle->started) { + return 0; + } - //stop can interrupts from activating - uint32_t prev_priority = __get_BASEPRI(); - __set_BASEPRI( MIN(canHandle->rx_interrupt_priority, canHandle->tx_interrupt_priority) ); + // stop can interrupts from activating + uint32_t prev_priority = __get_BASEPRI(); + __set_BASEPRI(MIN(canHandle->rx_interrupt_priority, canHandle->tx_interrupt_priority)); - HAL_FDCAN_Stop(canHandle->hal_fdcanP); + HAL_FDCAN_Stop(canHandle->hal_fdcanP); - IRQn_Type rx0it, txit; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); + IRQn_Type rx0it, txit; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); - HAL_NVIC_DisableIRQ(rx0it); - HAL_NVIC_DisableIRQ(txit); - HAL_NVIC_ClearPendingIRQ(rx0it); - HAL_NVIC_ClearPendingIRQ(txit); + HAL_NVIC_DisableIRQ(rx0it); + HAL_NVIC_DisableIRQ(txit); + HAL_NVIC_ClearPendingIRQ(rx0it); + HAL_NVIC_ClearPendingIRQ(txit); - __set_BASEPRI(prev_priority); + __set_BASEPRI(prev_priority); - GPIOx_CLK_DISABLE(canHandle->rx_gpio); - GPIOx_CLK_DISABLE(canHandle->tx_gpio); + GPIOx_CLK_DISABLE(canHandle->rx_gpio); + GPIOx_CLK_DISABLE(canHandle->tx_gpio); - canHandle->started = false; + canHandle->started = false; - return 0; + return 0; } - - - // ==================================== HELPER FUNCTIONS =============================================== -//TODO: Abstract across families +// ==================================== HELPER FUNCTIONS =============================================== +// TODO: Abstract across families static inline void fdcan_enable_shared_clock(void) { - if (fdcan_shared_clock_ref == 0) { - __HAL_RCC_FDCAN_CLK_ENABLE(); - } - fdcan_shared_clock_ref++; + if (fdcan_shared_clock_ref == 0) { + __HAL_RCC_FDCAN_CLK_ENABLE(); + } + fdcan_shared_clock_ref++; } static inline void fdcan_disable_shared_clock(void) { - if (fdcan_shared_clock_ref > 0) { - fdcan_shared_clock_ref--; - if (fdcan_shared_clock_ref == 0) { - __HAL_RCC_FDCAN_CLK_DISABLE(); - } - } + if (fdcan_shared_clock_ref > 0) { + fdcan_shared_clock_ref--; + if (fdcan_shared_clock_ref == 0) { + __HAL_RCC_FDCAN_CLK_DISABLE(); + } + } } // valid only for STM32G4 static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type *it1) { - if (instance == FDCAN1) { - *it0 = FDCAN1_IT0_IRQn; - *it1 = FDCAN1_IT1_IRQn; - return 0; - } - if (instance == FDCAN2) { - *it0 = FDCAN2_IT0_IRQn; - *it1 = FDCAN2_IT1_IRQn; - return 0; - } - if (instance == FDCAN3) { - *it0 = FDCAN3_IT0_IRQn; - *it1 = FDCAN3_IT1_IRQn; - return 0; - } + if (instance == FDCAN1) { + *it0 = FDCAN1_IT0_IRQn; + *it1 = FDCAN1_IT1_IRQn; + return 0; + } + if (instance == FDCAN2) { + *it0 = FDCAN2_IT0_IRQn; + *it1 = FDCAN2_IT1_IRQn; + return 0; + } + if (instance == FDCAN3) { + *it0 = FDCAN3_IT0_IRQn; + *it1 = FDCAN3_IT1_IRQn; + return 0; + } - return -1; // invalid instance + return -1; // invalid instance } - // valid only for STM32G4 static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan) { - // #ifdef STM32G474xx - if (hfdcan->Instance == FDCAN1) { - return &CAN1; - } else if (hfdcan->Instance == FDCAN2) { - return &CAN2; - } else if (hfdcan->Instance == FDCAN3) { - return &CAN3; - } else { - LOGOMATIC("CAN_get_handle: was given invalid FDCAN instance\n"); - return 0; - } + // #ifdef STM32G474xx + if (hfdcan->Instance == FDCAN1) { + return &CAN1; + } else if (hfdcan->Instance == FDCAN2) { + return &CAN2; + } else if (hfdcan->Instance == FDCAN3) { + return &CAN3; + } else { + LOGOMATIC("CAN_get_handle: was given invalid FDCAN instance\n"); + return 0; + } } /* static inline void gpio_clk_enable(GPIO_TypeDef *gpio) { if (gpio == GPIOA) { - __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); } else if (gpio == GPIOB) { - __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); } else if (gpio == GPIOD) { - __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); } } static inline void gpio_clk_disable(GPIO_TypeDef *gpio) { if (gpio == GPIOA) { - __HAL_RCC_GPIOA_CLK_DISABLE(); + __HAL_RCC_GPIOA_CLK_DISABLE(); } else if (gpio == GPIOB) { - __HAL_RCC_GPIOB_CLK_DISABLE(); + __HAL_RCC_GPIOB_CLK_DISABLE(); } else if (gpio == GPIOD) { - __HAL_RCC_GPIOD_CLK_DISABLE(); + __HAL_RCC_GPIOD_CLK_DISABLE(); } }*/ // only valid for #STM32G474x, must redefine for each family static int can_msp_init(CANHandle *canHandle, CANConfig *config) { - // MSP Init ------- This could be inside HAL_FDCAN_MspInit() instead - // FDCAN Clock Select + // MSP Init ------- This could be inside HAL_FDCAN_MspInit() instead + // FDCAN Clock Select - fdcan_enable_shared_clock(); + fdcan_enable_shared_clock(); - // Clock speed for FDCAN determined by APB1 clock speed and FDCAN prescaler + // Clock speed for FDCAN determined by APB1 clock speed and FDCAN prescaler - // GPIOs init - GPIOx_CLK_ENABLE(config->rx_gpio); - GPIOx_CLK_ENABLE(config->tx_gpio); + // GPIOs init + GPIOx_CLK_ENABLE(config->rx_gpio); + GPIOx_CLK_ENABLE(config->tx_gpio); - HAL_GPIO_Init(config->rx_gpio, &(config->init_rx_gpio)); - HAL_GPIO_Init(config->tx_gpio, &(config->init_tx_gpio)); + HAL_GPIO_Init(config->rx_gpio, &(config->init_rx_gpio)); + HAL_GPIO_Init(config->tx_gpio, &(config->init_tx_gpio)); - IRQn_Type rxit = -1; - IRQn_Type txit = -1; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rxit, &txit); + IRQn_Type rxit = -1; + IRQn_Type txit = -1; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rxit, &txit); - // rxfifo0 - HAL_NVIC_SetPriority(rxit, config->rx_interrupt_priority, 0); + // rxfifo0 + HAL_NVIC_SetPriority(rxit, config->rx_interrupt_priority, 0); - // tx - HAL_NVIC_SetPriority(txit, config->tx_interrupt_priority, 0); - // End MSP Init -------------- + // tx + HAL_NVIC_SetPriority(txit, config->tx_interrupt_priority, 0); + // End MSP Init -------------- - //Call can_start() to enable interrupts + // Call can_start() to enable interrupts - return 0; + return 0; } // Valid only for STM32G474xE -static int can_msp_deinit(CANHandle* canHandle) { - //MSP DeInit - // must disable NVIC IRQs before freeing circular buffer +static int can_msp_deinit(CANHandle *canHandle) +{ + // MSP DeInit + // must disable NVIC IRQs before freeing circular buffer - //NVIC - IRQn_Type rx0it = -1; - IRQn_Type txit = -1; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); - HAL_NVIC_DisableIRQ(rx0it); - HAL_NVIC_DisableIRQ(txit); + // NVIC + IRQn_Type rx0it = -1; + IRQn_Type txit = -1; + can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); + HAL_NVIC_DisableIRQ(rx0it); + HAL_NVIC_DisableIRQ(txit); - //TODO: turn off gpio clocks if no other peripherals are using them??? Could implement a shared GPIO layer - HAL_GPIO_DeInit(canHandle->rx_gpio, canHandle->rx_pin); - HAL_GPIO_DeInit(canHandle->tx_gpio, canHandle->tx_pin); + // TODO: turn off gpio clocks if no other peripherals are using them??? Could implement a shared GPIO layer + HAL_GPIO_DeInit(canHandle->rx_gpio, canHandle->rx_pin); + HAL_GPIO_DeInit(canHandle->tx_gpio, canHandle->tx_pin); - //MSP shared layer for GPIOs - //TODO: used to disable GPIOs clocks, but that might affect other peripherals + // MSP shared layer for GPIOs + // TODO: used to disable GPIOs clocks, but that might affect other peripherals - //RCC - fdcan_disable_shared_clock(); + // RCC + fdcan_disable_shared_clock(); - return 0; + return 0; } static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) { - // Enter INIT mode - hfdcan->Instance->CCCR |= FDCAN_CCCR_INIT; - while (!(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT)) - ; + // Enter INIT mode + hfdcan->Instance->CCCR |= FDCAN_CCCR_INIT; + while (!(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT)) + ; - // Disable interrupts - __HAL_FDCAN_DISABLE_IT(hfdcan, FDCAN_IT_LIST_RX_FIFO0 | FDCAN_IT_LIST_RX_FIFO1 | FDCAN_IT_LIST_SMSG | FDCAN_IT_LIST_TX_FIFO_ERROR | FDCAN_IT_LIST_MISC | FDCAN_IT_LIST_BIT_LINE_ERROR | - FDCAN_IT_LIST_PROTOCOL_ERROR); + // Disable interrupts + __HAL_FDCAN_DISABLE_IT(hfdcan, FDCAN_IT_LIST_RX_FIFO0 | FDCAN_IT_LIST_RX_FIFO1 | FDCAN_IT_LIST_SMSG | FDCAN_IT_LIST_TX_FIFO_ERROR | FDCAN_IT_LIST_MISC | FDCAN_IT_LIST_BIT_LINE_ERROR | + FDCAN_IT_LIST_PROTOCOL_ERROR); - // Clear filters - // TODO: fix magic numbers - memset((void *)hfdcan->msgRam.StandardFilterSA, 0, 0x0070); - memset((void *)hfdcan->msgRam.ExtendedFilterSA, 0, 0x0050); + // Clear filters + // TODO: fix magic numbers + memset((void *)hfdcan->msgRam.StandardFilterSA, 0, 0x0070); + memset((void *)hfdcan->msgRam.ExtendedFilterSA, 0, 0x0050); - // Optionally clear FIFOs / buffers + // Optionally clear FIFOs / buffers - // Exit INIT mode - hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT; - while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT); + // Exit INIT mode + hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT; + while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) + ; - // Update handle state - hfdcan->State = HAL_FDCAN_STATE_RESET; + // Update handle state + hfdcan->State = HAL_FDCAN_STATE_RESET; } - // valid only for STM32G4 /*static const char *can_get_instance_name(FDCAN_GlobalTypeDef *instance) { @@ -728,13 +722,31 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) }*/ // ===================================== HAL Callbacks ================================ -//TODO: Implement Family Checks -//Probably is safe from races -void FDCAN1_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); } -void FDCAN1_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan1); } +// TODO: Implement Family Checks +// Probably is safe from races +void FDCAN1_IT0_IRQHandler(void) +{ + HAL_FDCAN_IRQHandler(&hal_fdcan1); +} +void FDCAN1_IT1_IRQHandler(void) +{ + HAL_FDCAN_IRQHandler(&hal_fdcan1); +} -void FDCAN2_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); } -void FDCAN2_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan2); } +void FDCAN2_IT0_IRQHandler(void) +{ + HAL_FDCAN_IRQHandler(&hal_fdcan2); +} +void FDCAN2_IT1_IRQHandler(void) +{ + HAL_FDCAN_IRQHandler(&hal_fdcan2); +} -void FDCAN3_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); } -void FDCAN3_IT1_IRQHandler(void) { HAL_FDCAN_IRQHandler(&hal_fdcan3); } +void FDCAN3_IT0_IRQHandler(void) +{ + HAL_FDCAN_IRQHandler(&hal_fdcan3); +} +void FDCAN3_IT1_IRQHandler(void) +{ + HAL_FDCAN_IRQHandler(&hal_fdcan3); +} diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 53909eda9..d8310f065 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -28,7 +28,7 @@ void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) return; } -//TODO: G4 tests are dependent on the System clock configuration +// TODO: G4 tests are dependent on the System clock configuration int can_test(void) { CANConfig canCfg; From 9581d92cf2d010cd66c74d39224b2b7684e430dc Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Thu, 5 Mar 2026 02:35:10 -0800 Subject: [PATCH 18/44] Co-authored-by: Aagrim Hoysal --- CCU/Application/Src/CANDler.c | 2 +- DashPanel/Application/Src/CANdler.c | 2 +- Lib/Peripherals/CAN/Inc/can.h | 2 +- Lib/Peripherals/CAN/Src/can.c | 98 ++++++++++++++----- Lib/Peripherals/CAN/Test/can_tests.c | 141 +++++++++++++++++++++------ Lib/Peripherals/CAN/Test/can_tests.h | 5 + 6 files changed, 188 insertions(+), 62 deletions(-) diff --git a/CCU/Application/Src/CANDler.c b/CCU/Application/Src/CANDler.c index 80f6ae415..8c8230a9c 100644 --- a/CCU/Application/Src/CANDler.c +++ b/CCU/Application/Src/CANDler.c @@ -85,7 +85,7 @@ void CAN_Configure(void) canCfg.rx_callback = Read_CAN; canCfg.rx_interrupt_priority = 15; // TODO: Maybe make these not hardcoded canCfg.tx_interrupt_priority = 15; - canCfg.tx_buffer_length = 5; + //canCfg.tx_buffer_length = 5; // RX shared settings canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; diff --git a/DashPanel/Application/Src/CANdler.c b/DashPanel/Application/Src/CANdler.c index 900e1068b..008c11877 100644 --- a/DashPanel/Application/Src/CANdler.c +++ b/DashPanel/Application/Src/CANdler.c @@ -44,7 +44,7 @@ void CANInitialize() canCfg.rx_callback = CAN_callback; // PLEASE SET canCfg.rx_interrupt_priority = 0; // PLEASE SET canCfg.tx_interrupt_priority = 0; // PLEASE SET - canCfg.tx_buffer_length = 3; // PLEASE SET + //canCfg.tx_buffer_length = 3; // PLEASE SET canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index dbdae9863..f2d0ad538 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -49,7 +49,7 @@ typedef struct { FDCAN_HandleTypeDef *hal_fdcanP; // DO NOT REORDER THIS // TX buffer - volatile FDCANTxMessage *tx_buffer; + FDCANTxMessage * const tx_buffer; volatile uint32_t tx_capacity; volatile uint32_t tx_tail; volatile uint32_t tx_elements; diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 4de7d6c87..a435a50c0 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -7,27 +7,40 @@ #include "Logomatic.h" +//TODO: Figure out how to move these defines into the application code (by linking) + +//#define USECAN2 +//#define TX_BUFFER_2_SIZE 10 +//#define USECAN3 +//#define TX_BUFFER_3_SIZE 10 + // HAL handles -// #ifdef USECAN1 -#define TX_BUFFER_1_SIZE 3 +#ifdef USECAN1 +#ifndef TX_BUFFER_1_SIZE +#error "Please Define TX_BUFFER_1_SIZE" +#endif static FDCAN_HandleTypeDef hal_fdcan1 = {.Instance = FDCAN1}; FDCANTxMessage tx_buffer_1[TX_BUFFER_1_SIZE] = {0}; static CANHandle CAN1 = {.hal_fdcanP = &hal_fdcan1, .tx_buffer = tx_buffer_1}; -// #endif +#endif -// #ifdef USECAN2 -#define TX_BUFFER_2_SIZE 3 +#ifdef USECAN2 +#ifndef TX_BUFFER_2_SIZE +#error "Please Define TX_BUFFER_2_SIZE" +#endif static FDCAN_HandleTypeDef hal_fdcan2 = {.Instance = FDCAN2}; FDCANTxMessage tx_buffer_2[TX_BUFFER_2_SIZE] = {0}; static CANHandle CAN2 = {.hal_fdcanP = &hal_fdcan2, .tx_buffer = tx_buffer_2}; -// #endif +#endif -// #ifdef USECAN3 -#define TX_BUFFER_3_SIZE 3 +#ifdef USECAN3 +#ifndef TX_BUFFER_3_SIZE +#error "Please Define TX_BUFFER_3_SIZE" +#endif static FDCAN_HandleTypeDef hal_fdcan3 = {.Instance = FDCAN3}; FDCANTxMessage tx_buffer_3[TX_BUFFER_3_SIZE] = {0}; static CANHandle CAN3 = {.hal_fdcanP = &hal_fdcan3, .tx_buffer = tx_buffer_3}; -// #endif +#endif #define MIN(A, B) ((A < B) ? A : B) @@ -110,7 +123,7 @@ CANHandle *can_init(const CANConfig *config) // #ifdef STM32G474xx CANHandle *canHandle = 0; - // #ifdef USECAN1 + #ifdef USECAN1 if (config->fdcan_instance == FDCAN1) { if (CAN1.init) { LOGOMATIC("CAN: CAN1 is already initialized\n"); @@ -120,9 +133,9 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_capacity = TX_BUFFER_1_SIZE; } } - // #endif - // #ifdef USECAN2 - else if (config->fdcan_instance == FDCAN2) { + #endif + #ifdef USECAN2 + if (config->fdcan_instance == FDCAN2) { if (CAN2.init) { LOGOMATIC("CAN: CAN2 is already initialized\n"); return 0; @@ -131,8 +144,10 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_capacity = TX_BUFFER_2_SIZE; } } - // #ifdef USECAN3 - else if (config->fdcan_instance == FDCAN3) { + #endif + + #ifdef USECAN3 + if (config->fdcan_instance == FDCAN3) { if (CAN3.init) { LOGOMATIC("CAN: CAN3 is already initialized\n"); return 0; @@ -141,12 +156,12 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_capacity = TX_BUFFER_3_SIZE; } } - // #endif + #endif // #elif defined(STM32L476xx) // #else // #error "Unsupported STM32 family" // #endif - else { + if (canHandle == 0) { LOGOMATIC("CAN: Unrecognized FDCAN instance"); return 0; } @@ -298,7 +313,7 @@ static void can_tx_dequeue_helper(CANHandle *handle) // Can Add to Fifo Q if (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP)) { // lock the Circular Buffer - FDCANTxMessage *msg = &handle->tx_buffer[handle->tx_tail]; + const FDCANTxMessage *msg = &(handle->tx_buffer[handle->tx_tail]); // should call Tx Buffer Callback once complete HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(handle->hal_fdcanP, &msg->tx_header, msg->data); @@ -365,7 +380,8 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) canHandle->tx_elements++; // memcpy(&canHandle->tx_buffer[idx], message , sizeof(FDCANTxMessage) ); - //__set_BASEPRI(primask); + __set_BASEPRI(basepri); + return 0; // added to software buffer /*if (result != 0) { LOGOMATIC("CAN_send: buffer push failed\n"); @@ -488,7 +504,11 @@ int can_start(CANHandle *canHandle) } IRQn_Type rx0it, txit; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); + rx0it = txit = -1; //TOOD: Check that this is a valid way to initialize an invalid value + if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { + LOGOMATIC("can_start: could not obtain irq #s"); + return -1; + } HAL_NVIC_ClearPendingIRQ(rx0it); // prevent a spurious interrupt HAL_NVIC_ClearPendingIRQ(txit); @@ -523,8 +543,11 @@ int can_stop(CANHandle *canHandle) HAL_FDCAN_Stop(canHandle->hal_fdcanP); IRQn_Type rx0it, txit; - can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit); - + rx0it = txit = -1; //TODO: Check that this initialization is valid + if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit) ) { + LOGOMATIC("can_start: could not obtain irq #s"); + return -1; + } HAL_NVIC_DisableIRQ(rx0it); HAL_NVIC_DisableIRQ(txit); HAL_NVIC_ClearPendingIRQ(rx0it); @@ -587,16 +610,25 @@ static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan) { // #ifdef STM32G474xx + #ifdef USECAN1 if (hfdcan->Instance == FDCAN1) { return &CAN1; - } else if (hfdcan->Instance == FDCAN2) { + } + #endif + #ifdef USECAN2 + if (hfdcan->Instance == FDCAN2) { return &CAN2; - } else if (hfdcan->Instance == FDCAN3) { + } + #endif + #ifdef USECAN3 + if (hfdcan->Instance == FDCAN3) { return &CAN3; - } else { - LOGOMATIC("CAN_get_handle: was given invalid FDCAN instance\n"); - return 0; } + #endif + + LOGOMATIC("CAN_get_handle: was given invalid FDCAN instance\n"); + UNUSED(hfdcan); + return 0; } /* @@ -726,27 +758,39 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) // Probably is safe from races void FDCAN1_IT0_IRQHandler(void) { + #ifdef USECAN1 HAL_FDCAN_IRQHandler(&hal_fdcan1); + #endif } void FDCAN1_IT1_IRQHandler(void) { + #ifdef USECAN1 HAL_FDCAN_IRQHandler(&hal_fdcan1); + #endif } void FDCAN2_IT0_IRQHandler(void) { + #ifdef USECAN2 HAL_FDCAN_IRQHandler(&hal_fdcan2); + #endif } void FDCAN2_IT1_IRQHandler(void) { + #ifdef USECAN2 HAL_FDCAN_IRQHandler(&hal_fdcan2); + #endif } void FDCAN3_IT0_IRQHandler(void) { + #ifdef USECAN3 HAL_FDCAN_IRQHandler(&hal_fdcan3); + #endif } void FDCAN3_IT1_IRQHandler(void) { + #ifdef USECAN3 HAL_FDCAN_IRQHandler(&hal_fdcan3); + #endif } diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index d8310f065..651ba5c82 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -28,8 +28,7 @@ void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) return; } -// TODO: G4 tests are dependent on the System clock configuration -int can_test(void) +int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, CANHandle** primary_can_out, CANHandle** data_can_out) { CANConfig canCfg; // canCfg.fdcan_instance = FDCAN2; @@ -76,27 +75,7 @@ int can_test(void) // can_add_filter(data_can, &filter); /* USER CODE END 2 */ - FDCAN_TxHeaderTypeDef TxHeader = { - .Identifier = 1, - - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node - // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors - .DataLength = 1, - .BitRateSwitch = FDCAN_BRS_OFF, - .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages - .MessageMarker = 0 // also change this to a real address if you change fifo control - }; - - FDCANTxMessage msg; - memset(&(msg.data), 0, sizeof(msg.data)); - msg.data[0] = 0x80; - msg.tx_header = TxHeader; - - can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); - -#ifdef FDCAN1 +#ifdef USECAN1 canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; canCfg.init_rx_gpio.Pin = GPIO_PIN_11; @@ -106,15 +85,18 @@ int can_test(void) canCfg.init_tx_gpio.Pin = GPIO_PIN_12; canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN1; - canCfg.rx_callback = can_test_rx_callback1; // PLEASE SET + canCfg.rx_callback = primary_callback; // PLEASE SET CANHandle *primary_can = can_init(&canCfg); + if (primary_can == NULL) return -1; + *primary_can_out = primary_can; + HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); can_start(primary_can); #endif -#ifdef FDCAN2 +#ifdef USECAN2 canCfg.fdcan_instance = FDCAN2; canCfg.rx_gpio = GPIOB; canCfg.init_rx_gpio.Pin = GPIO_PIN_12; @@ -124,7 +106,7 @@ int can_test(void) canCfg.init_tx_gpio.Pin = GPIO_PIN_13; canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; - canCfg.rx_callback = can_test_rx_callback2; + canCfg.rx_callback = data_callback; // FDCAN_FilterTypeDef filter; // filter.IdType = FDCAN_STANDARD_ID; @@ -135,9 +117,11 @@ int can_test(void) // filter.FilterID2 = 0x02; CANHandle *data_can = can_init(&canCfg); + if (data_can == NULL) return ERROR; + *data_can_out = data_can; // accept unmatched standard and extended frames into RXFIFO0 - default behaviour - HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); + if (HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0) != HAL_OK) return ERROR; // not accepting filters // can_add_filter(data_can, &filter); @@ -145,16 +129,45 @@ int can_test(void) // API Testing // can_init(&canCfg); - can_start(data_can); - - can_send(data_can, &msg); + if (can_start(data_can)) return ERROR; // can_release(data_can); #endif -#ifdef FDCAN3 - +#ifdef USECAN3 #endif + return SUCCESS; +} + +//TODO - allow user to send data without needing to construct a header for the buffer +// TODO: G4 tests are dependent on the System clock configuration +int can_test(void) +{ + FDCAN_TxHeaderTypeDef TxHeader = { + .Identifier = 1, + + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + + CANHandle *primary_can, *data_can; + primary_can = data_can = NULL; + + if (defaultCANCfg(can_test_rx_callback1, can_test_rx_callback2, &primary_can, &data_can)) { + LOGOMATIC("Could not initialize and start both can buses"); + return ERROR; + } + + FDCANTxMessage msg = {0}; + msg.data[0] = 0x80; + msg.tx_header = TxHeader; + while (1) { HAL_Delay(1000); msg.data[0] = 0x2; @@ -166,3 +179,67 @@ int can_test(void) return 0; } + +static int can_stress_test_received = 0; +void can_stress_test_rx_callback(uint32_t id, void *data, uint32_t size) +{ + can_stress_test_received++; + UNUSED(id); + UNUSED(data); + UNUSED(size); + return; +} + +int can_stress_test(void) +{ + int status, i, loop; + UNUSED(status); + + status = loop = 0; + + CANHandle *primary_can, *data_can; + primary_can = data_can = NULL; + + defaultCANCfg(can_stress_test_rx_callback, NULL, &primary_can, &data_can); + + FDCAN_TxHeaderTypeDef TxHeader = { + .Identifier = 1, + + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + + FDCANTxMessage msg; + memset(&(msg.data), 0, sizeof(msg.data)); + msg.data[0] = 0x80; + msg.tx_header = TxHeader; + + while (1) { + loop++; + can_stress_test_received = 0; + i = 0; + while (i < 100) { + if (can_send(primary_can, &msg) != 0) { + LOGOMATIC("Stress test failed sending CAN msg at %d-th consecutive send.\n", i+1); + break; + } + i++; + } + LOGOMATIC("Sent %d CAN msgs...\n", i); + HAL_Delay(1000); + + LOGOMATIC("Received %d/%d CAN msgs after 1 second.\n", can_stress_test_received,i); + msg.data[0] = 0x10; + can_send(data_can, &msg); + HAL_Delay(1000); + LOGOMATIC("Stress test finished loop %d\n", loop); + } + + return 0; +} diff --git a/Lib/Peripherals/CAN/Test/can_tests.h b/Lib/Peripherals/CAN/Test/can_tests.h index 17985c045..892f9660b 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.h +++ b/Lib/Peripherals/CAN/Test/can_tests.h @@ -7,6 +7,11 @@ // Tested STM32 Families #ifdef STM32G4 +#define USECAN1 +#define TX_BUFFER_2_SIZE 10 +#define USECAN2 +#define TX_BUFFER_3_SIZE 10 + // #elif defined(STM32L4) // #elif defined(STM32U5) #else From e91fba1102d6e7459fa4a668ae6fad1dc401dc1a Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 10:42:45 +0000 Subject: [PATCH 19/44] Automatic Clang-Format: Standardized formatting automatically --- CCU/Application/Src/CANDler.c | 2 +- DashPanel/Application/Src/CANdler.c | 2 +- Lib/Peripherals/CAN/Inc/can.h | 2 +- Lib/Peripherals/CAN/Src/can.c | 66 ++++++++++++++-------------- Lib/Peripherals/CAN/Test/can_tests.c | 30 ++++++++----- 5 files changed, 55 insertions(+), 47 deletions(-) diff --git a/CCU/Application/Src/CANDler.c b/CCU/Application/Src/CANDler.c index 8c8230a9c..3b359d822 100644 --- a/CCU/Application/Src/CANDler.c +++ b/CCU/Application/Src/CANDler.c @@ -85,7 +85,7 @@ void CAN_Configure(void) canCfg.rx_callback = Read_CAN; canCfg.rx_interrupt_priority = 15; // TODO: Maybe make these not hardcoded canCfg.tx_interrupt_priority = 15; - //canCfg.tx_buffer_length = 5; + // canCfg.tx_buffer_length = 5; // RX shared settings canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; diff --git a/DashPanel/Application/Src/CANdler.c b/DashPanel/Application/Src/CANdler.c index 008c11877..14d5642d4 100644 --- a/DashPanel/Application/Src/CANdler.c +++ b/DashPanel/Application/Src/CANdler.c @@ -44,7 +44,7 @@ void CANInitialize() canCfg.rx_callback = CAN_callback; // PLEASE SET canCfg.rx_interrupt_priority = 0; // PLEASE SET canCfg.tx_interrupt_priority = 0; // PLEASE SET - //canCfg.tx_buffer_length = 3; // PLEASE SET + // canCfg.tx_buffer_length = 3; // PLEASE SET canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index f2d0ad538..c1cf132a5 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -49,7 +49,7 @@ typedef struct { FDCAN_HandleTypeDef *hal_fdcanP; // DO NOT REORDER THIS // TX buffer - FDCANTxMessage * const tx_buffer; + FDCANTxMessage *const tx_buffer; volatile uint32_t tx_capacity; volatile uint32_t tx_tail; volatile uint32_t tx_elements; diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index a435a50c0..bb04707d6 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -7,12 +7,12 @@ #include "Logomatic.h" -//TODO: Figure out how to move these defines into the application code (by linking) +// TODO: Figure out how to move these defines into the application code (by linking) -//#define USECAN2 -//#define TX_BUFFER_2_SIZE 10 -//#define USECAN3 -//#define TX_BUFFER_3_SIZE 10 +// #define USECAN2 +// #define TX_BUFFER_2_SIZE 10 +// #define USECAN3 +// #define TX_BUFFER_3_SIZE 10 // HAL handles #ifdef USECAN1 @@ -123,7 +123,7 @@ CANHandle *can_init(const CANConfig *config) // #ifdef STM32G474xx CANHandle *canHandle = 0; - #ifdef USECAN1 +#ifdef USECAN1 if (config->fdcan_instance == FDCAN1) { if (CAN1.init) { LOGOMATIC("CAN: CAN1 is already initialized\n"); @@ -133,8 +133,8 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_capacity = TX_BUFFER_1_SIZE; } } - #endif - #ifdef USECAN2 +#endif +#ifdef USECAN2 if (config->fdcan_instance == FDCAN2) { if (CAN2.init) { LOGOMATIC("CAN: CAN2 is already initialized\n"); @@ -144,9 +144,9 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_capacity = TX_BUFFER_2_SIZE; } } - #endif +#endif - #ifdef USECAN3 +#ifdef USECAN3 if (config->fdcan_instance == FDCAN3) { if (CAN3.init) { LOGOMATIC("CAN: CAN3 is already initialized\n"); @@ -156,7 +156,7 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_capacity = TX_BUFFER_3_SIZE; } } - #endif +#endif // #elif defined(STM32L476xx) // #else // #error "Unsupported STM32 family" @@ -504,7 +504,7 @@ int can_start(CANHandle *canHandle) } IRQn_Type rx0it, txit; - rx0it = txit = -1; //TOOD: Check that this is a valid way to initialize an invalid value + rx0it = txit = -1; // TOOD: Check that this is a valid way to initialize an invalid value if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { LOGOMATIC("can_start: could not obtain irq #s"); return -1; @@ -543,8 +543,8 @@ int can_stop(CANHandle *canHandle) HAL_FDCAN_Stop(canHandle->hal_fdcanP); IRQn_Type rx0it, txit; - rx0it = txit = -1; //TODO: Check that this initialization is valid - if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit) ) { + rx0it = txit = -1; // TODO: Check that this initialization is valid + if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { LOGOMATIC("can_start: could not obtain irq #s"); return -1; } @@ -609,22 +609,22 @@ static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type // valid only for STM32G4 static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan) { - // #ifdef STM32G474xx - #ifdef USECAN1 +// #ifdef STM32G474xx +#ifdef USECAN1 if (hfdcan->Instance == FDCAN1) { return &CAN1; } - #endif - #ifdef USECAN2 +#endif +#ifdef USECAN2 if (hfdcan->Instance == FDCAN2) { return &CAN2; } - #endif - #ifdef USECAN3 +#endif +#ifdef USECAN3 if (hfdcan->Instance == FDCAN3) { return &CAN3; } - #endif +#endif LOGOMATIC("CAN_get_handle: was given invalid FDCAN instance\n"); UNUSED(hfdcan); @@ -758,39 +758,39 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) // Probably is safe from races void FDCAN1_IT0_IRQHandler(void) { - #ifdef USECAN1 +#ifdef USECAN1 HAL_FDCAN_IRQHandler(&hal_fdcan1); - #endif +#endif } void FDCAN1_IT1_IRQHandler(void) { - #ifdef USECAN1 +#ifdef USECAN1 HAL_FDCAN_IRQHandler(&hal_fdcan1); - #endif +#endif } void FDCAN2_IT0_IRQHandler(void) { - #ifdef USECAN2 +#ifdef USECAN2 HAL_FDCAN_IRQHandler(&hal_fdcan2); - #endif +#endif } void FDCAN2_IT1_IRQHandler(void) { - #ifdef USECAN2 +#ifdef USECAN2 HAL_FDCAN_IRQHandler(&hal_fdcan2); - #endif +#endif } void FDCAN3_IT0_IRQHandler(void) { - #ifdef USECAN3 +#ifdef USECAN3 HAL_FDCAN_IRQHandler(&hal_fdcan3); - #endif +#endif } void FDCAN3_IT1_IRQHandler(void) { - #ifdef USECAN3 +#ifdef USECAN3 HAL_FDCAN_IRQHandler(&hal_fdcan3); - #endif +#endif } diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c index 651ba5c82..ac3aa0474 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ b/Lib/Peripherals/CAN/Test/can_tests.c @@ -28,7 +28,7 @@ void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) return; } -int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, CANHandle** primary_can_out, CANHandle** data_can_out) +int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, CANHandle **primary_can_out, CANHandle **data_can_out) { CANConfig canCfg; // canCfg.fdcan_instance = FDCAN2; @@ -88,7 +88,9 @@ int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, canCfg.rx_callback = primary_callback; // PLEASE SET CANHandle *primary_can = can_init(&canCfg); - if (primary_can == NULL) return -1; + if (primary_can == NULL) { + return -1; + } *primary_can_out = primary_can; HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); @@ -117,11 +119,15 @@ int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, // filter.FilterID2 = 0x02; CANHandle *data_can = can_init(&canCfg); - if (data_can == NULL) return ERROR; + if (data_can == NULL) { + return ERROR; + } *data_can_out = data_can; // accept unmatched standard and extended frames into RXFIFO0 - default behaviour - if (HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0) != HAL_OK) return ERROR; + if (HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0) != HAL_OK) { + return ERROR; + } // not accepting filters // can_add_filter(data_can, &filter); @@ -129,7 +135,9 @@ int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, // API Testing // can_init(&canCfg); - if (can_start(data_can)) return ERROR; + if (can_start(data_can)) { + return ERROR; + } // can_release(data_can); #endif @@ -139,8 +147,8 @@ int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, return SUCCESS; } -//TODO - allow user to send data without needing to construct a header for the buffer -// TODO: G4 tests are dependent on the System clock configuration +// TODO - allow user to send data without needing to construct a header for the buffer +// TODO: G4 tests are dependent on the System clock configuration int can_test(void) { FDCAN_TxHeaderTypeDef TxHeader = { @@ -156,7 +164,7 @@ int can_test(void) .MessageMarker = 0 // also change this to a real address if you change fifo control }; - CANHandle *primary_can, *data_can; + CANHandle *primary_can, *data_can; primary_can = data_can = NULL; if (defaultCANCfg(can_test_rx_callback1, can_test_rx_callback2, &primary_can, &data_can)) { @@ -197,7 +205,7 @@ int can_stress_test(void) status = loop = 0; - CANHandle *primary_can, *data_can; + CANHandle *primary_can, *data_can; primary_can = data_can = NULL; defaultCANCfg(can_stress_test_rx_callback, NULL, &primary_can, &data_can); @@ -226,7 +234,7 @@ int can_stress_test(void) i = 0; while (i < 100) { if (can_send(primary_can, &msg) != 0) { - LOGOMATIC("Stress test failed sending CAN msg at %d-th consecutive send.\n", i+1); + LOGOMATIC("Stress test failed sending CAN msg at %d-th consecutive send.\n", i + 1); break; } i++; @@ -234,7 +242,7 @@ int can_stress_test(void) LOGOMATIC("Sent %d CAN msgs...\n", i); HAL_Delay(1000); - LOGOMATIC("Received %d/%d CAN msgs after 1 second.\n", can_stress_test_received,i); + LOGOMATIC("Received %d/%d CAN msgs after 1 second.\n", can_stress_test_received, i); msg.data[0] = 0x10; can_send(data_can, &msg); HAL_Delay(1000); From 5e91ea8c15fa9ca5a0e9a0ffce7ea314bcc1f937 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Tue, 10 Mar 2026 00:24:49 -0700 Subject: [PATCH 20/44] new tests --- CMakeLists.txt | 15 +- G4CANTESTING/CMakeLists.txt | 53 ---- G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt | 61 +++++ G4CANTESTING/EXTERNAL_TEST/main.c | 274 +++++++++++++++++++ G4CANTESTING/INTERNAL_TEST/CMakeLists.txt | 61 +++++ G4CANTESTING/INTERNAL_TEST/main.c | 274 +++++++++++++++++++ G4CANTESTING/RELEASE_TEST/CMakeLists.txt | 61 +++++ G4CANTESTING/RELEASE_TEST/main.c | 274 +++++++++++++++++++ G4CANTESTING/STRESS_TEST/CMakeLists.txt | 53 ++++ G4CANTESTING/STRESS_TEST/main.c | 274 +++++++++++++++++++ Lib/Peripherals/CAN/Inc/can.h | 12 +- Lib/Peripherals/CAN/Src/can.c | 99 ++++--- Lib/Peripherals/CAN/Test/can_external_test.c | 115 ++++++++ Lib/Peripherals/CAN/Test/can_filter_test.c | 6 + Lib/Peripherals/CAN/Test/can_init_test.c | 20 ++ Lib/Peripherals/CAN/Test/can_internal_test.c | 115 ++++++++ Lib/Peripherals/CAN/Test/can_release_test.c | 15 + Lib/Peripherals/CAN/Test/can_stress_test.c | 86 ++++++ Lib/Peripherals/CAN/Test/can_test_helpers.c | 100 +++++++ Lib/Peripherals/CAN/Test/can_tests.c | 253 ----------------- Lib/Peripherals/CAN/Test/can_tests.h | 17 +- Lib/Peripherals/CAN/common.cmake | 13 +- 22 files changed, 1886 insertions(+), 365 deletions(-) create mode 100644 G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt create mode 100644 G4CANTESTING/EXTERNAL_TEST/main.c create mode 100644 G4CANTESTING/INTERNAL_TEST/CMakeLists.txt create mode 100644 G4CANTESTING/INTERNAL_TEST/main.c create mode 100644 G4CANTESTING/RELEASE_TEST/CMakeLists.txt create mode 100644 G4CANTESTING/RELEASE_TEST/main.c create mode 100644 G4CANTESTING/STRESS_TEST/CMakeLists.txt create mode 100644 G4CANTESTING/STRESS_TEST/main.c create mode 100644 Lib/Peripherals/CAN/Test/can_external_test.c create mode 100644 Lib/Peripherals/CAN/Test/can_filter_test.c create mode 100644 Lib/Peripherals/CAN/Test/can_init_test.c create mode 100644 Lib/Peripherals/CAN/Test/can_internal_test.c create mode 100644 Lib/Peripherals/CAN/Test/can_release_test.c create mode 100644 Lib/Peripherals/CAN/Test/can_stress_test.c create mode 100644 Lib/Peripherals/CAN/Test/can_test_helpers.c delete mode 100644 Lib/Peripherals/CAN/Test/can_tests.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 97e977d0b..22abe40c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,20 @@ add_gr_project(STM32G474xE CANine) # Development add_gr_project(STM32G474xE G4ADCTESTING) add_gr_project(STM32G474xE G4PERTESTING) -add_gr_project(STM32G474xE G4CANTESTING) +#add_gr_project(STM32G474xE G4CANTESTING) + +#CAN Peripheral Testing +#add_gr_project(STM32G474xE G4CANTESTING FILTER_TEST) +add_gr_project(STM32G474xE G4CANTESTING EXTERNAL_TEST) +add_gr_project(STM32G474xE G4CANTESTING INTERNAL_TEST) +#add_gr_project(STM32G474xE G4CANTESTING INIT_TEST) +add_gr_project(STM32G474xE G4CANTESTING RELEASE_TEST) +add_gr_project(STM32G474xE G4CANTESTING STRESS_TEST) + + +add_gr_project(STM32G474xE G4CANTESTING ) +#add_gr_project(STM32G474xE G4CANTESTING) + add_gr_project(STM32G474xE G4NEOTESTING) # BLINKY Demos diff --git a/G4CANTESTING/CMakeLists.txt b/G4CANTESTING/CMakeLists.txt index e1961b557..e69de29bb 100644 --- a/G4CANTESTING/CMakeLists.txt +++ b/G4CANTESTING/CMakeLists.txt @@ -1,53 +0,0 @@ -cmake_minimum_required(VERSION 3.25) - -# Setup compiler settings -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS ON) - -# Define the build type -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Debug") -endif() - -# Enable compile command to ease indexing with e.g. clangd -set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) - -# Enable CMake support for ASM and C languages -enable_language( - C - ASM -) - -# Core project settings -project(${CMAKE_PROJECT_NAME}) - -# what, does in fact not get the filename of somthing but rather the name of the project from the path -get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) - -add_library(${PROJECT_NAME}_USER_CODE INTERFACE) - -target_sources( - ${PROJECT_NAME}_USER_CODE - INTERFACE - Core/Src/adc.c - Core/Src/crc.c - Core/Src/dma.c - Core/Src/gpio.c - Core/Src/i2c.c - Core/Src/main.c - Core/Src/spi.c - Core/Src/stm32g4xx_hal_msp.c - Core/Src/stm32g4xx_it.c - Core/Src/tim.c - Core/Src/usart.c -) - -target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_link_libraries( - ${PROJECT_NAME}_USER_CODE - INTERFACE - PERIPHERAL_CAN_TEST_LIB -) - -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) diff --git a/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt new file mode 100644 index 000000000..b55f44091 --- /dev/null +++ b/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 3.25) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Enable CMake support for ASM and C languages +enable_language( + C + ASM +) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) + +# what, does in fact not get the filename of somthing but rather the name of the project from the path +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +add_library(${PROJECT_NAME}_USER_CODE INTERFACE) + +target_sources( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Src/adc.c + ../Core/Src/crc.c + ../Core/Src/dma.c + ../Core/Src/gpio.c + ../Core/Src/i2c.c + ../Core/Src/main.c + ../Core/Src/spi.c + ../Core/Src/stm32g4xx_hal_msp.c + ../Core/Src/stm32g4xx_it.c + ../Core/Src/tim.c + ../Core/Src/usart.c +) + + +if(FILTER EQUAL 1) +message(HERE) +target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) +else() +message(THERE) +endif() + + +target_link_libraries( + ${PROJECT_NAME}_USER_CODE + INTERFACE + PERIPHERAL_CAN_LIB +) + +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) diff --git a/G4CANTESTING/EXTERNAL_TEST/main.c b/G4CANTESTING/EXTERNAL_TEST/main.c new file mode 100644 index 000000000..5ac60cf41 --- /dev/null +++ b/G4CANTESTING/EXTERNAL_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + LOGOMATIC("running can_external_test:\n"); + can_external_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt new file mode 100644 index 000000000..b55f44091 --- /dev/null +++ b/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 3.25) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Enable CMake support for ASM and C languages +enable_language( + C + ASM +) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) + +# what, does in fact not get the filename of somthing but rather the name of the project from the path +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +add_library(${PROJECT_NAME}_USER_CODE INTERFACE) + +target_sources( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Src/adc.c + ../Core/Src/crc.c + ../Core/Src/dma.c + ../Core/Src/gpio.c + ../Core/Src/i2c.c + ../Core/Src/main.c + ../Core/Src/spi.c + ../Core/Src/stm32g4xx_hal_msp.c + ../Core/Src/stm32g4xx_it.c + ../Core/Src/tim.c + ../Core/Src/usart.c +) + + +if(FILTER EQUAL 1) +message(HERE) +target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) +else() +message(THERE) +endif() + + +target_link_libraries( + ${PROJECT_NAME}_USER_CODE + INTERFACE + PERIPHERAL_CAN_LIB +) + +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) diff --git a/G4CANTESTING/INTERNAL_TEST/main.c b/G4CANTESTING/INTERNAL_TEST/main.c new file mode 100644 index 000000000..1d09082e2 --- /dev/null +++ b/G4CANTESTING/INTERNAL_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + LOGOMATIC("running can_internal_test:\n"); + can_internal_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/RELEASE_TEST/CMakeLists.txt b/G4CANTESTING/RELEASE_TEST/CMakeLists.txt new file mode 100644 index 000000000..b55f44091 --- /dev/null +++ b/G4CANTESTING/RELEASE_TEST/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 3.25) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Enable CMake support for ASM and C languages +enable_language( + C + ASM +) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) + +# what, does in fact not get the filename of somthing but rather the name of the project from the path +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +add_library(${PROJECT_NAME}_USER_CODE INTERFACE) + +target_sources( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Src/adc.c + ../Core/Src/crc.c + ../Core/Src/dma.c + ../Core/Src/gpio.c + ../Core/Src/i2c.c + ../Core/Src/main.c + ../Core/Src/spi.c + ../Core/Src/stm32g4xx_hal_msp.c + ../Core/Src/stm32g4xx_it.c + ../Core/Src/tim.c + ../Core/Src/usart.c +) + + +if(FILTER EQUAL 1) +message(HERE) +target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) +else() +message(THERE) +endif() + + +target_link_libraries( + ${PROJECT_NAME}_USER_CODE + INTERFACE + PERIPHERAL_CAN_LIB +) + +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) diff --git a/G4CANTESTING/RELEASE_TEST/main.c b/G4CANTESTING/RELEASE_TEST/main.c new file mode 100644 index 000000000..22219a044 --- /dev/null +++ b/G4CANTESTING/RELEASE_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + LOGOMATIC("running can_release_test:\n"); + can_release_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/STRESS_TEST/CMakeLists.txt b/G4CANTESTING/STRESS_TEST/CMakeLists.txt new file mode 100644 index 000000000..f3637d8ad --- /dev/null +++ b/G4CANTESTING/STRESS_TEST/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.25) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Enable CMake support for ASM and C languages +enable_language( + C + ASM +) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) + +# what, does in fact not get the filename of somthing but rather the name of the project from the path +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +add_library(${PROJECT_NAME}_USER_CODE INTERFACE) + +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE /Users/vihan/Documents/Gaucho_Racing/Firmware/Firmware/G4CANTESTING/Core/Inc) + +target_sources( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Src/adc.c + ../Core/Src/crc.c + ../Core/Src/dma.c + ../Core/Src/gpio.c + ../Core/Src/i2c.c + ../Core/Src/main.c + ../Core/Src/spi.c + ../Core/Src/stm32g4xx_hal_msp.c + ../Core/Src/stm32g4xx_it.c + ../Core/Src/tim.c + ../Core/Src/usart.c +) + + +target_link_libraries( + ${PROJECT_NAME}_USER_CODE + INTERFACE + PERIPHERAL_CAN_LIB +) diff --git a/G4CANTESTING/STRESS_TEST/main.c b/G4CANTESTING/STRESS_TEST/main.c new file mode 100644 index 000000000..964b7d405 --- /dev/null +++ b/G4CANTESTING/STRESS_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + LOGOMATIC("running can_stress_test:\n"); + can_stress_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index c1cf132a5..d392ec9d3 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -46,7 +46,7 @@ typedef struct { // FDCAN peripheral for STM32G4 typedef struct { - FDCAN_HandleTypeDef *hal_fdcanP; // DO NOT REORDER THIS + FDCAN_HandleTypeDef *hal_fdcanP; // TX buffer FDCANTxMessage *const tx_buffer; @@ -74,6 +74,11 @@ typedef struct { // error states } CANHandle; +typedef enum { + CAN_SUCCESS, + CAN_ERROR +} CAN_STATUS; + CANHandle *can_init(const CANConfig *config); // user must supply an rx callback function int can_start(CANHandle *handle); int can_stop(CANHandle *handle); @@ -87,4 +92,9 @@ int can_add_filter(CANHandle *handle, FDCAN_FilterTypeDef *filter); // doesn't need a handle, CAN cores share peripheral clock void can_set_clksource(uint32_t clksource); // ex. LL_RCC_FDCAN_CLKSOURCE_PCLK1 for STM32G474RE +//TODO: Add thread mode vs handler mode checking (None of these functions should be called in handler mode) + +//TODO: put this somewhere that someone will read it +//Somewhere in your application, define USECAN1 and TX_BUFFER_1_SIZE + #endif // End Header Guard diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index bb04707d6..9e7deced2 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -122,12 +122,12 @@ CANHandle *can_init(const CANConfig *config) // assert(config != 0) // #ifdef STM32G474xx - CANHandle *canHandle = 0; + CANHandle *canHandle = NULL; #ifdef USECAN1 if (config->fdcan_instance == FDCAN1) { if (CAN1.init) { LOGOMATIC("CAN: CAN1 is already initialized\n"); - return 0; + return CAN_SUCCESS; } else { canHandle = &CAN1; canHandle->tx_capacity = TX_BUFFER_1_SIZE; @@ -138,7 +138,7 @@ CANHandle *can_init(const CANConfig *config) if (config->fdcan_instance == FDCAN2) { if (CAN2.init) { LOGOMATIC("CAN: CAN2 is already initialized\n"); - return 0; + return CAN_SUCCESS; } else { canHandle = &CAN2; canHandle->tx_capacity = TX_BUFFER_2_SIZE; @@ -150,7 +150,7 @@ CANHandle *can_init(const CANConfig *config) if (config->fdcan_instance == FDCAN3) { if (CAN3.init) { LOGOMATIC("CAN: CAN3 is already initialized\n"); - return 0; + return CAN_SUCCESS; } else { canHandle = &CAN3; canHandle->tx_capacity = TX_BUFFER_3_SIZE; @@ -161,9 +161,9 @@ CANHandle *can_init(const CANConfig *config) // #else // #error "Unsupported STM32 family" // #endif - if (canHandle == 0) { + if (canHandle == NULL) { LOGOMATIC("CAN: Unrecognized FDCAN instance"); - return 0; + return CAN_SUCCESS; } canHandle->init = false; canHandle->started = false; @@ -192,16 +192,18 @@ CANHandle *can_init(const CANConfig *config) // have can_msp_deinit setup state for HAL_FDCAN_MspDeInit to work correctly // Then call HAL_FDCAN_Init() and HAL_FDCAN_DeInit() - // Current idea, redefine HAL_FDCAN_MspInit and MspDeInit do nothing at all, do all the work in can_msp_init() + // Current idea, redefine HAL_FDCAN_MspInit and MspDeInit to do nothing at all, do all the work in can_msp_init() uint32_t failure = 0; if (failure |= (can_msp_init(canHandle, (CANConfig *)config))) { LOGOMATIC("CAN_init: could not initialize MSP resources"); + return 0; } // PROBLEM: HAL_FDCAN_Init expects HAL_FDCAN_MspInit() to be defined if (HAL_FDCAN_Init(canHandle->hal_fdcanP) != HAL_OK) { failure |= HAL_ERROR; LOGOMATIC("CAN: HAL Could not initialize FDCAN peripheral"); + return 0; // Error_Handler(); } @@ -236,12 +238,12 @@ CANHandle *can_init(const CANConfig *config) can_msp_deinit(canHandle); FDCAN_InstanceDeInit(canHandle->hal_fdcanP); memset(canHandle + sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); // FIXME: Make sure instance is not being overwritten (FDCANx) - return 0; + return CAN_SUCCESS; } /*if (!canHandle->tx_buffer) { LOGOMATIC("CAN: Could not allocate circular buffer\n"); - return 0; + return CAN_SUCCESS; }*/ canHandle->init = true; @@ -254,18 +256,23 @@ int can_release(CANHandle *canHandle) { if (!canHandle) { LOGOMATIC("CAN: Tried to release a null handle"); - return -1; + return CAN_ERROR; } if (!canHandle->init) { LOGOMATIC("CAN_release: can instance is already deinitialized"); - return -1; + return CAN_ERROR; + } + if (can_stop(canHandle)) {// try to prevent more interrupts from firing + LOGOMATIC("CAN_release: could not stop instance"); + return CAN_ERROR; } - can_stop(canHandle); // try to prevent more interrupts from firing // No more interrupts should be firing that modify canHandle - - can_msp_deinit(canHandle); + if (can_msp_deinit(canHandle)) { + LOGOMATIC("CAN_release: could not stop instance"); + return CAN_ERROR; + } // reset FDCANx instance and message RAM and filters, clear interrupts // HAL_FDCAN_DeInit(canHandle->hal_fdcanP); resets a little too hard @@ -277,14 +284,16 @@ int can_release(CANHandle *canHandle) // free circular buffer contents // GR_CircularBuffer_Free(&(canHandle->tx_buffer)); - memset((void *)canHandle->tx_buffer, 0, canHandle->tx_capacity * sizeof(FDCANTxMessage)); + memset((void *)canHandle->tx_buffer, 0, canHandle->tx_capacity * sizeof(canHandle->tx_buffer[0])); canHandle->tx_elements = 0; canHandle->tx_tail = 0; // reset can handle - memset((void *)canHandle + sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); + FDCAN_HandleTypeDef *temp = canHandle->hal_fdcanP; + memset(canHandle, 0, sizeof(*canHandle)); + canHandle->hal_fdcanP = temp; - return 0; + return CAN_SUCCESS; } // TODO: prevent races conditions on the circular buffer // TODO: Implement timer @@ -338,12 +347,12 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) { if (!canHandle || !message) { LOGOMATIC("CAN_send: received null pointer\n"); - return -1; + return CAN_ERROR; } if (!canHandle->init || !canHandle->started) { LOGOMATIC("CAN_send: CAN not initialized or started\n"); - return -1; + return CAN_ERROR; } // IF TX Fifos are not full, send directly to them @@ -362,9 +371,9 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) uint32_t val = 0; if (status != HAL_OK) { LOGOMATIC("CAN_send: failed to add to HW FIFO\n"); - val = -1; + val = CAN_ERROR; } else { - val = 0; + val = CAN_SUCCESS; } __set_BASEPRI(basepri); return val; @@ -381,20 +390,20 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) // memcpy(&canHandle->tx_buffer[idx], message , sizeof(FDCANTxMessage) ); __set_BASEPRI(basepri); - return 0; // added to software buffer + return CAN_SUCCESS; // added to software buffer /*if (result != 0) { LOGOMATIC("CAN_send: buffer push failed\n"); - return -1; + return CAN_ERROR; } else { - return 0; + return CAN_SUCCESS; }*/ } else { LOGOMATIC("CAN_send: all buffers full\n"); // p } __set_BASEPRI(basepri); // Both buffers full - return -1; + return CAN_ERROR; } void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes) @@ -477,37 +486,37 @@ int can_add_filter(CANHandle *canHandle, FDCAN_FilterTypeDef *filter) { if (!canHandle) { LOGOMATIC("CAN_add_filter: handle is null"); - return -1; + return CAN_ERROR; } if (!canHandle->init || canHandle->started) { LOGOMATIC("CAN_add_filter: can instance is not initialized or already started"); - return -1; + return CAN_ERROR; } if (HAL_FDCAN_ConfigFilter(canHandle->hal_fdcanP, filter) != HAL_OK) { LOGOMATIC("CAN_add_filter: failed to configure filter"); - return -1; + return CAN_ERROR; } - return 0; + return CAN_SUCCESS; // check that # of filters isn't exceeding max value } int can_start(CANHandle *canHandle) { if (!canHandle || !canHandle->init) { - return -1; + return CAN_ERROR; } if (canHandle->started) { - return 0; + return CAN_SUCCESS; } IRQn_Type rx0it, txit; rx0it = txit = -1; // TOOD: Check that this is a valid way to initialize an invalid value if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { LOGOMATIC("can_start: could not obtain irq #s"); - return -1; + return CAN_ERROR; } HAL_NVIC_ClearPendingIRQ(rx0it); // prevent a spurious interrupt @@ -523,17 +532,17 @@ int can_start(CANHandle *canHandle) HAL_NVIC_EnableIRQ(rx0it); HAL_NVIC_EnableIRQ(txit); - return 0; + return CAN_SUCCESS; } int can_stop(CANHandle *canHandle) { if (!canHandle || !canHandle->init) { - return -1; + return CAN_ERROR; } if (!canHandle->started) { - return 0; + return CAN_SUCCESS; } // stop can interrupts from activating @@ -545,8 +554,8 @@ int can_stop(CANHandle *canHandle) IRQn_Type rx0it, txit; rx0it = txit = -1; // TODO: Check that this initialization is valid if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { - LOGOMATIC("can_start: could not obtain irq #s"); - return -1; + LOGOMATIC("can_stop: could not obtain irq #s"); + return CAN_ERROR; } HAL_NVIC_DisableIRQ(rx0it); HAL_NVIC_DisableIRQ(txit); @@ -560,7 +569,7 @@ int can_stop(CANHandle *canHandle) canHandle->started = false; - return 0; + return CAN_SUCCESS; } // ==================================== HELPER FUNCTIONS =============================================== @@ -590,20 +599,20 @@ static int can_get_irqs(FDCAN_GlobalTypeDef *instance, IRQn_Type *it0, IRQn_Type if (instance == FDCAN1) { *it0 = FDCAN1_IT0_IRQn; *it1 = FDCAN1_IT1_IRQn; - return 0; + return CAN_SUCCESS; } if (instance == FDCAN2) { *it0 = FDCAN2_IT0_IRQn; *it1 = FDCAN2_IT1_IRQn; - return 0; + return CAN_SUCCESS; } if (instance == FDCAN3) { *it0 = FDCAN3_IT0_IRQn; *it1 = FDCAN3_IT1_IRQn; - return 0; + return CAN_SUCCESS; } - return -1; // invalid instance + return CAN_ERROR; // invalid instance } // valid only for STM32G4 @@ -628,7 +637,7 @@ static CANHandle *can_get_handle(FDCAN_HandleTypeDef *hfdcan) LOGOMATIC("CAN_get_handle: was given invalid FDCAN instance\n"); UNUSED(hfdcan); - return 0; + return CAN_SUCCESS; } /* @@ -684,7 +693,7 @@ static int can_msp_init(CANHandle *canHandle, CANConfig *config) // Call can_start() to enable interrupts - return 0; + return CAN_SUCCESS; } // Valid only for STM32G474xE @@ -710,7 +719,7 @@ static int can_msp_deinit(CANHandle *canHandle) // RCC fdcan_disable_shared_clock(); - return 0; + return CAN_SUCCESS; } static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) diff --git a/Lib/Peripherals/CAN/Test/can_external_test.c b/Lib/Peripherals/CAN/Test/can_external_test.c new file mode 100644 index 000000000..d004b0d0e --- /dev/null +++ b/Lib/Peripherals/CAN/Test/can_external_test.c @@ -0,0 +1,115 @@ +#include "can_tests.h" + +#include +#include + +#include "can.h" + +// each family has a constant number of CAN peripherals + +/*int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) +{ + //can_init(fdcan_handle); + UNUSED(fdcan_handle); + return 0; +}*/ + +//TODO: Make creating these callbacks a macro, rather than defining each one separately +static volatile int rx_2_received = 0; +void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) +{ + rx_2_received++; + LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); + // Is within an ISR, so needs to exit quickly + return; +} + +static volatile int rx_1_received = 0; +void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) +{ + rx_1_received++; + LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); + + // Is within an ISR, so needs to exit quickly + return; +} + +// TODO - allow user to send data without needing to construct a header for the buffer +// TODO: G4 tests are dependent on the System clock configuration?? +int can_external_test(void) +{ + FDCAN_TxHeaderTypeDef TxHeader = { + .Identifier = 1, + + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + + CANHandle *primary_can = 0, *data_can = 0; + primary_can = data_can = NULL; + CANConfig cfg1, cfg2; + + LOGOMATIC("Initializing primary and data CAN Bus in Normal mode.\n"); + if (get_cfg(FDCAN1, can_test_rx_callback1, &cfg1, FDCAN_MODE_NORMAL)) { + LOGOMATIC("Could not get config for FDCAN1\n"); + return ERROR; + } + if (get_cfg(FDCAN2, can_test_rx_callback2, &cfg2, FDCAN_MODE_NORMAL)) { + LOGOMATIC("Could not get config for FDCAN2\n"); + return ERROR; + } + + //============================================================================================= + if ( (primary_can = can_init(&cfg1)) == NULL) { + LOGOMATIC("Could not initialize primary_can\n"); + return ERROR; + } + HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); + + if ((data_can = can_init(&cfg2)) == NULL) { + LOGOMATIC("Could not initialize data_can\n"); + return ERROR; + } + HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); + + //============================================================================================= + if (can_start(primary_can)) { + LOGOMATIC("Could not start primary_can\n"); + return ERROR; + } + if (can_start(data_can)) { + LOGOMATIC("Could not start data_can\n"); + return ERROR; + } + + FDCANTxMessage msg = {0}; + msg.data[0] = 0x80; + msg.tx_header = TxHeader; + + uint32_t i = 0; + uint32_t num_messages = 5; + + LOGOMATIC("Sending %ld messages on each bus...\n",num_messages); + while (i < num_messages) { + HAL_Delay(1000); + msg.data[0] = 0x2; + can_send(primary_can, &msg); + HAL_Delay(1000); + msg.data[0] = 0x10; + can_send(data_can, &msg); + i += 1; + } + LOGOMATIC("Received %d messages on bus1...\n",rx_1_received); + LOGOMATIC("Received %d messages on bus2...\n",rx_2_received); + + if (can_release(primary_can)) LOGOMATIC("can_test; could not release primary_can\n"); + if (can_release(data_can)) LOGOMATIC("can_test; could not release data_can\n"); + + return SUCCESS; +} diff --git a/Lib/Peripherals/CAN/Test/can_filter_test.c b/Lib/Peripherals/CAN/Test/can_filter_test.c new file mode 100644 index 000000000..813492423 --- /dev/null +++ b/Lib/Peripherals/CAN/Test/can_filter_test.c @@ -0,0 +1,6 @@ +#include "can_tests.h" + + + + +//TODO: diff --git a/Lib/Peripherals/CAN/Test/can_init_test.c b/Lib/Peripherals/CAN/Test/can_init_test.c new file mode 100644 index 000000000..4ab0ad583 --- /dev/null +++ b/Lib/Peripherals/CAN/Test/can_init_test.c @@ -0,0 +1,20 @@ +#include "can_tests.h" +#include "can.h" + + +//TODO: +int can_init_test(CANConfig * cfg) { + CANHandle *handle; + if ( (handle = can_init(cfg)) == NULL) { + LOGOMATIC("can_init_test: init failed\n"); + return ERROR; + } + + //inspect handle + if (!handle->init) { + LOGOMATIC("can_init_test: did not set init bool in handle\n"); + return ERROR; + } + + return SUCCESS; +} diff --git a/Lib/Peripherals/CAN/Test/can_internal_test.c b/Lib/Peripherals/CAN/Test/can_internal_test.c new file mode 100644 index 000000000..9bb4e065d --- /dev/null +++ b/Lib/Peripherals/CAN/Test/can_internal_test.c @@ -0,0 +1,115 @@ +#include "can_tests.h" + +#include +#include + +#include "can.h" + +// each family has a constant number of CAN peripherals + +/*int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) +{ + //can_init(fdcan_handle); + UNUSED(fdcan_handle); + return 0; +}*/ + +//TODO: Make creating these callbacks a macro, rather than defining each one separately +static volatile int rx_2_received = 0; +void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) +{ + rx_2_received++; + LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); + // Is within an ISR, so needs to exit quickly + return; +} + +static volatile int rx_1_received = 0; +void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) +{ + rx_1_received++; + LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); + + // Is within an ISR, so needs to exit quickly + return; +} + +// TODO - allow user to send data without needing to construct a header for the buffer +// TODO: G4 tests are dependent on the System clock configuration?? +int can_external_test(void) +{ + FDCAN_TxHeaderTypeDef TxHeader = { + .Identifier = 1, + + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + + CANHandle *primary_can = 0, *data_can = 0; + primary_can = data_can = NULL; + CANConfig cfg1, cfg2; + + LOGOMATIC("Initializing primary and data CAN Bus in Normal mode.\n"); + if (get_cfg(FDCAN1, can_test_rx_callback1, &cfg1, FDCAN_MODE_INTERNAL_LOOPBACK)) { + LOGOMATIC("Could not get config for FDCAN1\n"); + return ERROR; + } + if (get_cfg(FDCAN2, can_test_rx_callback2, &cfg2, FDCAN_MODE_INTERNAL_LOOPBACK)) { + LOGOMATIC("Could not get config for FDCAN2\n"); + return ERROR; + } + + //============================================================================================= + if ( (primary_can = can_init(&cfg1)) == NULL) { + LOGOMATIC("Could not initialize primary_can\n"); + return ERROR; + } + HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); + + if ((data_can = can_init(&cfg2)) == NULL) { + LOGOMATIC("Could not initialize data_can\n"); + return ERROR; + } + HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); + + //============================================================================================= + if (can_start(primary_can)) { + LOGOMATIC("Could not start primary_can\n"); + return ERROR; + } + if (can_start(data_can)) { + LOGOMATIC("Could not start data_can\n"); + return ERROR; + } + + FDCANTxMessage msg = {0}; + msg.data[0] = 0x80; + msg.tx_header = TxHeader; + + uint32_t i = 0; + uint32_t num_messages = 5; + + LOGOMATIC("Sending %ld messages on each bus...\n",num_messages); + while (i < num_messages) { + HAL_Delay(1000); + msg.data[0] = 0x2; + can_send(primary_can, &msg); + HAL_Delay(1000); + msg.data[0] = 0x10; + can_send(data_can, &msg); + i += 1; + } + LOGOMATIC("Received %d messages on bus1...\n",rx_1_received); + LOGOMATIC("Received %d messages on bus2...\n",rx_2_received); + + if (can_release(primary_can)) LOGOMATIC("can_test; could not release primary_can\n"); + if (can_release(data_can)) LOGOMATIC("can_test; could not release data_can\n"); + + return SUCCESS; +} diff --git a/Lib/Peripherals/CAN/Test/can_release_test.c b/Lib/Peripherals/CAN/Test/can_release_test.c new file mode 100644 index 000000000..c9ea03b4d --- /dev/null +++ b/Lib/Peripherals/CAN/Test/can_release_test.c @@ -0,0 +1,15 @@ +#include "can_tests.h" +#include "can.h" + +//TODO: +int can_release_test(CANHandle * handle) { + if (handle == NULL) {return ERROR;} + + FDCAN_HandleTypeDef * hal_instance = handle->hal_fdcanP; + + if (can_release(handle)) LOGOMATIC("can_test; could not release primary_can\n"); + + if (hal_instance != canHandle->hal_fdcanP) { LOGOMATIC("can_release_test; did not reset CAN handle correctly\n"); return ERROR;} + + return SUCCESS; +} diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c new file mode 100644 index 000000000..0871e1bbe --- /dev/null +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -0,0 +1,86 @@ +#include "can.h" +#include "can_tests.h" +#include + + +//TODO: +static volatile uint32_t can_stress_test_received = 0; +void can_stress_test_rx_callback(uint32_t id, void *data, uint32_t size) +{ + can_stress_test_received++; + UNUSED(id); + UNUSED(data); + UNUSED(size); + return; +} + +int can_stress_test(void) +{ + uint32_t status, loop; + UNUSED(status); + + status = loop = 0; + + CANHandle *primary_can, *data_can; + primary_can = data_can = NULL; + CANConfig cfg1; + + if (get_cfg(FDCAN1, can_stress_test_rx_callback, &cfg1, FDCAN_MODE_INTERNAL_LOOPBACK)) { + LOGOMATIC("Could not get config for FDCAN1\n"); + return ERROR; + } + + FDCAN_TxHeaderTypeDef TxHeader = { + .Identifier = 1, + + .IdType = FDCAN_STANDARD_ID, + .TxFrameType = FDCAN_DATA_FRAME, + .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node + // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors + .DataLength = 1, + .BitRateSwitch = FDCAN_BRS_OFF, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages + .MessageMarker = 0 // also change this to a real address if you change fifo control + }; + + if ( (primary_can = can_init(&cfg1)) == NULL) { + LOGOMATIC("Could not initialize primary_can\n"); + return ERROR; + } + if (can_start(primary_can)) { + LOGOMATIC("Could not start primary_can\n"); + return ERROR; + } + + FDCANTxMessage msg; + memset(&(msg.data), 0, sizeof(msg.data)); + msg.data[0] = 0x80; + msg.tx_header = TxHeader; + + size_t i = 0; + size_t messages = 5; + while (i < messages) { + loop++; + can_stress_test_received = 0; + i = 0; + while (i < 100) { + if (can_send(primary_can, &msg) != 0) { + LOGOMATIC("Stress test failed sending CAN msg at %ud-th consecutive send.\n", (unsigned int) i + 1); + break; + } + i++; + } + LOGOMATIC("Sent %ud CAN msgs...\n", (unsigned int)i); + HAL_Delay(1000); + + LOGOMATIC("Received %ud/%ud CAN msgs after 1 second.\n", (unsigned int)can_stress_test_received, (unsigned int) i); + msg.data[0] = 0x10; + can_send(data_can, &msg); + HAL_Delay(1000); + LOGOMATIC("Stress test finished loop %ld\n", loop); + } + + if (can_release(primary_can)) LOGOMATIC("can_test; could not release primary_can\n"); + + return SUCCESS; +} diff --git a/Lib/Peripherals/CAN/Test/can_test_helpers.c b/Lib/Peripherals/CAN/Test/can_test_helpers.c new file mode 100644 index 000000000..56d20e71d --- /dev/null +++ b/Lib/Peripherals/CAN/Test/can_test_helpers.c @@ -0,0 +1,100 @@ +#include "can_tests.h" +#include "can.h" + +int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode) { + #ifdef STM32G4 + return defaultSTM32G4_CANCfg(instance, callback, out_cfg,Mode); + #elif defined(STM32L4) + #elif defined(STM32U5) + #error "STM32U5 is untested"#else + #else + #error "Untested STM32 Family" + #endif +} + +//TODO: Abstract out the system clock calculation +//Abstracts out everything but the mode and callback +int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef* instance , CAN_RXCallback callback, CANConfig * out_cfg, uint32_t Mode) +{ + CANConfig canCfg; + // canCfg.fdcan_instance = FDCAN2; + + canCfg.hal_fdcan_init.ClockDivider = FDCAN_CLOCK_DIV1; + canCfg.hal_fdcan_init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; + canCfg.hal_fdcan_init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; + canCfg.hal_fdcan_init.Mode = Mode; + canCfg.hal_fdcan_init.AutoRetransmission = ENABLE; + canCfg.hal_fdcan_init.TransmitPause = DISABLE; + canCfg.hal_fdcan_init.ProtocolException = ENABLE; + canCfg.hal_fdcan_init.NominalPrescaler = 1; + canCfg.hal_fdcan_init.NominalSyncJumpWidth = 16; + canCfg.hal_fdcan_init.NominalTimeSeg1 = 127; // Updated for 170MHz: (1+127+42)*1 = 170 ticks -> 1 Mbps + canCfg.hal_fdcan_init.NominalTimeSeg2 = 42; + canCfg.hal_fdcan_init.DataPrescaler = 8; + canCfg.hal_fdcan_init.DataSyncJumpWidth = 16; + canCfg.hal_fdcan_init.DataTimeSeg1 = 15; // Updated for 170MHz: (1+15+5)*8 = 168 ticks -> ~5 Mbps + canCfg.hal_fdcan_init.DataTimeSeg2 = 5; + canCfg.hal_fdcan_init.StdFiltersNbr = 1; + canCfg.hal_fdcan_init.ExtFiltersNbr = 0; + + canCfg.rx_callback = NULL; // PLEASE SET + canCfg.rx_interrupt_priority = 14; // PLEASE SET + canCfg.tx_interrupt_priority = 14; // PLEASE SET + + // canCfg.rx_gpio = GPIOB; + // canCfg.init_rx_gpio.Pin = GPIO_PIN_12; + canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; + canCfg.init_rx_gpio.Pull = GPIO_PULLUP; + canCfg.init_rx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + // canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN2; + + // canCfg.tx_gpio = GPIOB; + // canCfg.init_tx_gpio.Pin = GPIO_PIN_13; + canCfg.init_tx_gpio.Mode = GPIO_MODE_AF_PP; + canCfg.init_tx_gpio.Pull = GPIO_NOPULL; + canCfg.init_tx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + // canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; + + // Not testing filters at the moment + // FDCAN_FilterTypeDef filter; + + // can_add_filter(data_can, &filter); + /* USER CODE END 2 */ + + canCfg.rx_callback = callback; + + if (instance == FDCAN1){ + canCfg.fdcan_instance = FDCAN1; + canCfg.rx_gpio = GPIOA; + canCfg.init_rx_gpio.Pin = GPIO_PIN_11; + canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN1; + + canCfg.tx_gpio = GPIOA; + canCfg.init_tx_gpio.Pin = GPIO_PIN_12; + canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN1; + + *out_cfg = canCfg; + return SUCCESS; + } + +#ifdef USECAN2 + if (instance == FDCAN2) { + canCfg.fdcan_instance = FDCAN2; + canCfg.rx_gpio = GPIOB; + canCfg.init_rx_gpio.Pin = GPIO_PIN_12; + canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN2; + + canCfg.tx_gpio = GPIOB; + canCfg.init_tx_gpio.Pin = GPIO_PIN_13; + canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; + + *out_cfg = canCfg; + return SUCCESS; + } +#endif + +#ifdef USECAN3 +#endif + + return ERROR; +} diff --git a/Lib/Peripherals/CAN/Test/can_tests.c b/Lib/Peripherals/CAN/Test/can_tests.c deleted file mode 100644 index ac3aa0474..000000000 --- a/Lib/Peripherals/CAN/Test/can_tests.c +++ /dev/null @@ -1,253 +0,0 @@ -#include "can_tests.h" - -#include -#include - -#include "can.h" - -// each family has a constant number of CAN peripherals - -int can_test_instance(FDCAN_HandleTypeDef fdcan_handle) -{ - UNUSED(fdcan_handle); - return 0; -} - -void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) -{ - LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); - // Is within an ISR, so needs to exit quickly - return; -} - -void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) -{ - LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); - - // Is within an ISR, so needs to exit quickly - return; -} - -int defaultCANCfg(CAN_RXCallback primary_callback, CAN_RXCallback data_callback, CANHandle **primary_can_out, CANHandle **data_can_out) -{ - CANConfig canCfg; - // canCfg.fdcan_instance = FDCAN2; - - canCfg.hal_fdcan_init.ClockDivider = FDCAN_CLOCK_DIV1; - canCfg.hal_fdcan_init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; - canCfg.hal_fdcan_init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; - canCfg.hal_fdcan_init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK; - canCfg.hal_fdcan_init.AutoRetransmission = ENABLE; - canCfg.hal_fdcan_init.TransmitPause = DISABLE; - canCfg.hal_fdcan_init.ProtocolException = ENABLE; - canCfg.hal_fdcan_init.NominalPrescaler = 1; - canCfg.hal_fdcan_init.NominalSyncJumpWidth = 16; - canCfg.hal_fdcan_init.NominalTimeSeg1 = 127; // Updated for 170MHz: (1+127+42)*1 = 170 ticks -> 1 Mbps - canCfg.hal_fdcan_init.NominalTimeSeg2 = 42; - canCfg.hal_fdcan_init.DataPrescaler = 8; - canCfg.hal_fdcan_init.DataSyncJumpWidth = 16; - canCfg.hal_fdcan_init.DataTimeSeg1 = 15; // Updated for 170MHz: (1+15+5)*8 = 168 ticks -> ~5 Mbps - canCfg.hal_fdcan_init.DataTimeSeg2 = 5; - canCfg.hal_fdcan_init.StdFiltersNbr = 1; - canCfg.hal_fdcan_init.ExtFiltersNbr = 0; - - canCfg.rx_callback = NULL; // PLEASE SET - canCfg.rx_interrupt_priority = 5; // PLEASE SET - canCfg.tx_interrupt_priority = 5; // PLEASE SET - - // canCfg.rx_gpio = GPIOB; - // canCfg.init_rx_gpio.Pin = GPIO_PIN_12; - canCfg.init_rx_gpio.Mode = GPIO_MODE_AF_PP; - canCfg.init_rx_gpio.Pull = GPIO_PULLUP; - canCfg.init_rx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - // canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN2; - - // canCfg.tx_gpio = GPIOB; - // canCfg.init_tx_gpio.Pin = GPIO_PIN_13; - canCfg.init_tx_gpio.Mode = GPIO_MODE_AF_PP; - canCfg.init_tx_gpio.Pull = GPIO_NOPULL; - canCfg.init_tx_gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - // canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; - - // Not testing filters at the moment - // FDCAN_FilterTypeDef filter; - - // can_add_filter(data_can, &filter); - /* USER CODE END 2 */ - -#ifdef USECAN1 - canCfg.fdcan_instance = FDCAN1; - canCfg.rx_gpio = GPIOA; - canCfg.init_rx_gpio.Pin = GPIO_PIN_11; - canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN1; - - canCfg.tx_gpio = GPIOA; - canCfg.init_tx_gpio.Pin = GPIO_PIN_12; - canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN1; - - canCfg.rx_callback = primary_callback; // PLEASE SET - - CANHandle *primary_can = can_init(&canCfg); - if (primary_can == NULL) { - return -1; - } - *primary_can_out = primary_can; - - HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); - - can_start(primary_can); - -#endif -#ifdef USECAN2 - canCfg.fdcan_instance = FDCAN2; - canCfg.rx_gpio = GPIOB; - canCfg.init_rx_gpio.Pin = GPIO_PIN_12; - canCfg.init_rx_gpio.Alternate = GPIO_AF9_FDCAN2; - - canCfg.tx_gpio = GPIOB; - canCfg.init_tx_gpio.Pin = GPIO_PIN_13; - canCfg.init_tx_gpio.Alternate = GPIO_AF9_FDCAN2; - - canCfg.rx_callback = data_callback; - - // FDCAN_FilterTypeDef filter; - // filter.IdType = FDCAN_STANDARD_ID; - // filter.FilterIndex = 0; - // filter.FilterType = FDCAN_FILTER_RANGE, - // filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; - // filter.FilterID1 = 0x00; - // filter.FilterID2 = 0x02; - - CANHandle *data_can = can_init(&canCfg); - if (data_can == NULL) { - return ERROR; - } - *data_can_out = data_can; - - // accept unmatched standard and extended frames into RXFIFO0 - default behaviour - if (HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0) != HAL_OK) { - return ERROR; - } - - // not accepting filters - // can_add_filter(data_can, &filter); - - // API Testing - // can_init(&canCfg); - - if (can_start(data_can)) { - return ERROR; - } - // can_release(data_can); - -#endif -#ifdef USECAN3 -#endif - - return SUCCESS; -} - -// TODO - allow user to send data without needing to construct a header for the buffer -// TODO: G4 tests are dependent on the System clock configuration -int can_test(void) -{ - FDCAN_TxHeaderTypeDef TxHeader = { - .Identifier = 1, - - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node - // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors - .DataLength = 1, - .BitRateSwitch = FDCAN_BRS_OFF, - .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages - .MessageMarker = 0 // also change this to a real address if you change fifo control - }; - - CANHandle *primary_can, *data_can; - primary_can = data_can = NULL; - - if (defaultCANCfg(can_test_rx_callback1, can_test_rx_callback2, &primary_can, &data_can)) { - LOGOMATIC("Could not initialize and start both can buses"); - return ERROR; - } - - FDCANTxMessage msg = {0}; - msg.data[0] = 0x80; - msg.tx_header = TxHeader; - - while (1) { - HAL_Delay(1000); - msg.data[0] = 0x2; - can_send(primary_can, &msg); - HAL_Delay(1000); - msg.data[0] = 0x10; - can_send(data_can, &msg); - } - - return 0; -} - -static int can_stress_test_received = 0; -void can_stress_test_rx_callback(uint32_t id, void *data, uint32_t size) -{ - can_stress_test_received++; - UNUSED(id); - UNUSED(data); - UNUSED(size); - return; -} - -int can_stress_test(void) -{ - int status, i, loop; - UNUSED(status); - - status = loop = 0; - - CANHandle *primary_can, *data_can; - primary_can = data_can = NULL; - - defaultCANCfg(can_stress_test_rx_callback, NULL, &primary_can, &data_can); - - FDCAN_TxHeaderTypeDef TxHeader = { - .Identifier = 1, - - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, // honestly this might be a value you have to read from a node - // FDCAN_ESI_ACTIVE is just a state that assumes there are minimal errors - .DataLength = 1, - .BitRateSwitch = FDCAN_BRS_OFF, - .TxEventFifoControl = FDCAN_NO_TX_EVENTS, // change to FDCAN_STORE_TX_EVENTS if you need to store info regarding transmitted messages - .MessageMarker = 0 // also change this to a real address if you change fifo control - }; - - FDCANTxMessage msg; - memset(&(msg.data), 0, sizeof(msg.data)); - msg.data[0] = 0x80; - msg.tx_header = TxHeader; - - while (1) { - loop++; - can_stress_test_received = 0; - i = 0; - while (i < 100) { - if (can_send(primary_can, &msg) != 0) { - LOGOMATIC("Stress test failed sending CAN msg at %d-th consecutive send.\n", i + 1); - break; - } - i++; - } - LOGOMATIC("Sent %d CAN msgs...\n", i); - HAL_Delay(1000); - - LOGOMATIC("Received %d/%d CAN msgs after 1 second.\n", can_stress_test_received, i); - msg.data[0] = 0x10; - can_send(data_can, &msg); - HAL_Delay(1000); - LOGOMATIC("Stress test finished loop %d\n", loop); - } - - return 0; -} diff --git a/Lib/Peripherals/CAN/Test/can_tests.h b/Lib/Peripherals/CAN/Test/can_tests.h index 892f9660b..9668c0fda 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.h +++ b/Lib/Peripherals/CAN/Test/can_tests.h @@ -6,19 +6,20 @@ #include "can_platform_deps.h" // Tested STM32 Families -#ifdef STM32G4 #define USECAN1 #define TX_BUFFER_2_SIZE 10 #define USECAN2 #define TX_BUFFER_3_SIZE 10 -// #elif defined(STM32L4) -// #elif defined(STM32U5) -#else -#error "Untested STM32 Family" -#endif +//abstract families +extern int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); +extern int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); + -// Assume the LOGOMATIC is setup correctly -int can_test(void); // top-level function, just call this and check if the return status is correct +//testing functions +extern int can_external_test(void); +extern int can_internal_test(void); +extern int can_stress_test(void); +extern int can_release_test(CANHandle * handle); #endif diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 120a4dcbe..76fceee70 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -1,6 +1,6 @@ add_library(PERIPHERAL_CAN_LIB INTERFACE) -target_link_libraries(PERIPHERAL_CAN_LIB INTERFACE CircularBuffer_Lib) +target_link_libraries(PERIPHERAL_CAN_LIB INTERFACE PERIPHERAL_CAN_TEST_LIB CircularBuffer_Lib) target_sources(PERIPHERAL_CAN_LIB INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Src/can.c) @@ -16,7 +16,12 @@ add_library(PERIPHERAL_CAN_TEST_LIB INTERFACE) target_sources( PERIPHERAL_CAN_TEST_LIB INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c + ${CMAKE_CURRENT_LIST_DIR}/Test/can_external_test.c + ${CMAKE_CURRENT_LIST_DIR}/Test/can_internal_test.c + ${CMAKE_CURRENT_LIST_DIR}/Test/can_stress_test.c + #${CMAKE_CURRENT_LIST_DIR}/Test/can.c + #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c + ) target_include_directories( PERIPHERAL_CAN_TEST_LIB @@ -28,8 +33,8 @@ target_include_directories( #if(CMAKE_BUILD_TYPE STREQUAL "Test") # Initialization # add_executable( -# PERIPHERAL_CAN_LIB_init_test -# ${CMAKE_CURRENT_LIST_DIR}/Test/can_test_init.c +# PERIPHERAL_CAN_LIB_external_test +# ${CMAKE_CURRENT_LIST_DIR}/Test/can_external_test.c # ) # target_link_libraries( # PERIPHERAL_CAN_LIB_init_test From 42198b132fb2587f112ced5038101ca97f8b8234 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 07:25:49 +0000 Subject: [PATCH 21/44] Automatic CMake Format: Standardized formatting automatically --- CMakeLists.txt | 1 - G4CANTESTING/CMakeLists.txt | 1 + G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt | 14 ++++---------- G4CANTESTING/INTERNAL_TEST/CMakeLists.txt | 14 ++++---------- G4CANTESTING/RELEASE_TEST/CMakeLists.txt | 14 ++++---------- G4CANTESTING/STRESS_TEST/CMakeLists.txt | 13 ++++++------- Lib/Peripherals/CAN/common.cmake | 12 ++++++++---- 7 files changed, 27 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22abe40c9..2fb7cf37e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,7 +87,6 @@ add_gr_project(STM32G474xE G4CANTESTING INTERNAL_TEST) add_gr_project(STM32G474xE G4CANTESTING RELEASE_TEST) add_gr_project(STM32G474xE G4CANTESTING STRESS_TEST) - add_gr_project(STM32G474xE G4CANTESTING ) #add_gr_project(STM32G474xE G4CANTESTING) diff --git a/G4CANTESTING/CMakeLists.txt b/G4CANTESTING/CMakeLists.txt index e69de29bb..8b1378917 100644 --- a/G4CANTESTING/CMakeLists.txt +++ b/G4CANTESTING/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt index b55f44091..7bb38dc9c 100644 --- a/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt @@ -43,19 +43,13 @@ target_sources( ../Core/Src/usart.c ) - if(FILTER EQUAL 1) -message(HERE) -target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) + message(HERE) + target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) else() -message(THERE) + message(THERE) endif() - -target_link_libraries( - ${PROJECT_NAME}_USER_CODE - INTERFACE - PERIPHERAL_CAN_LIB -) +target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) diff --git a/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt index b55f44091..7bb38dc9c 100644 --- a/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt @@ -43,19 +43,13 @@ target_sources( ../Core/Src/usart.c ) - if(FILTER EQUAL 1) -message(HERE) -target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) + message(HERE) + target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) else() -message(THERE) + message(THERE) endif() - -target_link_libraries( - ${PROJECT_NAME}_USER_CODE - INTERFACE - PERIPHERAL_CAN_LIB -) +target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) diff --git a/G4CANTESTING/RELEASE_TEST/CMakeLists.txt b/G4CANTESTING/RELEASE_TEST/CMakeLists.txt index b55f44091..7bb38dc9c 100644 --- a/G4CANTESTING/RELEASE_TEST/CMakeLists.txt +++ b/G4CANTESTING/RELEASE_TEST/CMakeLists.txt @@ -43,19 +43,13 @@ target_sources( ../Core/Src/usart.c ) - if(FILTER EQUAL 1) -message(HERE) -target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) + message(HERE) + target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) else() -message(THERE) + message(THERE) endif() - -target_link_libraries( - ${PROJECT_NAME}_USER_CODE - INTERFACE - PERIPHERAL_CAN_LIB -) +target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) diff --git a/G4CANTESTING/STRESS_TEST/CMakeLists.txt b/G4CANTESTING/STRESS_TEST/CMakeLists.txt index f3637d8ad..a33e440f9 100644 --- a/G4CANTESTING/STRESS_TEST/CMakeLists.txt +++ b/G4CANTESTING/STRESS_TEST/CMakeLists.txt @@ -27,7 +27,11 @@ get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) add_library(${PROJECT_NAME}_USER_CODE INTERFACE) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE /Users/vihan/Documents/Gaucho_Racing/Firmware/Firmware/G4CANTESTING/Core/Inc) +target_include_directories( + ${PROJECT_NAME}_USER_CODE + INTERFACE + /Users/vihan/Documents/Gaucho_Racing/Firmware/Firmware/G4CANTESTING/Core/Inc +) target_sources( ${PROJECT_NAME}_USER_CODE @@ -45,9 +49,4 @@ target_sources( ../Core/Src/usart.c ) - -target_link_libraries( - ${PROJECT_NAME}_USER_CODE - INTERFACE - PERIPHERAL_CAN_LIB -) +target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 76fceee70..5db5ab72c 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -1,6 +1,11 @@ add_library(PERIPHERAL_CAN_LIB INTERFACE) -target_link_libraries(PERIPHERAL_CAN_LIB INTERFACE PERIPHERAL_CAN_TEST_LIB CircularBuffer_Lib) +target_link_libraries( + PERIPHERAL_CAN_LIB + INTERFACE + PERIPHERAL_CAN_TEST_LIB + CircularBuffer_Lib +) target_sources(PERIPHERAL_CAN_LIB INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Src/can.c) @@ -19,9 +24,8 @@ target_sources( ${CMAKE_CURRENT_LIST_DIR}/Test/can_external_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_internal_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_stress_test.c - #${CMAKE_CURRENT_LIST_DIR}/Test/can.c - #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c - + #${CMAKE_CURRENT_LIST_DIR}/Test/can.c + #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c ) target_include_directories( PERIPHERAL_CAN_TEST_LIB From 5684d4154ff42ec91ff68405d45a63c924b676c6 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 07:27:18 +0000 Subject: [PATCH 22/44] Automatic Clang-Format: Standardized formatting automatically --- Lib/Peripherals/CAN/Inc/can.h | 6 ++-- Lib/Peripherals/CAN/Src/can.c | 4 +-- Lib/Peripherals/CAN/Test/can_external_test.c | 21 +++++++------ Lib/Peripherals/CAN/Test/can_filter_test.c | 5 +--- Lib/Peripherals/CAN/Test/can_init_test.c | 30 +++++++++---------- Lib/Peripherals/CAN/Test/can_internal_test.c | 21 +++++++------ Lib/Peripherals/CAN/Test/can_release_test.c | 22 +++++++++----- Lib/Peripherals/CAN/Test/can_stress_test.c | 18 +++++++----- Lib/Peripherals/CAN/Test/can_test_helpers.c | 31 ++++++++++---------- Lib/Peripherals/CAN/Test/can_tests.h | 7 ++--- 10 files changed, 89 insertions(+), 76 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index d392ec9d3..a1e91491a 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -92,9 +92,9 @@ int can_add_filter(CANHandle *handle, FDCAN_FilterTypeDef *filter); // doesn't need a handle, CAN cores share peripheral clock void can_set_clksource(uint32_t clksource); // ex. LL_RCC_FDCAN_CLKSOURCE_PCLK1 for STM32G474RE -//TODO: Add thread mode vs handler mode checking (None of these functions should be called in handler mode) +// TODO: Add thread mode vs handler mode checking (None of these functions should be called in handler mode) -//TODO: put this somewhere that someone will read it -//Somewhere in your application, define USECAN1 and TX_BUFFER_1_SIZE +// TODO: put this somewhere that someone will read it +// Somewhere in your application, define USECAN1 and TX_BUFFER_1_SIZE #endif // End Header Guard diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 9e7deced2..67b7daf99 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -203,7 +203,7 @@ CANHandle *can_init(const CANConfig *config) if (HAL_FDCAN_Init(canHandle->hal_fdcanP) != HAL_OK) { failure |= HAL_ERROR; LOGOMATIC("CAN: HAL Could not initialize FDCAN peripheral"); - return 0; + return 0; // Error_Handler(); } @@ -263,7 +263,7 @@ int can_release(CANHandle *canHandle) LOGOMATIC("CAN_release: can instance is already deinitialized"); return CAN_ERROR; } - if (can_stop(canHandle)) {// try to prevent more interrupts from firing + if (can_stop(canHandle)) { // try to prevent more interrupts from firing LOGOMATIC("CAN_release: could not stop instance"); return CAN_ERROR; } diff --git a/Lib/Peripherals/CAN/Test/can_external_test.c b/Lib/Peripherals/CAN/Test/can_external_test.c index d004b0d0e..71f9704cc 100644 --- a/Lib/Peripherals/CAN/Test/can_external_test.c +++ b/Lib/Peripherals/CAN/Test/can_external_test.c @@ -1,9 +1,8 @@ -#include "can_tests.h" - #include #include #include "can.h" +#include "can_tests.h" // each family has a constant number of CAN peripherals @@ -14,7 +13,7 @@ return 0; }*/ -//TODO: Make creating these callbacks a macro, rather than defining each one separately +// TODO: Make creating these callbacks a macro, rather than defining each one separately static volatile int rx_2_received = 0; void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { @@ -66,7 +65,7 @@ int can_external_test(void) } //============================================================================================= - if ( (primary_can = can_init(&cfg1)) == NULL) { + if ((primary_can = can_init(&cfg1)) == NULL) { LOGOMATIC("Could not initialize primary_can\n"); return ERROR; } @@ -95,7 +94,7 @@ int can_external_test(void) uint32_t i = 0; uint32_t num_messages = 5; - LOGOMATIC("Sending %ld messages on each bus...\n",num_messages); + LOGOMATIC("Sending %ld messages on each bus...\n", num_messages); while (i < num_messages) { HAL_Delay(1000); msg.data[0] = 0x2; @@ -105,11 +104,15 @@ int can_external_test(void) can_send(data_can, &msg); i += 1; } - LOGOMATIC("Received %d messages on bus1...\n",rx_1_received); - LOGOMATIC("Received %d messages on bus2...\n",rx_2_received); + LOGOMATIC("Received %d messages on bus1...\n", rx_1_received); + LOGOMATIC("Received %d messages on bus2...\n", rx_2_received); - if (can_release(primary_can)) LOGOMATIC("can_test; could not release primary_can\n"); - if (can_release(data_can)) LOGOMATIC("can_test; could not release data_can\n"); + if (can_release(primary_can)) { + LOGOMATIC("can_test; could not release primary_can\n"); + } + if (can_release(data_can)) { + LOGOMATIC("can_test; could not release data_can\n"); + } return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_filter_test.c b/Lib/Peripherals/CAN/Test/can_filter_test.c index 813492423..ce66ebe89 100644 --- a/Lib/Peripherals/CAN/Test/can_filter_test.c +++ b/Lib/Peripherals/CAN/Test/can_filter_test.c @@ -1,6 +1,3 @@ #include "can_tests.h" - - - -//TODO: +// TODO: diff --git a/Lib/Peripherals/CAN/Test/can_init_test.c b/Lib/Peripherals/CAN/Test/can_init_test.c index 4ab0ad583..68e619bab 100644 --- a/Lib/Peripherals/CAN/Test/can_init_test.c +++ b/Lib/Peripherals/CAN/Test/can_init_test.c @@ -1,20 +1,20 @@ -#include "can_tests.h" #include "can.h" +#include "can_tests.h" +// TODO: +int can_init_test(CANConfig *cfg) +{ + CANHandle *handle; + if ((handle = can_init(cfg)) == NULL) { + LOGOMATIC("can_init_test: init failed\n"); + return ERROR; + } -//TODO: -int can_init_test(CANConfig * cfg) { - CANHandle *handle; - if ( (handle = can_init(cfg)) == NULL) { - LOGOMATIC("can_init_test: init failed\n"); - return ERROR; - } - - //inspect handle - if (!handle->init) { - LOGOMATIC("can_init_test: did not set init bool in handle\n"); - return ERROR; - } + // inspect handle + if (!handle->init) { + LOGOMATIC("can_init_test: did not set init bool in handle\n"); + return ERROR; + } - return SUCCESS; + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_internal_test.c b/Lib/Peripherals/CAN/Test/can_internal_test.c index 9bb4e065d..19e7a308a 100644 --- a/Lib/Peripherals/CAN/Test/can_internal_test.c +++ b/Lib/Peripherals/CAN/Test/can_internal_test.c @@ -1,9 +1,8 @@ -#include "can_tests.h" - #include #include #include "can.h" +#include "can_tests.h" // each family has a constant number of CAN peripherals @@ -14,7 +13,7 @@ return 0; }*/ -//TODO: Make creating these callbacks a macro, rather than defining each one separately +// TODO: Make creating these callbacks a macro, rather than defining each one separately static volatile int rx_2_received = 0; void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { @@ -66,7 +65,7 @@ int can_external_test(void) } //============================================================================================= - if ( (primary_can = can_init(&cfg1)) == NULL) { + if ((primary_can = can_init(&cfg1)) == NULL) { LOGOMATIC("Could not initialize primary_can\n"); return ERROR; } @@ -95,7 +94,7 @@ int can_external_test(void) uint32_t i = 0; uint32_t num_messages = 5; - LOGOMATIC("Sending %ld messages on each bus...\n",num_messages); + LOGOMATIC("Sending %ld messages on each bus...\n", num_messages); while (i < num_messages) { HAL_Delay(1000); msg.data[0] = 0x2; @@ -105,11 +104,15 @@ int can_external_test(void) can_send(data_can, &msg); i += 1; } - LOGOMATIC("Received %d messages on bus1...\n",rx_1_received); - LOGOMATIC("Received %d messages on bus2...\n",rx_2_received); + LOGOMATIC("Received %d messages on bus1...\n", rx_1_received); + LOGOMATIC("Received %d messages on bus2...\n", rx_2_received); - if (can_release(primary_can)) LOGOMATIC("can_test; could not release primary_can\n"); - if (can_release(data_can)) LOGOMATIC("can_test; could not release data_can\n"); + if (can_release(primary_can)) { + LOGOMATIC("can_test; could not release primary_can\n"); + } + if (can_release(data_can)) { + LOGOMATIC("can_test; could not release data_can\n"); + } return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_release_test.c b/Lib/Peripherals/CAN/Test/can_release_test.c index c9ea03b4d..1e71c7a3d 100644 --- a/Lib/Peripherals/CAN/Test/can_release_test.c +++ b/Lib/Peripherals/CAN/Test/can_release_test.c @@ -1,15 +1,23 @@ -#include "can_tests.h" #include "can.h" +#include "can_tests.h" -//TODO: -int can_release_test(CANHandle * handle) { - if (handle == NULL) {return ERROR;} +// TODO: +int can_release_test(CANHandle *handle) +{ + if (handle == NULL) { + return ERROR; + } - FDCAN_HandleTypeDef * hal_instance = handle->hal_fdcanP; + FDCAN_HandleTypeDef *hal_instance = handle->hal_fdcanP; - if (can_release(handle)) LOGOMATIC("can_test; could not release primary_can\n"); + if (can_release(handle)) { + LOGOMATIC("can_test; could not release primary_can\n"); + } - if (hal_instance != canHandle->hal_fdcanP) { LOGOMATIC("can_release_test; did not reset CAN handle correctly\n"); return ERROR;} + if (hal_instance != canHandle->hal_fdcanP) { + LOGOMATIC("can_release_test; did not reset CAN handle correctly\n"); + return ERROR; + } return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c index 0871e1bbe..ec0063563 100644 --- a/Lib/Peripherals/CAN/Test/can_stress_test.c +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -1,9 +1,9 @@ -#include "can.h" -#include "can_tests.h" #include +#include "can.h" +#include "can_tests.h" -//TODO: +// TODO: static volatile uint32_t can_stress_test_received = 0; void can_stress_test_rx_callback(uint32_t id, void *data, uint32_t size) { @@ -43,7 +43,7 @@ int can_stress_test(void) .MessageMarker = 0 // also change this to a real address if you change fifo control }; - if ( (primary_can = can_init(&cfg1)) == NULL) { + if ((primary_can = can_init(&cfg1)) == NULL) { LOGOMATIC("Could not initialize primary_can\n"); return ERROR; } @@ -57,7 +57,7 @@ int can_stress_test(void) msg.data[0] = 0x80; msg.tx_header = TxHeader; - size_t i = 0; + size_t i = 0; size_t messages = 5; while (i < messages) { loop++; @@ -65,7 +65,7 @@ int can_stress_test(void) i = 0; while (i < 100) { if (can_send(primary_can, &msg) != 0) { - LOGOMATIC("Stress test failed sending CAN msg at %ud-th consecutive send.\n", (unsigned int) i + 1); + LOGOMATIC("Stress test failed sending CAN msg at %ud-th consecutive send.\n", (unsigned int)i + 1); break; } i++; @@ -73,14 +73,16 @@ int can_stress_test(void) LOGOMATIC("Sent %ud CAN msgs...\n", (unsigned int)i); HAL_Delay(1000); - LOGOMATIC("Received %ud/%ud CAN msgs after 1 second.\n", (unsigned int)can_stress_test_received, (unsigned int) i); + LOGOMATIC("Received %ud/%ud CAN msgs after 1 second.\n", (unsigned int)can_stress_test_received, (unsigned int)i); msg.data[0] = 0x10; can_send(data_can, &msg); HAL_Delay(1000); LOGOMATIC("Stress test finished loop %ld\n", loop); } - if (can_release(primary_can)) LOGOMATIC("can_test; could not release primary_can\n"); + if (can_release(primary_can)) { + LOGOMATIC("can_test; could not release primary_can\n"); + } return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_test_helpers.c b/Lib/Peripherals/CAN/Test/can_test_helpers.c index 56d20e71d..483aed184 100644 --- a/Lib/Peripherals/CAN/Test/can_test_helpers.c +++ b/Lib/Peripherals/CAN/Test/can_test_helpers.c @@ -1,20 +1,21 @@ -#include "can_tests.h" #include "can.h" +#include "can_tests.h" -int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode) { - #ifdef STM32G4 - return defaultSTM32G4_CANCfg(instance, callback, out_cfg,Mode); - #elif defined(STM32L4) - #elif defined(STM32U5) - #error "STM32U5 is untested"#else - #else - #error "Untested STM32 Family" - #endif +int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode) +{ +#ifdef STM32G4 + return defaultSTM32G4_CANCfg(instance, callback, out_cfg, Mode); +#elif defined(STM32L4) +#elif defined(STM32U5) +#error "STM32U5 is untested"#else +#else +#error "Untested STM32 Family" +#endif } -//TODO: Abstract out the system clock calculation -//Abstracts out everything but the mode and callback -int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef* instance , CAN_RXCallback callback, CANConfig * out_cfg, uint32_t Mode) +// TODO: Abstract out the system clock calculation +// Abstracts out everything but the mode and callback +int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode) { CANConfig canCfg; // canCfg.fdcan_instance = FDCAN2; @@ -37,7 +38,7 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef* instance , CAN_RXCallback callbac canCfg.hal_fdcan_init.StdFiltersNbr = 1; canCfg.hal_fdcan_init.ExtFiltersNbr = 0; - canCfg.rx_callback = NULL; // PLEASE SET + canCfg.rx_callback = NULL; // PLEASE SET canCfg.rx_interrupt_priority = 14; // PLEASE SET canCfg.tx_interrupt_priority = 14; // PLEASE SET @@ -63,7 +64,7 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef* instance , CAN_RXCallback callbac canCfg.rx_callback = callback; - if (instance == FDCAN1){ + if (instance == FDCAN1) { canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; canCfg.init_rx_gpio.Pin = GPIO_PIN_11; diff --git a/Lib/Peripherals/CAN/Test/can_tests.h b/Lib/Peripherals/CAN/Test/can_tests.h index 9668c0fda..12e0f7123 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.h +++ b/Lib/Peripherals/CAN/Test/can_tests.h @@ -11,15 +11,14 @@ #define USECAN2 #define TX_BUFFER_3_SIZE 10 -//abstract families +// abstract families extern int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); extern int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); - -//testing functions +// testing functions extern int can_external_test(void); extern int can_internal_test(void); extern int can_stress_test(void); -extern int can_release_test(CANHandle * handle); +extern int can_release_test(CANHandle *handle); #endif From c02a207716841a0da37173adf2ac5051a31bb3ae Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Tue, 10 Mar 2026 00:40:49 -0700 Subject: [PATCH 23/44] Some working version of some testing maybe Signed-off-by: Daniel Hansen --- DashPanel/Application/Src/CANdler.c | 2 +- G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt | 4 ++-- G4CANTESTING/INTERNAL_TEST/CMakeLists.txt | 4 ++-- G4CANTESTING/RELEASE_TEST/CMakeLists.txt | 4 ++-- G4CANTESTING/STRESS_TEST/CMakeLists.txt | 8 ++------ Lib/Peripherals/CAN/Test/can_external_test.c | 4 ++-- Lib/Peripherals/CAN/Test/can_internal_test.c | 6 +++--- Lib/Peripherals/CAN/Test/can_test_helpers.c | 2 ++ Lib/Peripherals/CAN/common.cmake | 6 ++++-- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/DashPanel/Application/Src/CANdler.c b/DashPanel/Application/Src/CANdler.c index 65874f3de..ee42e92f5 100644 --- a/DashPanel/Application/Src/CANdler.c +++ b/DashPanel/Application/Src/CANdler.c @@ -46,7 +46,7 @@ void CANInitialize() canCfg.rx_callback = CAN_callback; canCfg.rx_interrupt_priority = 15; canCfg.tx_interrupt_priority = 15; - canCfg.tx_buffer_length = 3; + //canCfg.tx_buffer_length = 3; canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; diff --git a/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt index 7bb38dc9c..8e45c7d12 100644 --- a/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt @@ -35,7 +35,7 @@ target_sources( ../Core/Src/dma.c ../Core/Src/gpio.c ../Core/Src/i2c.c - ../Core/Src/main.c + main.c ../Core/Src/spi.c ../Core/Src/stm32g4xx_hal_msp.c ../Core/Src/stm32g4xx_it.c @@ -52,4 +52,4 @@ endif() target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt index 7bb38dc9c..8e45c7d12 100644 --- a/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt @@ -35,7 +35,7 @@ target_sources( ../Core/Src/dma.c ../Core/Src/gpio.c ../Core/Src/i2c.c - ../Core/Src/main.c + main.c ../Core/Src/spi.c ../Core/Src/stm32g4xx_hal_msp.c ../Core/Src/stm32g4xx_it.c @@ -52,4 +52,4 @@ endif() target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/RELEASE_TEST/CMakeLists.txt b/G4CANTESTING/RELEASE_TEST/CMakeLists.txt index 7bb38dc9c..8e45c7d12 100644 --- a/G4CANTESTING/RELEASE_TEST/CMakeLists.txt +++ b/G4CANTESTING/RELEASE_TEST/CMakeLists.txt @@ -35,7 +35,7 @@ target_sources( ../Core/Src/dma.c ../Core/Src/gpio.c ../Core/Src/i2c.c - ../Core/Src/main.c + main.c ../Core/Src/spi.c ../Core/Src/stm32g4xx_hal_msp.c ../Core/Src/stm32g4xx_it.c @@ -52,4 +52,4 @@ endif() target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE Core/Inc) +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/STRESS_TEST/CMakeLists.txt b/G4CANTESTING/STRESS_TEST/CMakeLists.txt index a33e440f9..97567b980 100644 --- a/G4CANTESTING/STRESS_TEST/CMakeLists.txt +++ b/G4CANTESTING/STRESS_TEST/CMakeLists.txt @@ -27,21 +27,17 @@ get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) add_library(${PROJECT_NAME}_USER_CODE INTERFACE) -target_include_directories( - ${PROJECT_NAME}_USER_CODE - INTERFACE - /Users/vihan/Documents/Gaucho_Racing/Firmware/Firmware/G4CANTESTING/Core/Inc -) +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) target_sources( ${PROJECT_NAME}_USER_CODE INTERFACE + main.c ../Core/Src/adc.c ../Core/Src/crc.c ../Core/Src/dma.c ../Core/Src/gpio.c ../Core/Src/i2c.c - ../Core/Src/main.c ../Core/Src/spi.c ../Core/Src/stm32g4xx_hal_msp.c ../Core/Src/stm32g4xx_it.c diff --git a/Lib/Peripherals/CAN/Test/can_external_test.c b/Lib/Peripherals/CAN/Test/can_external_test.c index 71f9704cc..ee52504b3 100644 --- a/Lib/Peripherals/CAN/Test/can_external_test.c +++ b/Lib/Peripherals/CAN/Test/can_external_test.c @@ -15,7 +15,7 @@ // TODO: Make creating these callbacks a macro, rather than defining each one separately static volatile int rx_2_received = 0; -void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) +static void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { rx_2_received++; LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); @@ -24,7 +24,7 @@ void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) } static volatile int rx_1_received = 0; -void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) +static void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) { rx_1_received++; LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); diff --git a/Lib/Peripherals/CAN/Test/can_internal_test.c b/Lib/Peripherals/CAN/Test/can_internal_test.c index 19e7a308a..472c90b34 100644 --- a/Lib/Peripherals/CAN/Test/can_internal_test.c +++ b/Lib/Peripherals/CAN/Test/can_internal_test.c @@ -15,7 +15,7 @@ // TODO: Make creating these callbacks a macro, rather than defining each one separately static volatile int rx_2_received = 0; -void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) +static void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { rx_2_received++; LOGOMATIC("CAN2 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); @@ -24,7 +24,7 @@ void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) } static volatile int rx_1_received = 0; -void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) +static void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) { rx_1_received++; LOGOMATIC("CAN1 Got data! Size %ld, data[0] = 0x%x, id %" PRIu32 "\n", size, *(char *)data, id); @@ -35,7 +35,7 @@ void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) // TODO - allow user to send data without needing to construct a header for the buffer // TODO: G4 tests are dependent on the System clock configuration?? -int can_external_test(void) +int can_internal_test(void) { FDCAN_TxHeaderTypeDef TxHeader = { .Identifier = 1, diff --git a/Lib/Peripherals/CAN/Test/can_test_helpers.c b/Lib/Peripherals/CAN/Test/can_test_helpers.c index 483aed184..e2d3da885 100644 --- a/Lib/Peripherals/CAN/Test/can_test_helpers.c +++ b/Lib/Peripherals/CAN/Test/can_test_helpers.c @@ -1,5 +1,7 @@ #include "can.h" #include "can_tests.h" +#include "can.h" +#include int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode) { diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 5db5ab72c..2cef4ba21 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -24,8 +24,10 @@ target_sources( ${CMAKE_CURRENT_LIST_DIR}/Test/can_external_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_internal_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_stress_test.c - #${CMAKE_CURRENT_LIST_DIR}/Test/can.c - #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c + ${CMAKE_CURRENT_LIST_DIR}/Test/can_test_helpers.c + #${CMAKE_CURRENT_LIST_DIR}/Test/can.c + #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c + ) target_include_directories( PERIPHERAL_CAN_TEST_LIB From 2b606621ba5f2591e73c8325d73ef401beda5aab Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 07:41:29 +0000 Subject: [PATCH 24/44] Automatic CMake Format: Standardized formatting automatically --- Lib/Peripherals/CAN/common.cmake | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 2cef4ba21..3a987ff8a 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -25,9 +25,8 @@ target_sources( ${CMAKE_CURRENT_LIST_DIR}/Test/can_internal_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_stress_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_test_helpers.c - #${CMAKE_CURRENT_LIST_DIR}/Test/can.c - #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c - + #${CMAKE_CURRENT_LIST_DIR}/Test/can.c + #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c ) target_include_directories( PERIPHERAL_CAN_TEST_LIB From e7c8328f458352ad3e0a4e9cc97d84d85367dfb1 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 07:42:51 +0000 Subject: [PATCH 25/44] Automatic Clang-Format: Standardized formatting automatically --- DashPanel/Application/Src/CANdler.c | 2 +- Lib/Peripherals/CAN/Test/can_test_helpers.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DashPanel/Application/Src/CANdler.c b/DashPanel/Application/Src/CANdler.c index ee42e92f5..6d0df463d 100644 --- a/DashPanel/Application/Src/CANdler.c +++ b/DashPanel/Application/Src/CANdler.c @@ -46,7 +46,7 @@ void CANInitialize() canCfg.rx_callback = CAN_callback; canCfg.rx_interrupt_priority = 15; canCfg.tx_interrupt_priority = 15; - //canCfg.tx_buffer_length = 3; + // canCfg.tx_buffer_length = 3; canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; diff --git a/Lib/Peripherals/CAN/Test/can_test_helpers.c b/Lib/Peripherals/CAN/Test/can_test_helpers.c index e2d3da885..64c63cb23 100644 --- a/Lib/Peripherals/CAN/Test/can_test_helpers.c +++ b/Lib/Peripherals/CAN/Test/can_test_helpers.c @@ -1,7 +1,7 @@ +#include + #include "can.h" #include "can_tests.h" -#include "can.h" -#include int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode) { From e3dd937236f6bd3019a911d5ee013803b8286d14 Mon Sep 17 00:00:00 2001 From: Daniel Hansen Date: Tue, 10 Mar 2026 00:43:35 -0700 Subject: [PATCH 26/44] Everything builds Signed-off-by: Daniel Hansen --- CMakeLists.txt | 1 - G4CANTESTING/CMakeLists.txt | 1 - G4CANTESTING/Core/Src/main.c | 273 ------------------------------- G4CANTESTING/RELEASE_TEST/main.c | 2 +- 4 files changed, 1 insertion(+), 276 deletions(-) delete mode 100644 G4CANTESTING/CMakeLists.txt delete mode 100644 G4CANTESTING/Core/Src/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fb7cf37e..edf5ae3ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,7 +87,6 @@ add_gr_project(STM32G474xE G4CANTESTING INTERNAL_TEST) add_gr_project(STM32G474xE G4CANTESTING RELEASE_TEST) add_gr_project(STM32G474xE G4CANTESTING STRESS_TEST) -add_gr_project(STM32G474xE G4CANTESTING ) #add_gr_project(STM32G474xE G4CANTESTING) add_gr_project(STM32G474xE G4NEOTESTING) diff --git a/G4CANTESTING/CMakeLists.txt b/G4CANTESTING/CMakeLists.txt deleted file mode 100644 index 8b1378917..000000000 --- a/G4CANTESTING/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/G4CANTESTING/Core/Src/main.c b/G4CANTESTING/Core/Src/main.c deleted file mode 100644 index c659e0390..000000000 --- a/G4CANTESTING/Core/Src/main.c +++ /dev/null @@ -1,273 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * - * Copyright (c) 2024 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "main.h" - -#include "adc.h" -#include "can.h" // Assume this works -#include "can_tests.h" -#include "dma.h" -#include "fdcan.h" -#include "gpio.h" -#include "i2c.h" -#include "spi.h" -#include "tim.h" -#include "usart.h" - -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include "Logomatic.h" -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ -/* Enable ITM for SWO output */ -static void ITM_Enable(void) -{ - LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); - LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = LL_GPIO_PIN_3; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_0; - LL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; - - /* Enable TRC (Trace) */ - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - - /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ - TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ - TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ - - ITM->TER |= (1UL << 0); - ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); -} -// static int toggleze = 0; -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) -{ - /* USER CODE BEGIN 1 */ - - /* USER CODE END 1 */ - - /* MCU - * Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the - * Systick. */ - HAL_Init(); - /* USER CODE BEGIN Init */ - ITM_Enable(); - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_DMA_Init(); - // MX_FDCAN2_Init(); - MX_ADC1_Init(); - MX_LPUART1_UART_Init(); - MX_I2C2_Init(); - MX_USART1_UART_Init(); - MX_SPI3_Init(); - MX_TIM2_Init(); - - /* USER CODE BEGIN 2 */ - - LOGOMATIC("Booted!\n"); - - can_test(); - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - while (1) { - /* USER CODE END WHILE */ - LOGOMATIC("Main Loop\n"); - LL_mDelay(1000); - - // Receive on GPIOs - // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET - // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? - // 0x00 : 0x80; can_send(data_can, &msg); - - // RCC->CFGR |= RCC_CFGR_SW; - /* USER CODE BEGIN 3 */ - } -} - -/** - * @brief System Clock Configuration - * @retval None - */ - -// void SystemClock_Config(void) -// { -// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); -// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { -// } -// LL_PWR_EnableRange1BoostMode(); -// LL_RCC_HSE_Enable(); - -// /* Wait till HSE is ready */ -// while (LL_RCC_HSE_IsReady() != 1) { -// } - -// LL_RCC_HSE_EnableCSS(); -// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, -// LL_RCC_PLLR_DIV_2); -// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); -// LL_RCC_PLL_EnableDomain_SYS(); -// LL_RCC_PLL_Enable(); -// /* Wait till PLL is ready */ -// while (LL_RCC_PLL_IsReady() != 1) { -// } - -// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); -// /* Wait till System clock is ready */ -// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { -// } - -// /* Insure 1us transition state at intermediate medium speed clock*/ -// for (__IO uint32_t i = (170 >> 1); i != 0; i--) -// ; - -// /* Set AHB prescaler*/ -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); -// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); -// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); -// LL_SetSystemCoreClock(160000000); - -// /* Update the time base */ -// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { -// Error_Handler(); -// } -// }*/ -void SystemClock_Config(void) -{ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); - while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} - LL_PWR_EnableRange1BoostMode(); - LL_RCC_HSI_Enable(); - /* Wait till HSI is ready */ - while (LL_RCC_HSI_IsReady() != 1) {} - - LL_RCC_HSI_SetCalibTrimming(64); - LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); - LL_RCC_PLL_EnableDomain_SYS(); - LL_RCC_PLL_Enable(); - /* Wait till PLL is ready */ - while (LL_RCC_PLL_IsReady() != 1) {} - - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - /* Wait till System clock is ready */ - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} - - /* Insure 1us transition state at intermediate medium speed clock*/ - for (__IO uint32_t i = (170 >> 1); i != 0; i--) - ; - - /* Set AHB prescaler*/ - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); - LL_SetSystemCoreClock(170000000); - - /* Update the time base */ - if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ - -/* USER CODE END 4 */ - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) -{ - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return - * state */ - __disable_irq(); - while (1) {} - /* USER CODE END Error_Handler_Debug */ -} -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line - number, ex: printf("Wrong parameters value: file %s on line %d\r\n", - file, line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/RELEASE_TEST/main.c b/G4CANTESTING/RELEASE_TEST/main.c index 22219a044..edb293959 100644 --- a/G4CANTESTING/RELEASE_TEST/main.c +++ b/G4CANTESTING/RELEASE_TEST/main.c @@ -134,7 +134,7 @@ int main(void) LOGOMATIC("Booted!\n"); LOGOMATIC("running can_release_test:\n"); - can_release_test(); +// can_release_test(); /* Infinite loop */ /* USER CODE BEGIN WHILE */ From 00f4d3d3bb83c70059401a299d6d52f61dfeb097 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 07:45:02 +0000 Subject: [PATCH 27/44] Automatic Clang-Format: Standardized formatting automatically --- G4CANTESTING/RELEASE_TEST/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/G4CANTESTING/RELEASE_TEST/main.c b/G4CANTESTING/RELEASE_TEST/main.c index edb293959..35c016f90 100644 --- a/G4CANTESTING/RELEASE_TEST/main.c +++ b/G4CANTESTING/RELEASE_TEST/main.c @@ -134,7 +134,7 @@ int main(void) LOGOMATIC("Booted!\n"); LOGOMATIC("running can_release_test:\n"); -// can_release_test(); + // can_release_test(); /* Infinite loop */ /* USER CODE BEGIN WHILE */ From 3b27e30664543941b64a5cb7b2e05315bf76d265 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Tue, 10 Mar 2026 02:47:17 -0700 Subject: [PATCH 28/44] changed tests --- .vscode/launch.json | 120 ++++++++ .vscode/tasks.json | 32 ++ CMakeLists.txt | 8 +- .../CMakeLists.txt | 9 +- G4CANTESTING/CAN_EXTERNAL_TEST/main.c | 274 ++++++++++++++++++ G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt | 52 ++++ G4CANTESTING/CAN_INTERNAL_TEST/main.c | 274 ++++++++++++++++++ G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt | 52 ++++ G4CANTESTING/CAN_RELEASE_TEST/main.c | 274 ++++++++++++++++++ G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt | 52 ++++ G4CANTESTING/CAN_STRESS_TEST/main.c | 274 ++++++++++++++++++ Lib/Peripherals/CAN/Src/can.c | 2 +- Lib/Peripherals/CAN/Test/can_external_test.c | 34 ++- Lib/Peripherals/CAN/Test/can_internal_test.c | 34 ++- Lib/Peripherals/CAN/Test/can_release_test.c | 32 +- Lib/Peripherals/CAN/Test/can_stress_test.c | 19 +- Lib/Peripherals/CAN/Test/can_tests.h | 2 +- Lib/Peripherals/CAN/common.cmake | 1 + 18 files changed, 1508 insertions(+), 37 deletions(-) rename G4CANTESTING/{EXTERNAL_TEST => CAN_EXTERNAL_TEST}/CMakeLists.txt (89%) create mode 100644 G4CANTESTING/CAN_EXTERNAL_TEST/main.c create mode 100644 G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt create mode 100644 G4CANTESTING/CAN_INTERNAL_TEST/main.c create mode 100644 G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt create mode 100644 G4CANTESTING/CAN_RELEASE_TEST/main.c create mode 100644 G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt create mode 100644 G4CANTESTING/CAN_STRESS_TEST/main.c diff --git a/.vscode/launch.json b/.vscode/launch.json index a773f1ed9..9055b3e9e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -467,6 +467,126 @@ } ] } + },{ + "cwd": "${workspaceFolder}", + "executable": "${command:cmake.buildDirectory}/CAN_EXTERNAL_TEST.elf", + "name": "CAN_EXTERNAL_TEST", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32g4x.cfg" + ], + "searchDir": [], + "preLaunchTask": "CMake: configure and build CAN_EXTERNAL_TEST", + "showDevDebugOutput": "raw", + "svdPath": "${workspaceFolder}/Lib/Vendor/CMSIS_5/SVD/STM32G474.svd", + "swoConfig": { + "enabled": true, + "cpuFrequency": 170000000, + "swoFrequency": 2000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "ITM", + "showOnStartup": true, + "port": 0, + "encoding": "ascii" + } + ] + } + },{ + "cwd": "${workspaceFolder}", + "executable": "${command:cmake.buildDirectory}/CAN_INTERNAL_TEST.elf", + "name": "CAN_INTERNAL_TEST", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32g4x.cfg" + ], + "searchDir": [], + "preLaunchTask": "CMake: configure and build CAN_INTERNAL_TEST", + "showDevDebugOutput": "raw", + "svdPath": "${workspaceFolder}/Lib/Vendor/CMSIS_5/SVD/STM32G474.svd", + "swoConfig": { + "enabled": true, + "cpuFrequency": 170000000, + "swoFrequency": 2000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "ITM", + "showOnStartup": true, + "port": 0, + "encoding": "ascii" + } + ] + } + },{ + "cwd": "${workspaceFolder}", + "executable": "${command:cmake.buildDirectory}/CAN_STRESS_TEST.elf", + "name": "CAN_STRESS_TEST", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32g4x.cfg" + ], + "searchDir": [], + "preLaunchTask": "CMake: configure and build CAN_STRESS_TEST", + "showDevDebugOutput": "raw", + "svdPath": "${workspaceFolder}/Lib/Vendor/CMSIS_5/SVD/STM32G474.svd", + "swoConfig": { + "enabled": true, + "cpuFrequency": 170000000, + "swoFrequency": 2000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "ITM", + "showOnStartup": true, + "port": 0, + "encoding": "ascii" + } + ] + } + },{ + "cwd": "${workspaceFolder}", + "executable": "${command:cmake.buildDirectory}/CAN_RELEASE_TEST.elf", + "name": "CAN_RELEASE_TEST", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32g4x.cfg" + ], + "searchDir": [], + "preLaunchTask": "CMake: configure and build CAN_RELEASE_TEST", + "showDevDebugOutput": "raw", + "svdPath": "${workspaceFolder}/Lib/Vendor/CMSIS_5/SVD/STM32G474.svd", + "swoConfig": { + "enabled": true, + "cpuFrequency": 170000000, + "swoFrequency": 2000000, + "source": "probe", + "decoders": [ + { + "type": "console", + "label": "ITM", + "showOnStartup": true, + "port": 0, + "encoding": "ascii" + } + ] + } } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 7f017158b..59fd7226d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -152,6 +152,38 @@ "CMake: configure" ], "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target W3_G4SPI_Receive" + },{ + "label": "CMake: configure and build CAN_EXTERNAL_TEST", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "CMake: configure" + ], + "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target CAN_EXTERNAL_TEST" + },{ + "label": "CMake: configure and build CAN_INTERNAL_TEST", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "CMake: configure" + ], + "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target CAN_INTERNAL_TEST" + },{ + "label": "CMake: configure and build CAN_RELEASE_TEST", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "CMake: configure" + ], + "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target CAN_RELEASE_TEST" + },{ + "label": "CMake: configure and build CAN_STRESS_TEST", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "CMake: configure" + ], + "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target CAN_STRESS_TEST" } ] } diff --git a/CMakeLists.txt b/CMakeLists.txt index edf5ae3ce..055405567 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,11 +81,11 @@ add_gr_project(STM32G474xE G4PERTESTING) #CAN Peripheral Testing #add_gr_project(STM32G474xE G4CANTESTING FILTER_TEST) -add_gr_project(STM32G474xE G4CANTESTING EXTERNAL_TEST) -add_gr_project(STM32G474xE G4CANTESTING INTERNAL_TEST) +add_gr_project(STM32G474xE G4CANTESTING CAN_EXTERNAL_TEST) +add_gr_project(STM32G474xE G4CANTESTING CAN_INTERNAL_TEST) #add_gr_project(STM32G474xE G4CANTESTING INIT_TEST) -add_gr_project(STM32G474xE G4CANTESTING RELEASE_TEST) -add_gr_project(STM32G474xE G4CANTESTING STRESS_TEST) +add_gr_project(STM32G474xE G4CANTESTING CAN_RELEASE_TEST) +add_gr_project(STM32G474xE G4CANTESTING CAN_STRESS_TEST) #add_gr_project(STM32G474xE G4CANTESTING) diff --git a/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt similarity index 89% rename from G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt rename to G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt index 8e45c7d12..97c066be9 100644 --- a/G4CANTESTING/EXTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt @@ -43,12 +43,9 @@ target_sources( ../Core/Src/usart.c ) -if(FILTER EQUAL 1) - message(HERE) - target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) -else() - message(THERE) -endif() +set_target_properties(${NAME} PROPERTIES + OUTPUT_NAME "CAN_${NAME}" +) target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/main.c b/G4CANTESTING/CAN_EXTERNAL_TEST/main.c new file mode 100644 index 000000000..7926c9850 --- /dev/null +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + //LOGOMATIC("running can_external_test:\n"); + can_external_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt new file mode 100644 index 000000000..97c066be9 --- /dev/null +++ b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.25) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Enable CMake support for ASM and C languages +enable_language( + C + ASM +) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) + +# what, does in fact not get the filename of somthing but rather the name of the project from the path +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +add_library(${PROJECT_NAME}_USER_CODE INTERFACE) + +target_sources( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Src/adc.c + ../Core/Src/crc.c + ../Core/Src/dma.c + ../Core/Src/gpio.c + ../Core/Src/i2c.c + main.c + ../Core/Src/spi.c + ../Core/Src/stm32g4xx_hal_msp.c + ../Core/Src/stm32g4xx_it.c + ../Core/Src/tim.c + ../Core/Src/usart.c +) + +set_target_properties(${NAME} PROPERTIES + OUTPUT_NAME "CAN_${NAME}" +) + +target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) + +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/main.c b/G4CANTESTING/CAN_INTERNAL_TEST/main.c new file mode 100644 index 000000000..c8632a431 --- /dev/null +++ b/G4CANTESTING/CAN_INTERNAL_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + //LOGOMATIC("running can_internal_test:\n"); + can_internal_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt b/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt new file mode 100644 index 000000000..97c066be9 --- /dev/null +++ b/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.25) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Enable CMake support for ASM and C languages +enable_language( + C + ASM +) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) + +# what, does in fact not get the filename of somthing but rather the name of the project from the path +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +add_library(${PROJECT_NAME}_USER_CODE INTERFACE) + +target_sources( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Src/adc.c + ../Core/Src/crc.c + ../Core/Src/dma.c + ../Core/Src/gpio.c + ../Core/Src/i2c.c + main.c + ../Core/Src/spi.c + ../Core/Src/stm32g4xx_hal_msp.c + ../Core/Src/stm32g4xx_it.c + ../Core/Src/tim.c + ../Core/Src/usart.c +) + +set_target_properties(${NAME} PROPERTIES + OUTPUT_NAME "CAN_${NAME}" +) + +target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) + +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/CAN_RELEASE_TEST/main.c b/G4CANTESTING/CAN_RELEASE_TEST/main.c new file mode 100644 index 000000000..ece53ba15 --- /dev/null +++ b/G4CANTESTING/CAN_RELEASE_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + //LOGOMATIC("running can_release_test:\n"); + can_release_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt b/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt new file mode 100644 index 000000000..b6163b1bb --- /dev/null +++ b/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.25) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Enable CMake support for ASM and C languages +enable_language( + C + ASM +) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) + +# what, does in fact not get the filename of somthing but rather the name of the project from the path +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +add_library(${PROJECT_NAME}_USER_CODE INTERFACE) + + + +target_sources( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Src/adc.c + ../Core/Src/crc.c + ../Core/Src/dma.c + ../Core/Src/gpio.c + ../Core/Src/i2c.c + main.c + ../Core/Src/spi.c + ../Core/Src/stm32g4xx_hal_msp.c + ../Core/Src/stm32g4xx_it.c + ../Core/Src/tim.c + ../Core/Src/usart.c +) + + + +target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) + +target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/CAN_STRESS_TEST/main.c b/G4CANTESTING/CAN_STRESS_TEST/main.c new file mode 100644 index 000000000..6939cbe9f --- /dev/null +++ b/G4CANTESTING/CAN_STRESS_TEST/main.c @@ -0,0 +1,274 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +#include "adc.h" +#include "can.h" // Assume this works +#include "can_tests.h" +#include "dma.h" +#include "fdcan.h" +#include "gpio.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "Logomatic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +/* Enable ITM for SWO output */ +static void ITM_Enable(void) +{ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_0; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + + /* Enable TRC (Trace) */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + + /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ + TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ + TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ + + ITM->TER |= (1UL << 0); + ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); +} +// static int toggleze = 0; +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU + * Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the + * Systick. */ + HAL_Init(); + /* USER CODE BEGIN Init */ + ITM_Enable(); + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + // MX_FDCAN2_Init(); + MX_ADC1_Init(); + MX_LPUART1_UART_Init(); + MX_I2C2_Init(); + MX_USART1_UART_Init(); + MX_SPI3_Init(); + MX_TIM2_Init(); + + /* USER CODE BEGIN 2 */ + + LOGOMATIC("Booted!\n"); + + //LOGOMATIC("running can_stress_test:\n"); + can_stress_test(); + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + /* USER CODE END WHILE */ + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); + + // Receive on GPIOs + // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET + // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? + // 0x00 : 0x80; can_send(data_can, &msg); + + // RCC->CFGR |= RCC_CFGR_SW; + /* USER CODE BEGIN 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ + +// void SystemClock_Config(void) +// { +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { +// } +// LL_PWR_EnableRange1BoostMode(); +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) { +// } + +// LL_RCC_HSE_EnableCSS(); +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, +// LL_RCC_PLLR_DIV_2); +// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) { +// } + +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { +// } + +// /* Insure 1us transition state at intermediate medium speed clock*/ +// for (__IO uint32_t i = (170 >> 1); i != 0; i--) +// ; + +// /* Set AHB prescaler*/ +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); +// LL_SetSystemCoreClock(160000000); + +// /* Update the time base */ +// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { +// Error_Handler(); +// } +// }*/ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} + LL_PWR_EnableRange1BoostMode(); + LL_RCC_HSI_Enable(); + /* Wait till HSI is ready */ + while (LL_RCC_HSI_IsReady() != 1) {} + + LL_RCC_HSI_SetCalibTrimming(64); + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) {} + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} + + /* Insure 1us transition state at intermediate medium speed clock*/ + for (__IO uint32_t i = (170 >> 1); i != 0; i--) + ; + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_SetSystemCoreClock(170000000); + + /* Update the time base */ + if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return + * state */ + __disable_irq(); + while (1) {} + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, ex: printf("Wrong parameters value: file %s on line %d\r\n", + file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 67b7daf99..2f43ef5c2 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -163,7 +163,7 @@ CANHandle *can_init(const CANConfig *config) // #endif if (canHandle == NULL) { LOGOMATIC("CAN: Unrecognized FDCAN instance"); - return CAN_SUCCESS; + return NULL; } canHandle->init = false; canHandle->started = false; diff --git a/Lib/Peripherals/CAN/Test/can_external_test.c b/Lib/Peripherals/CAN/Test/can_external_test.c index ee52504b3..7a92689a6 100644 --- a/Lib/Peripherals/CAN/Test/can_external_test.c +++ b/Lib/Peripherals/CAN/Test/can_external_test.c @@ -13,8 +13,13 @@ return 0; }*/ +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + // TODO: Make creating these callbacks a macro, rather than defining each one separately -static volatile int rx_2_received = 0; +static volatile uint32_t rx_2_received = 0; static void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { rx_2_received++; @@ -23,7 +28,7 @@ static void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) return; } -static volatile int rx_1_received = 0; +static volatile uint32_t rx_1_received = 0; static void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) { rx_1_received++; @@ -104,15 +109,28 @@ int can_external_test(void) can_send(data_can, &msg); i += 1; } - LOGOMATIC("Received %d messages on bus1...\n", rx_1_received); - LOGOMATIC("Received %d messages on bus2...\n", rx_2_received); + LOGOMATIC("Received %ld messages on bus1...\n", rx_1_received); + LOGOMATIC("Received %ld messages on bus2...\n", rx_2_received); + + + uint32_t error = false; - if (can_release(primary_can)) { - LOGOMATIC("can_test; could not release primary_can\n"); + if ((rx_1_received!=num_messages)) { + error = true; + LOGOMATIC("FAIL: can_internal_test: did not receive all rx1\n"); } - if (can_release(data_can)) { - LOGOMATIC("can_test; could not release data_can\n"); + if ((rx_2_received!=num_messages)) { + error = true; + LOGOMATIC("FAIL: can_internal_test: did not receive all rx2\n"); } + uint32_t rc; + if ( (rc = can_release(primary_can))) LOGOMATIC("FAIL: can_external_test; could not release primary_can\n"); + error |= rc; + if ( (rc = can_release(primary_can))) LOGOMATIC("FAIL: can_external_test; could not release data_can\n"); + error |= rc; + + if (error) {return ERROR;} + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_internal_test.c b/Lib/Peripherals/CAN/Test/can_internal_test.c index 472c90b34..dc2f8d35b 100644 --- a/Lib/Peripherals/CAN/Test/can_internal_test.c +++ b/Lib/Peripherals/CAN/Test/can_internal_test.c @@ -13,8 +13,13 @@ return 0; }*/ +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + // TODO: Make creating these callbacks a macro, rather than defining each one separately -static volatile int rx_2_received = 0; +static volatile uint32_t rx_2_received = 0; static void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { rx_2_received++; @@ -23,7 +28,7 @@ static void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) return; } -static volatile int rx_1_received = 0; +static volatile uint32_t rx_1_received = 0; static void can_test_rx_callback1(uint32_t id, void *data, uint32_t size) { rx_1_received++; @@ -104,15 +109,28 @@ int can_internal_test(void) can_send(data_can, &msg); i += 1; } - LOGOMATIC("Received %d messages on bus1...\n", rx_1_received); - LOGOMATIC("Received %d messages on bus2...\n", rx_2_received); + LOGOMATIC("Received %ld messages on bus1...\n", rx_1_received); + LOGOMATIC("Received %ld messages on bus2...\n", rx_2_received); + + + uint32_t error = false; - if (can_release(primary_can)) { - LOGOMATIC("can_test; could not release primary_can\n"); + if ((rx_1_received!=num_messages)) { + error = true; + LOGOMATIC("FAIL: can_internal_test: did not receive all rx1\n"); } - if (can_release(data_can)) { - LOGOMATIC("can_test; could not release data_can\n"); + if ((rx_2_received!=num_messages)) { + error = true; + LOGOMATIC("FAIL: can_internal_test: did not receive all rx2\n"); } + uint32_t rc; + if ( (rc = can_release(primary_can)) ) LOGOMATIC("FAIL: can_internal_test; could not release primary_can\n"); + error |= rc; + if ( (rc = can_release(primary_can)) ) LOGOMATIC("FAIL: can_internal_test; could not release data_can\n"); + error |= rc; + + if (error) {return ERROR;} + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_release_test.c b/Lib/Peripherals/CAN/Test/can_release_test.c index 1e71c7a3d..dfc8fe383 100644 --- a/Lib/Peripherals/CAN/Test/can_release_test.c +++ b/Lib/Peripherals/CAN/Test/can_release_test.c @@ -1,23 +1,39 @@ #include "can.h" #include "can_tests.h" +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + // TODO: -int can_release_test(CANHandle *handle) +int can_release_test() { - if (handle == NULL) { + LOGOMATIC("running can_release_test\n"); + + CANConfig cfg; + if (get_cfg(FDCAN1, NULL, &cfg, FDCAN_MODE_NORMAL)) { + LOGOMATIC("Could not get config for FDCAN1\n"); return ERROR; } - FDCAN_HandleTypeDef *hal_instance = handle->hal_fdcanP; + CANHandle *can = NULL; + + //============================================================================================= + if ((can = can_init(&cfg)) == NULL) { + LOGOMATIC("can_init: Could not initialize primary_can\n"); + return ERROR; + } - if (can_release(handle)) { - LOGOMATIC("can_test; could not release primary_can\n"); + FDCAN_HandleTypeDef * temp = can->hal_fdcanP; + if (can_release(can)) { + LOGOMATIC("can_release: Could not release can\n"); + return ERROR; } - if (hal_instance != canHandle->hal_fdcanP) { - LOGOMATIC("can_release_test; did not reset CAN handle correctly\n"); + //test state of canHandle after release + if (temp != can->hal_fdcanP) { + LOGOMATIC("can_release: cleared handle incorrectly\n"); return ERROR; } - return SUCCESS; + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c index ec0063563..9e795e10a 100644 --- a/Lib/Peripherals/CAN/Test/can_stress_test.c +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -3,6 +3,9 @@ #include "can.h" #include "can_tests.h" +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + // TODO: static volatile uint32_t can_stress_test_received = 0; void can_stress_test_rx_callback(uint32_t id, void *data, uint32_t size) @@ -16,6 +19,7 @@ void can_stress_test_rx_callback(uint32_t id, void *data, uint32_t size) int can_stress_test(void) { + LOGOMATIC("running can_stress_test\n"); uint32_t status, loop; UNUSED(status); @@ -59,6 +63,7 @@ int can_stress_test(void) size_t i = 0; size_t messages = 5; + uint32_t successes = 0; while (i < messages) { loop++; can_stress_test_received = 0; @@ -74,7 +79,11 @@ int can_stress_test(void) HAL_Delay(1000); LOGOMATIC("Received %ud/%ud CAN msgs after 1 second.\n", (unsigned int)can_stress_test_received, (unsigned int)i); - msg.data[0] = 0x10; + + if (can_stress_test_received == i) { + successes += 1; + } + msg.data[0] = 0x10; can_send(data_can, &msg); HAL_Delay(1000); LOGOMATIC("Stress test finished loop %ld\n", loop); @@ -82,7 +91,15 @@ int can_stress_test(void) if (can_release(primary_can)) { LOGOMATIC("can_test; could not release primary_can\n"); + return ERROR; } + if (successes != messages) { + LOGOMATIC("can_stress_test failed\n"); + return ERROR; + } + + LOGOMATIC("can_stress_test passed\n"); + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_tests.h b/Lib/Peripherals/CAN/Test/can_tests.h index 12e0f7123..41004c34c 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.h +++ b/Lib/Peripherals/CAN/Test/can_tests.h @@ -19,6 +19,6 @@ extern int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANCo extern int can_external_test(void); extern int can_internal_test(void); extern int can_stress_test(void); -extern int can_release_test(CANHandle *handle); +extern int can_release_test(void); #endif diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 3a987ff8a..9efce16b9 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -23,6 +23,7 @@ target_sources( INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Test/can_external_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_internal_test.c + ${CMAKE_CURRENT_LIST_DIR}/Test/can_release_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_stress_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_test_helpers.c #${CMAKE_CURRENT_LIST_DIR}/Test/can.c From 4700904bb9115c492e9ddec1c9b406a981116aaa Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:13:46 -0700 Subject: [PATCH 29/44] running through tests --- G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h | 12 ++++++++++++ G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt | 1 - G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h | 12 ++++++++++++ G4CANTESTING/CAN_RELEASE_TEST/can_conf.h | 12 ++++++++++++ G4CANTESTING/CAN_STRESS_TEST/can_conf.h | 12 ++++++++++++ Lib/Peripherals/CAN/Src/can.c | 16 +++++++++++----- Lib/Peripherals/CAN/Test/can_external_test.c | 8 ++++---- Lib/Peripherals/CAN/Test/can_init_test.c | 3 ++- Lib/Peripherals/CAN/Test/can_internal_test.c | 8 ++++---- Lib/Peripherals/CAN/Test/can_release_test.c | 4 ++-- Lib/Peripherals/CAN/Test/can_stress_test.c | 4 ++-- Lib/Peripherals/CAN/Test/can_test_helpers.c | 11 +++++++---- Lib/Peripherals/CAN/Test/can_tests.h | 8 ++++---- 13 files changed, 84 insertions(+), 27 deletions(-) create mode 100644 G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h create mode 100644 G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h create mode 100644 G4CANTESTING/CAN_RELEASE_TEST/can_conf.h create mode 100644 G4CANTESTING/CAN_STRESS_TEST/can_conf.h diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h b/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h new file mode 100644 index 000000000..d9fa87b8a --- /dev/null +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h @@ -0,0 +1,12 @@ + +#ifndef CAN_CONF_H +#define CAN_CONF_H + + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + +#endif diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt index 97c066be9..701da5ea0 100644 --- a/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt @@ -48,5 +48,4 @@ set_target_properties(${NAME} PROPERTIES ) target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) - target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h b/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h new file mode 100644 index 000000000..d9fa87b8a --- /dev/null +++ b/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h @@ -0,0 +1,12 @@ + +#ifndef CAN_CONF_H +#define CAN_CONF_H + + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + +#endif diff --git a/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h b/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h new file mode 100644 index 000000000..d9fa87b8a --- /dev/null +++ b/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h @@ -0,0 +1,12 @@ + +#ifndef CAN_CONF_H +#define CAN_CONF_H + + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + +#endif diff --git a/G4CANTESTING/CAN_STRESS_TEST/can_conf.h b/G4CANTESTING/CAN_STRESS_TEST/can_conf.h new file mode 100644 index 000000000..d9fa87b8a --- /dev/null +++ b/G4CANTESTING/CAN_STRESS_TEST/can_conf.h @@ -0,0 +1,12 @@ + +#ifndef CAN_CONF_H +#define CAN_CONF_H + + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + +#endif diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 2f43ef5c2..f395febee 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -7,12 +7,18 @@ #include "Logomatic.h" -// TODO: Figure out how to move these defines into the application code (by linking) +//#include "can_conf.h" +// TODO: Figure out how to move these defines into the application code + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + +#define USECAN3 +#define TX_BUFFER_3_SIZE 10 -// #define USECAN2 -// #define TX_BUFFER_2_SIZE 10 -// #define USECAN3 -// #define TX_BUFFER_3_SIZE 10 // HAL handles #ifdef USECAN1 diff --git a/Lib/Peripherals/CAN/Test/can_external_test.c b/Lib/Peripherals/CAN/Test/can_external_test.c index 7a92689a6..8f2d3f39c 100644 --- a/Lib/Peripherals/CAN/Test/can_external_test.c +++ b/Lib/Peripherals/CAN/Test/can_external_test.c @@ -13,10 +13,10 @@ return 0; }*/ -#define USECAN1 -#define TX_BUFFER_1_SIZE 10 -#define USECAN2 -#define TX_BUFFER_2_SIZE 10 +//#define USECAN1 +//#define TX_BUFFER_1_SIZE 10 +//#define USECAN2 +//#define TX_BUFFER_2_SIZE 10 // TODO: Make creating these callbacks a macro, rather than defining each one separately static volatile uint32_t rx_2_received = 0; diff --git a/Lib/Peripherals/CAN/Test/can_init_test.c b/Lib/Peripherals/CAN/Test/can_init_test.c index 68e619bab..4300e6e34 100644 --- a/Lib/Peripherals/CAN/Test/can_init_test.c +++ b/Lib/Peripherals/CAN/Test/can_init_test.c @@ -1,7 +1,8 @@ #include "can.h" #include "can_tests.h" -// TODO: + + int can_init_test(CANConfig *cfg) { CANHandle *handle; diff --git a/Lib/Peripherals/CAN/Test/can_internal_test.c b/Lib/Peripherals/CAN/Test/can_internal_test.c index dc2f8d35b..4f99eb13b 100644 --- a/Lib/Peripherals/CAN/Test/can_internal_test.c +++ b/Lib/Peripherals/CAN/Test/can_internal_test.c @@ -13,10 +13,10 @@ return 0; }*/ -#define USECAN1 -#define TX_BUFFER_1_SIZE 10 -#define USECAN2 -#define TX_BUFFER_2_SIZE 10 +//#define USECAN1 1 +//#define TX_BUFFER_1_SIZE 10 +//#define USECAN2 1 +//#define TX_BUFFER_2_SIZE 10 // TODO: Make creating these callbacks a macro, rather than defining each one separately static volatile uint32_t rx_2_received = 0; diff --git a/Lib/Peripherals/CAN/Test/can_release_test.c b/Lib/Peripherals/CAN/Test/can_release_test.c index dfc8fe383..42025e3b7 100644 --- a/Lib/Peripherals/CAN/Test/can_release_test.c +++ b/Lib/Peripherals/CAN/Test/can_release_test.c @@ -1,8 +1,8 @@ #include "can.h" #include "can_tests.h" -#define USECAN1 -#define TX_BUFFER_1_SIZE 10 +//#define USECAN1 +//#define TX_BUFFER_1_SIZE 10 // TODO: int can_release_test() diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c index 9e795e10a..50b62f589 100644 --- a/Lib/Peripherals/CAN/Test/can_stress_test.c +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -3,8 +3,8 @@ #include "can.h" #include "can_tests.h" -#define USECAN1 -#define TX_BUFFER_1_SIZE 10 +//#define USECAN1 +//#define TX_BUFFER_1_SIZE 10 // TODO: static volatile uint32_t can_stress_test_received = 0; diff --git a/Lib/Peripherals/CAN/Test/can_test_helpers.c b/Lib/Peripherals/CAN/Test/can_test_helpers.c index 64c63cb23..27e4f0cc3 100644 --- a/Lib/Peripherals/CAN/Test/can_test_helpers.c +++ b/Lib/Peripherals/CAN/Test/can_test_helpers.c @@ -66,6 +66,8 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback canCfg.rx_callback = callback; +//TODO: Recheck these once you figure out how to define in application code +//#ifdef USECAN1 if (instance == FDCAN1) { canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; @@ -79,8 +81,9 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } +//#endif -#ifdef USECAN2 +//#ifdef USECAN2 if (instance == FDCAN2) { canCfg.fdcan_instance = FDCAN2; canCfg.rx_gpio = GPIOB; @@ -94,10 +97,10 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } -#endif +//#endif -#ifdef USECAN3 -#endif +//#ifdef USECAN3 +//#endif return ERROR; } diff --git a/Lib/Peripherals/CAN/Test/can_tests.h b/Lib/Peripherals/CAN/Test/can_tests.h index 41004c34c..922cf2b09 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.h +++ b/Lib/Peripherals/CAN/Test/can_tests.h @@ -6,10 +6,10 @@ #include "can_platform_deps.h" // Tested STM32 Families -#define USECAN1 -#define TX_BUFFER_2_SIZE 10 -#define USECAN2 -#define TX_BUFFER_3_SIZE 10 +//#define USECAN1 +//#define TX_BUFFER_2_SIZE 10 +//#define USECAN2 +//#define TX_BUFFER_3_SIZE 10 // abstract families extern int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); From 4a44cfd5474d9bc2250b2142c46d3453564ac88d Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:17:09 -0700 Subject: [PATCH 30/44] tested can_external_test.c can_internal_test.c can_stress_test.c, can_release is now verified --- G4CANTESTING/CAN_INTERNAL_TEST/main.c | 2 +- Lib/Peripherals/CAN/Inc/can.h | 6 +- Lib/Peripherals/CAN/README.md | 3 + Lib/Peripherals/CAN/Src/can.c | 78 ++++++++++---------- Lib/Peripherals/CAN/Test/can_external_test.c | 27 +++++-- Lib/Peripherals/CAN/Test/can_internal_test.c | 27 +++++-- Lib/Peripherals/CAN/Test/can_stress_test.c | 50 ++++++++----- 7 files changed, 122 insertions(+), 71 deletions(-) diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/main.c b/G4CANTESTING/CAN_INTERNAL_TEST/main.c index c8632a431..b9186b648 100644 --- a/G4CANTESTING/CAN_INTERNAL_TEST/main.c +++ b/G4CANTESTING/CAN_INTERNAL_TEST/main.c @@ -141,7 +141,7 @@ int main(void) while (1) { /* USER CODE END WHILE */ LOGOMATIC("Main Loop\n"); - LL_mDelay(1000); + LL_mDelay(10000); // Receive on GPIOs // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index a1e91491a..6821ba43c 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -57,8 +57,8 @@ typedef struct { // RX Callback CAN_RXCallback rx_callback; - uint32_t rx_interrupt_priority; - uint32_t tx_interrupt_priority; + uint8_t rx_interrupt_priority; //only 4 bits + uint8_t tx_interrupt_priority; // for release GPIO_TypeDef *rx_gpio; @@ -94,7 +94,5 @@ void can_set_clksource(uint32_t clksource); // ex. LL_RCC_FDCAN_CLKSOURCE_PCLK1 // TODO: Add thread mode vs handler mode checking (None of these functions should be called in handler mode) -// TODO: put this somewhere that someone will read it -// Somewhere in your application, define USECAN1 and TX_BUFFER_1_SIZE #endif // End Header Guard diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index 879bc771e..a50d350c4 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -1,5 +1,8 @@ - USAGE: +- Somewhere in your application, define USECAN1 and TX_BUFFER_1_SIZE + + CANHandle* can_init(CANConfig *config); //user must supply an rx callback function void can_set_clksource(uint32_t LL_RCC_FDCAN_CLKSOURCE); //ex LL_RCC_FDCAN_CLKSOURCE_PCLK1 for STM32G474RE diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index f395febee..04b6253f0 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -184,6 +184,7 @@ CANHandle *can_init(const CANConfig *config) canHandle->tx_gpio = config->tx_gpio; canHandle->rx_pin = config->init_rx_gpio.Pin; canHandle->tx_pin = config->init_tx_gpio.Pin; + canHandle->rx_interrupt_priority = config->rx_interrupt_priority; canHandle->tx_interrupt_priority = config->tx_interrupt_priority; @@ -243,7 +244,11 @@ CANHandle *can_init(const CANConfig *config) if (failure) { can_msp_deinit(canHandle); FDCAN_InstanceDeInit(canHandle->hal_fdcanP); - memset(canHandle + sizeof(FDCAN_HandleTypeDef), 0, sizeof(*canHandle) - sizeof(FDCAN_HandleTypeDef)); // FIXME: Make sure instance is not being overwritten (FDCANx) + + FDCAN_HandleTypeDef *temp = canHandle->hal_fdcanP; + memset(canHandle, 0, sizeof(*canHandle)); // FIXME: Make sure instance is not being overwritten (FDCANx) + canHandle->hal_fdcanP = temp; + return CAN_SUCCESS; } @@ -284,9 +289,8 @@ int can_release(CANHandle *canHandle) // HAL_FDCAN_DeInit(canHandle->hal_fdcanP); resets a little too hard FDCAN_InstanceDeInit(canHandle->hal_fdcanP); - // TODO: Not sure these actually do anything - //__DSB(); // Data Synchronization Barrier - //__ISB(); // Instruction Synchronization Barrier + __DSB(); // Data Synchronization Barrier + __ISB(); // Instruction Synchronization Barrier // free circular buffer contents // GR_CircularBuffer_Free(&(canHandle->tx_buffer)); @@ -301,7 +305,6 @@ int can_release(CANHandle *canHandle) return CAN_SUCCESS; } -// TODO: prevent races conditions on the circular buffer // TODO: Implement timer // lock access to Circular Buffer when sending and dequeuing static void can_tx_dequeue_helper(CANHandle *handle) @@ -311,23 +314,17 @@ static void can_tx_dequeue_helper(CANHandle *handle) return; } - // TODO: use interrupt masking in case any other ISRs need to lock the circular buffer + // use interrupt masking in case any other ISRs need to lock the circular buffer uint32_t basepri = __get_BASEPRI(); - - __set_BASEPRI(handle->tx_interrupt_priority); - // single consumer shouldn't affect state of circular buffer too closely + __set_BASEPRI(handle->tx_interrupt_priority << 4); + // single consumer shouldn't affect state of circular buffer if (handle->tx_elements == 0) { - __set_BASEPRI(basepri); + __set_BASEPRI(basepri << 4); return; } - // uint32_t basepri = __get_basepri(); - //__disable_irq(); - // TODO: No need to lock circular buffer, as this ISR cannot interrupt the thread mode (can_send) - // Can Add to Fifo Q if (HAL_FDCAN_GetTxFifoFreeLevel(handle->hal_fdcanP)) { - // lock the Circular Buffer const FDCANTxMessage *msg = &(handle->tx_buffer[handle->tx_tail]); // should call Tx Buffer Callback once complete @@ -335,7 +332,7 @@ static void can_tx_dequeue_helper(CANHandle *handle) if (status != HAL_OK) { // LOGOMATIC("CAN_tx_helper: failed to add message to FIFO\n"); //FIXME: Logomatic may not work with interrupts disabled - __set_BASEPRI(basepri); + __set_BASEPRI(basepri << 4); return; // Stop trying to send more } // free(msg); // Successfully sent, free the entry in the circular buffer (which is pointed to by tail) @@ -346,7 +343,7 @@ static void can_tx_dequeue_helper(CANHandle *handle) } // alternatively, if fifo is full, tx_dequeue should get called anyways, and we don't need the else statement - __set_BASEPRI(basepri); + __set_BASEPRI(basepri << 4); } int can_send(CANHandle *canHandle, FDCANTxMessage *message) @@ -367,11 +364,10 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) // stop can_tx_dequeue_helper from from interleaving uint32_t basepri = __get_BASEPRI(); - __set_BASEPRI(canHandle->tx_interrupt_priority); + __set_BASEPRI( (canHandle->tx_interrupt_priority) << 4); - // FIXME: get rid of this jank - // if (hardwareEnabled) { - if (HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP) > 0) { + uint32_t free = 0; + if ( (free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP)) > 0) { HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), message->data); uint32_t val = 0; @@ -381,7 +377,7 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) } else { val = CAN_SUCCESS; } - __set_BASEPRI(basepri); + __set_BASEPRI(basepri << 4); return val; } //} @@ -395,7 +391,7 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) canHandle->tx_elements++; // memcpy(&canHandle->tx_buffer[idx], message , sizeof(FDCANTxMessage) ); - __set_BASEPRI(basepri); + __set_BASEPRI(basepri << 4); return CAN_SUCCESS; // added to software buffer /*if (result != 0) { @@ -407,7 +403,7 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) } else { LOGOMATIC("CAN_send: all buffers full\n"); // p } - __set_BASEPRI(basepri); + __set_BASEPRI(basepri << 4); // Both buffers full return CAN_ERROR; } @@ -453,7 +449,7 @@ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) // if (GR_CircularBuffer_IsFull(handle->rx_buffer)) return; FDCAN_RxHeaderTypeDef rx_header; - // TODO: Stack allocation may be unsafe + // TODO: Stack allocation may be unsafe, (but not unsafer than heap) uint8_t rx_data[64] = {0}; // TODO: maybe also use a timer for this? @@ -520,7 +516,7 @@ int can_start(CANHandle *canHandle) IRQn_Type rx0it, txit; rx0it = txit = -1; // TOOD: Check that this is a valid way to initialize an invalid value - if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { + if (can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { LOGOMATIC("can_start: could not obtain irq #s"); return CAN_ERROR; } @@ -553,13 +549,15 @@ int can_stop(CANHandle *canHandle) // stop can interrupts from activating uint32_t prev_priority = __get_BASEPRI(); - __set_BASEPRI(MIN(canHandle->rx_interrupt_priority, canHandle->tx_interrupt_priority)); + __set_BASEPRI(MIN(canHandle->rx_interrupt_priority, canHandle->tx_interrupt_priority) << 4); - HAL_FDCAN_Stop(canHandle->hal_fdcanP); + if (HAL_FDCAN_Stop(canHandle->hal_fdcanP)) { + return ERROR; + } IRQn_Type rx0it, txit; - rx0it = txit = -1; // TODO: Check that this initialization is valid - if (!can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { + rx0it = txit = -1; + if (can_get_irqs(canHandle->hal_fdcanP->Instance, &rx0it, &txit)) { LOGOMATIC("can_stop: could not obtain irq #s"); return CAN_ERROR; } @@ -568,7 +566,7 @@ int can_stop(CANHandle *canHandle) HAL_NVIC_ClearPendingIRQ(rx0it); HAL_NVIC_ClearPendingIRQ(txit); - __set_BASEPRI(prev_priority); + __set_BASEPRI(prev_priority << 4); GPIOx_CLK_DISABLE(canHandle->rx_gpio); GPIOx_CLK_DISABLE(canHandle->tx_gpio); @@ -723,8 +721,8 @@ static int can_msp_deinit(CANHandle *canHandle) // TODO: used to disable GPIOs clocks, but that might affect other peripherals // RCC - fdcan_disable_shared_clock(); - + //fdcan_disable_shared_clock(); + //can only disable clock after resetting all FDCAN instances return CAN_SUCCESS; } @@ -734,10 +732,15 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) hfdcan->Instance->CCCR |= FDCAN_CCCR_INIT; while (!(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT)) ; + hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE; // Disable interrupts - __HAL_FDCAN_DISABLE_IT(hfdcan, FDCAN_IT_LIST_RX_FIFO0 | FDCAN_IT_LIST_RX_FIFO1 | FDCAN_IT_LIST_SMSG | FDCAN_IT_LIST_TX_FIFO_ERROR | FDCAN_IT_LIST_MISC | FDCAN_IT_LIST_BIT_LINE_ERROR | - FDCAN_IT_LIST_PROTOCOL_ERROR); + //__HAL_FDCAN_DISABLE_IT(hfdcan, FDCAN_IT_LIST_RX_FIFO0 | FDCAN_IT_LIST_RX_FIFO1 | FDCAN_IT_LIST_SMSG | FDCAN_IT_LIST_TX_FIFO_ERROR | FDCAN_IT_LIST_MISC | //FDCAN_IT_LIST_BIT_LINE_ERROR | + //FDCAN_IT_LIST_PROTOCOL_ERROR); + + // + CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1)); + // Clear filters // TODO: fix magic numbers @@ -748,11 +751,12 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) // Exit INIT mode hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT; - while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) - ; + while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT); // Update handle state hfdcan->State = HAL_FDCAN_STATE_RESET; + + fdcan_disable_shared_clock(); } // valid only for STM32G4 diff --git a/Lib/Peripherals/CAN/Test/can_external_test.c b/Lib/Peripherals/CAN/Test/can_external_test.c index 8f2d3f39c..437927741 100644 --- a/Lib/Peripherals/CAN/Test/can_external_test.c +++ b/Lib/Peripherals/CAN/Test/can_external_test.c @@ -18,7 +18,7 @@ //#define USECAN2 //#define TX_BUFFER_2_SIZE 10 -// TODO: Make creating these callbacks a macro, rather than defining each one separately +// TODO: could make creating these callbacks a macro, rather than defining each one separately static volatile uint32_t rx_2_received = 0; static void can_test_rx_callback2(uint32_t id, void *data, uint32_t size) { @@ -69,6 +69,9 @@ int can_external_test(void) return ERROR; } + can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); + + //============================================================================================= if ((primary_can = can_init(&cfg1)) == NULL) { LOGOMATIC("Could not initialize primary_can\n"); @@ -101,10 +104,10 @@ int can_external_test(void) LOGOMATIC("Sending %ld messages on each bus...\n", num_messages); while (i < num_messages) { - HAL_Delay(1000); + HAL_Delay(100); msg.data[0] = 0x2; can_send(primary_can, &msg); - HAL_Delay(1000); + HAL_Delay(100); msg.data[0] = 0x10; can_send(data_can, &msg); i += 1; @@ -112,25 +115,39 @@ int can_external_test(void) LOGOMATIC("Received %ld messages on bus1...\n", rx_1_received); LOGOMATIC("Received %ld messages on bus2...\n", rx_2_received); - uint32_t error = false; + + //TODO: Create testing functions to check state of can instance if ((rx_1_received!=num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx1\n"); + } else { + LOGOMATIC("SUCCESS: can_internal_test: received all rx1\n"); } if ((rx_2_received!=num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx2\n"); + } else { + LOGOMATIC("SUCCESS: can_internal_test: received all rx2\n"); } + if (primary_can->tx_elements > 0) { + LOGOMATIC("can_internal_test: FAIL: did not send all messages from tx_buffer\n"); + } + LOGOMATIC("\n"); + uint32_t rc; if ( (rc = can_release(primary_can))) LOGOMATIC("FAIL: can_external_test; could not release primary_can\n"); error |= rc; - if ( (rc = can_release(primary_can))) LOGOMATIC("FAIL: can_external_test; could not release data_can\n"); + if ( (rc = can_release(data_can))) LOGOMATIC("FAIL: can_external_test; could not release data_can\n"); error |= rc; if (error) {return ERROR;} + + LOGOMATIC("can_external_test: SUCCESS\n"); + + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_internal_test.c b/Lib/Peripherals/CAN/Test/can_internal_test.c index 4f99eb13b..86f3e5572 100644 --- a/Lib/Peripherals/CAN/Test/can_internal_test.c +++ b/Lib/Peripherals/CAN/Test/can_internal_test.c @@ -69,18 +69,21 @@ int can_internal_test(void) return ERROR; } + can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); + //============================================================================================= if ((primary_can = can_init(&cfg1)) == NULL) { LOGOMATIC("Could not initialize primary_can\n"); return ERROR; } - HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); + //HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); if ((data_can = can_init(&cfg2)) == NULL) { LOGOMATIC("Could not initialize data_can\n"); return ERROR; } - HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); + //HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); + //============================================================================================= if (can_start(primary_can)) { @@ -101,10 +104,10 @@ int can_internal_test(void) LOGOMATIC("Sending %ld messages on each bus...\n", num_messages); while (i < num_messages) { - HAL_Delay(1000); + HAL_Delay(100); msg.data[0] = 0x2; can_send(primary_can, &msg); - HAL_Delay(1000); + HAL_Delay(100); msg.data[0] = 0x10; can_send(data_can, &msg); i += 1; @@ -112,25 +115,37 @@ int can_internal_test(void) LOGOMATIC("Received %ld messages on bus1...\n", rx_1_received); LOGOMATIC("Received %ld messages on bus2...\n", rx_2_received); - uint32_t error = false; if ((rx_1_received!=num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx1\n"); + } else { + LOGOMATIC("SUCCESS: can_internal_test: received all rx1\n"); } if ((rx_2_received!=num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx2\n"); + } else { + LOGOMATIC("SUCCESS: can_internal_test: received all rx2\n"); + } + + if (primary_can->tx_elements > 0) { + LOGOMATIC("can_internal_test: FAIL: did not send all messages from tx_buffer\n"); } + LOGOMATIC("\n"); + uint32_t rc; if ( (rc = can_release(primary_can)) ) LOGOMATIC("FAIL: can_internal_test; could not release primary_can\n"); error |= rc; - if ( (rc = can_release(primary_can)) ) LOGOMATIC("FAIL: can_internal_test; could not release data_can\n"); + if ( (rc = can_release(data_can)) ) LOGOMATIC("FAIL: can_internal_test; could not release data_can\n"); error |= rc; if (error) {return ERROR;} + LOGOMATIC("can_internal_test: SUCCESS\n"); + + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c index 50b62f589..7daa77826 100644 --- a/Lib/Peripherals/CAN/Test/can_stress_test.c +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -34,6 +34,9 @@ int can_stress_test(void) return ERROR; } + can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); + + FDCAN_TxHeaderTypeDef TxHeader = { .Identifier = 1, @@ -62,44 +65,55 @@ int can_stress_test(void) msg.tx_header = TxHeader; size_t i = 0; - size_t messages = 5; + size_t rounds = 5; + size_t messages = primary_can->tx_capacity * 2; uint32_t successes = 0; - while (i < messages) { + while (loop < rounds) { loop++; can_stress_test_received = 0; i = 0; - while (i < 100) { + while (i < messages) { if (can_send(primary_can, &msg) != 0) { - LOGOMATIC("Stress test failed sending CAN msg at %ud-th consecutive send.\n", (unsigned int)i + 1); + LOGOMATIC("can_stress_test: FAIL: sending CAN msg at %u-th consecutive send.\n", (unsigned int)i + 1); break; } i++; } - LOGOMATIC("Sent %ud CAN msgs...\n", (unsigned int)i); + LOGOMATIC("Sent %u/%u CAN msgs...\n", (unsigned int)i, (unsigned int) messages); HAL_Delay(1000); - LOGOMATIC("Received %ud/%ud CAN msgs after 1 second.\n", (unsigned int)can_stress_test_received, (unsigned int)i); + LOGOMATIC("Received %u/%u CAN msgs after 1 second.\n", (unsigned int)can_stress_test_received, (unsigned int)messages); + + LOGOMATIC("finished loop %ld\n", loop); - if (can_stress_test_received == i) { + if (primary_can->tx_elements > 0) { + LOGOMATIC("can_stress_test: FAIL: did not send all messages from tx_buffer\n"); + continue; + } + LOGOMATIC("\n"); + + if (can_stress_test_received == messages) { successes += 1; } - msg.data[0] = 0x10; - can_send(data_can, &msg); - HAL_Delay(1000); - LOGOMATIC("Stress test finished loop %ld\n", loop); + //msg.data[0] = 0x10; + //can_send(data_can, &msg); + //HAL_Delay(1000); } + + if (can_release(primary_can)) { - LOGOMATIC("can_test; could not release primary_can\n"); + LOGOMATIC("can_stress_test: FAIL: could not release primary_can\n"); return ERROR; } - if (successes != messages) { - LOGOMATIC("can_stress_test failed\n"); - return ERROR; - } - - LOGOMATIC("can_stress_test passed\n"); + //FINAL CHECK + LOGOMATIC("can_stress_test: succeeded %u/%u rounds\n",successes,rounds); + if (successes < rounds) { + LOGOMATIC("can_stress_test: FAIL\n"); + } else { + LOGOMATIC("can_stress_test: SUCCESS\n"); + } return SUCCESS; } From 9b2ebc376cad21d6fe9621efdb37757327ef26dc Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:19:47 -0700 Subject: [PATCH 31/44] deleted unused folders --- G4CANTESTING/EXTERNAL_TEST/main.c | 274 ---------------------- G4CANTESTING/INTERNAL_TEST/CMakeLists.txt | 55 ----- G4CANTESTING/INTERNAL_TEST/main.c | 274 ---------------------- G4CANTESTING/RELEASE_TEST/CMakeLists.txt | 55 ----- G4CANTESTING/RELEASE_TEST/main.c | 274 ---------------------- G4CANTESTING/STRESS_TEST/CMakeLists.txt | 48 ---- G4CANTESTING/STRESS_TEST/main.c | 274 ---------------------- 7 files changed, 1254 deletions(-) delete mode 100644 G4CANTESTING/EXTERNAL_TEST/main.c delete mode 100644 G4CANTESTING/INTERNAL_TEST/CMakeLists.txt delete mode 100644 G4CANTESTING/INTERNAL_TEST/main.c delete mode 100644 G4CANTESTING/RELEASE_TEST/CMakeLists.txt delete mode 100644 G4CANTESTING/RELEASE_TEST/main.c delete mode 100644 G4CANTESTING/STRESS_TEST/CMakeLists.txt delete mode 100644 G4CANTESTING/STRESS_TEST/main.c diff --git a/G4CANTESTING/EXTERNAL_TEST/main.c b/G4CANTESTING/EXTERNAL_TEST/main.c deleted file mode 100644 index 5ac60cf41..000000000 --- a/G4CANTESTING/EXTERNAL_TEST/main.c +++ /dev/null @@ -1,274 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * - * Copyright (c) 2024 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "main.h" - -#include "adc.h" -#include "can.h" // Assume this works -#include "can_tests.h" -#include "dma.h" -#include "fdcan.h" -#include "gpio.h" -#include "i2c.h" -#include "spi.h" -#include "tim.h" -#include "usart.h" - -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include "Logomatic.h" -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ -/* Enable ITM for SWO output */ -static void ITM_Enable(void) -{ - LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); - LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = LL_GPIO_PIN_3; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_0; - LL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; - - /* Enable TRC (Trace) */ - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - - /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ - TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ - TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ - - ITM->TER |= (1UL << 0); - ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); -} -// static int toggleze = 0; -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) -{ - /* USER CODE BEGIN 1 */ - - /* USER CODE END 1 */ - - /* MCU - * Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the - * Systick. */ - HAL_Init(); - /* USER CODE BEGIN Init */ - ITM_Enable(); - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_DMA_Init(); - // MX_FDCAN2_Init(); - MX_ADC1_Init(); - MX_LPUART1_UART_Init(); - MX_I2C2_Init(); - MX_USART1_UART_Init(); - MX_SPI3_Init(); - MX_TIM2_Init(); - - /* USER CODE BEGIN 2 */ - - LOGOMATIC("Booted!\n"); - - LOGOMATIC("running can_external_test:\n"); - can_external_test(); - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - while (1) { - /* USER CODE END WHILE */ - LOGOMATIC("Main Loop\n"); - LL_mDelay(1000); - - // Receive on GPIOs - // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET - // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? - // 0x00 : 0x80; can_send(data_can, &msg); - - // RCC->CFGR |= RCC_CFGR_SW; - /* USER CODE BEGIN 3 */ - } -} - -/** - * @brief System Clock Configuration - * @retval None - */ - -// void SystemClock_Config(void) -// { -// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); -// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { -// } -// LL_PWR_EnableRange1BoostMode(); -// LL_RCC_HSE_Enable(); - -// /* Wait till HSE is ready */ -// while (LL_RCC_HSE_IsReady() != 1) { -// } - -// LL_RCC_HSE_EnableCSS(); -// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, -// LL_RCC_PLLR_DIV_2); -// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); -// LL_RCC_PLL_EnableDomain_SYS(); -// LL_RCC_PLL_Enable(); -// /* Wait till PLL is ready */ -// while (LL_RCC_PLL_IsReady() != 1) { -// } - -// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); -// /* Wait till System clock is ready */ -// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { -// } - -// /* Insure 1us transition state at intermediate medium speed clock*/ -// for (__IO uint32_t i = (170 >> 1); i != 0; i--) -// ; - -// /* Set AHB prescaler*/ -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); -// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); -// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); -// LL_SetSystemCoreClock(160000000); - -// /* Update the time base */ -// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { -// Error_Handler(); -// } -// }*/ -void SystemClock_Config(void) -{ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); - while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} - LL_PWR_EnableRange1BoostMode(); - LL_RCC_HSI_Enable(); - /* Wait till HSI is ready */ - while (LL_RCC_HSI_IsReady() != 1) {} - - LL_RCC_HSI_SetCalibTrimming(64); - LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); - LL_RCC_PLL_EnableDomain_SYS(); - LL_RCC_PLL_Enable(); - /* Wait till PLL is ready */ - while (LL_RCC_PLL_IsReady() != 1) {} - - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - /* Wait till System clock is ready */ - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} - - /* Insure 1us transition state at intermediate medium speed clock*/ - for (__IO uint32_t i = (170 >> 1); i != 0; i--) - ; - - /* Set AHB prescaler*/ - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); - LL_SetSystemCoreClock(170000000); - - /* Update the time base */ - if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ - -/* USER CODE END 4 */ - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) -{ - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return - * state */ - __disable_irq(); - while (1) {} - /* USER CODE END Error_Handler_Debug */ -} -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line - number, ex: printf("Wrong parameters value: file %s on line %d\r\n", - file, line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt deleted file mode 100644 index 8e45c7d12..000000000 --- a/G4CANTESTING/INTERNAL_TEST/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -cmake_minimum_required(VERSION 3.25) - -# Setup compiler settings -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS ON) - -# Define the build type -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Debug") -endif() - -# Enable compile command to ease indexing with e.g. clangd -set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) - -# Enable CMake support for ASM and C languages -enable_language( - C - ASM -) - -# Core project settings -project(${CMAKE_PROJECT_NAME}) - -# what, does in fact not get the filename of somthing but rather the name of the project from the path -get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) - -add_library(${PROJECT_NAME}_USER_CODE INTERFACE) - -target_sources( - ${PROJECT_NAME}_USER_CODE - INTERFACE - ../Core/Src/adc.c - ../Core/Src/crc.c - ../Core/Src/dma.c - ../Core/Src/gpio.c - ../Core/Src/i2c.c - main.c - ../Core/Src/spi.c - ../Core/Src/stm32g4xx_hal_msp.c - ../Core/Src/stm32g4xx_it.c - ../Core/Src/tim.c - ../Core/Src/usart.c -) - -if(FILTER EQUAL 1) - message(HERE) - target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) -else() - message(THERE) -endif() - -target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) - -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/INTERNAL_TEST/main.c b/G4CANTESTING/INTERNAL_TEST/main.c deleted file mode 100644 index 1d09082e2..000000000 --- a/G4CANTESTING/INTERNAL_TEST/main.c +++ /dev/null @@ -1,274 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * - * Copyright (c) 2024 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "main.h" - -#include "adc.h" -#include "can.h" // Assume this works -#include "can_tests.h" -#include "dma.h" -#include "fdcan.h" -#include "gpio.h" -#include "i2c.h" -#include "spi.h" -#include "tim.h" -#include "usart.h" - -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include "Logomatic.h" -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ -/* Enable ITM for SWO output */ -static void ITM_Enable(void) -{ - LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); - LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = LL_GPIO_PIN_3; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_0; - LL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; - - /* Enable TRC (Trace) */ - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - - /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ - TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ - TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ - - ITM->TER |= (1UL << 0); - ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); -} -// static int toggleze = 0; -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) -{ - /* USER CODE BEGIN 1 */ - - /* USER CODE END 1 */ - - /* MCU - * Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the - * Systick. */ - HAL_Init(); - /* USER CODE BEGIN Init */ - ITM_Enable(); - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_DMA_Init(); - // MX_FDCAN2_Init(); - MX_ADC1_Init(); - MX_LPUART1_UART_Init(); - MX_I2C2_Init(); - MX_USART1_UART_Init(); - MX_SPI3_Init(); - MX_TIM2_Init(); - - /* USER CODE BEGIN 2 */ - - LOGOMATIC("Booted!\n"); - - LOGOMATIC("running can_internal_test:\n"); - can_internal_test(); - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - while (1) { - /* USER CODE END WHILE */ - LOGOMATIC("Main Loop\n"); - LL_mDelay(1000); - - // Receive on GPIOs - // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET - // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? - // 0x00 : 0x80; can_send(data_can, &msg); - - // RCC->CFGR |= RCC_CFGR_SW; - /* USER CODE BEGIN 3 */ - } -} - -/** - * @brief System Clock Configuration - * @retval None - */ - -// void SystemClock_Config(void) -// { -// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); -// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { -// } -// LL_PWR_EnableRange1BoostMode(); -// LL_RCC_HSE_Enable(); - -// /* Wait till HSE is ready */ -// while (LL_RCC_HSE_IsReady() != 1) { -// } - -// LL_RCC_HSE_EnableCSS(); -// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, -// LL_RCC_PLLR_DIV_2); -// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); -// LL_RCC_PLL_EnableDomain_SYS(); -// LL_RCC_PLL_Enable(); -// /* Wait till PLL is ready */ -// while (LL_RCC_PLL_IsReady() != 1) { -// } - -// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); -// /* Wait till System clock is ready */ -// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { -// } - -// /* Insure 1us transition state at intermediate medium speed clock*/ -// for (__IO uint32_t i = (170 >> 1); i != 0; i--) -// ; - -// /* Set AHB prescaler*/ -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); -// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); -// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); -// LL_SetSystemCoreClock(160000000); - -// /* Update the time base */ -// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { -// Error_Handler(); -// } -// }*/ -void SystemClock_Config(void) -{ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); - while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} - LL_PWR_EnableRange1BoostMode(); - LL_RCC_HSI_Enable(); - /* Wait till HSI is ready */ - while (LL_RCC_HSI_IsReady() != 1) {} - - LL_RCC_HSI_SetCalibTrimming(64); - LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); - LL_RCC_PLL_EnableDomain_SYS(); - LL_RCC_PLL_Enable(); - /* Wait till PLL is ready */ - while (LL_RCC_PLL_IsReady() != 1) {} - - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - /* Wait till System clock is ready */ - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} - - /* Insure 1us transition state at intermediate medium speed clock*/ - for (__IO uint32_t i = (170 >> 1); i != 0; i--) - ; - - /* Set AHB prescaler*/ - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); - LL_SetSystemCoreClock(170000000); - - /* Update the time base */ - if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ - -/* USER CODE END 4 */ - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) -{ - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return - * state */ - __disable_irq(); - while (1) {} - /* USER CODE END Error_Handler_Debug */ -} -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line - number, ex: printf("Wrong parameters value: file %s on line %d\r\n", - file, line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/RELEASE_TEST/CMakeLists.txt b/G4CANTESTING/RELEASE_TEST/CMakeLists.txt deleted file mode 100644 index 8e45c7d12..000000000 --- a/G4CANTESTING/RELEASE_TEST/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -cmake_minimum_required(VERSION 3.25) - -# Setup compiler settings -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS ON) - -# Define the build type -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Debug") -endif() - -# Enable compile command to ease indexing with e.g. clangd -set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) - -# Enable CMake support for ASM and C languages -enable_language( - C - ASM -) - -# Core project settings -project(${CMAKE_PROJECT_NAME}) - -# what, does in fact not get the filename of somthing but rather the name of the project from the path -get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) - -add_library(${PROJECT_NAME}_USER_CODE INTERFACE) - -target_sources( - ${PROJECT_NAME}_USER_CODE - INTERFACE - ../Core/Src/adc.c - ../Core/Src/crc.c - ../Core/Src/dma.c - ../Core/Src/gpio.c - ../Core/Src/i2c.c - main.c - ../Core/Src/spi.c - ../Core/Src/stm32g4xx_hal_msp.c - ../Core/Src/stm32g4xx_it.c - ../Core/Src/tim.c - ../Core/Src/usart.c -) - -if(FILTER EQUAL 1) - message(HERE) - target_compile_definitions(${PROJECT_NAME}_USER_CODE INTERFACE FILTER) -else() - message(THERE) -endif() - -target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) - -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) diff --git a/G4CANTESTING/RELEASE_TEST/main.c b/G4CANTESTING/RELEASE_TEST/main.c deleted file mode 100644 index 35c016f90..000000000 --- a/G4CANTESTING/RELEASE_TEST/main.c +++ /dev/null @@ -1,274 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * - * Copyright (c) 2024 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "main.h" - -#include "adc.h" -#include "can.h" // Assume this works -#include "can_tests.h" -#include "dma.h" -#include "fdcan.h" -#include "gpio.h" -#include "i2c.h" -#include "spi.h" -#include "tim.h" -#include "usart.h" - -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include "Logomatic.h" -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ -/* Enable ITM for SWO output */ -static void ITM_Enable(void) -{ - LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); - LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = LL_GPIO_PIN_3; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_0; - LL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; - - /* Enable TRC (Trace) */ - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - - /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ - TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ - TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ - - ITM->TER |= (1UL << 0); - ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); -} -// static int toggleze = 0; -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) -{ - /* USER CODE BEGIN 1 */ - - /* USER CODE END 1 */ - - /* MCU - * Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the - * Systick. */ - HAL_Init(); - /* USER CODE BEGIN Init */ - ITM_Enable(); - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_DMA_Init(); - // MX_FDCAN2_Init(); - MX_ADC1_Init(); - MX_LPUART1_UART_Init(); - MX_I2C2_Init(); - MX_USART1_UART_Init(); - MX_SPI3_Init(); - MX_TIM2_Init(); - - /* USER CODE BEGIN 2 */ - - LOGOMATIC("Booted!\n"); - - LOGOMATIC("running can_release_test:\n"); - // can_release_test(); - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - while (1) { - /* USER CODE END WHILE */ - LOGOMATIC("Main Loop\n"); - LL_mDelay(1000); - - // Receive on GPIOs - // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET - // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? - // 0x00 : 0x80; can_send(data_can, &msg); - - // RCC->CFGR |= RCC_CFGR_SW; - /* USER CODE BEGIN 3 */ - } -} - -/** - * @brief System Clock Configuration - * @retval None - */ - -// void SystemClock_Config(void) -// { -// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); -// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { -// } -// LL_PWR_EnableRange1BoostMode(); -// LL_RCC_HSE_Enable(); - -// /* Wait till HSE is ready */ -// while (LL_RCC_HSE_IsReady() != 1) { -// } - -// LL_RCC_HSE_EnableCSS(); -// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, -// LL_RCC_PLLR_DIV_2); -// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); -// LL_RCC_PLL_EnableDomain_SYS(); -// LL_RCC_PLL_Enable(); -// /* Wait till PLL is ready */ -// while (LL_RCC_PLL_IsReady() != 1) { -// } - -// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); -// /* Wait till System clock is ready */ -// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { -// } - -// /* Insure 1us transition state at intermediate medium speed clock*/ -// for (__IO uint32_t i = (170 >> 1); i != 0; i--) -// ; - -// /* Set AHB prescaler*/ -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); -// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); -// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); -// LL_SetSystemCoreClock(160000000); - -// /* Update the time base */ -// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { -// Error_Handler(); -// } -// }*/ -void SystemClock_Config(void) -{ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); - while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} - LL_PWR_EnableRange1BoostMode(); - LL_RCC_HSI_Enable(); - /* Wait till HSI is ready */ - while (LL_RCC_HSI_IsReady() != 1) {} - - LL_RCC_HSI_SetCalibTrimming(64); - LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); - LL_RCC_PLL_EnableDomain_SYS(); - LL_RCC_PLL_Enable(); - /* Wait till PLL is ready */ - while (LL_RCC_PLL_IsReady() != 1) {} - - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - /* Wait till System clock is ready */ - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} - - /* Insure 1us transition state at intermediate medium speed clock*/ - for (__IO uint32_t i = (170 >> 1); i != 0; i--) - ; - - /* Set AHB prescaler*/ - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); - LL_SetSystemCoreClock(170000000); - - /* Update the time base */ - if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ - -/* USER CODE END 4 */ - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) -{ - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return - * state */ - __disable_irq(); - while (1) {} - /* USER CODE END Error_Handler_Debug */ -} -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line - number, ex: printf("Wrong parameters value: file %s on line %d\r\n", - file, line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ diff --git a/G4CANTESTING/STRESS_TEST/CMakeLists.txt b/G4CANTESTING/STRESS_TEST/CMakeLists.txt deleted file mode 100644 index 97567b980..000000000 --- a/G4CANTESTING/STRESS_TEST/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -cmake_minimum_required(VERSION 3.25) - -# Setup compiler settings -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS ON) - -# Define the build type -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Debug") -endif() - -# Enable compile command to ease indexing with e.g. clangd -set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) - -# Enable CMake support for ASM and C languages -enable_language( - C - ASM -) - -# Core project settings -project(${CMAKE_PROJECT_NAME}) - -# what, does in fact not get the filename of somthing but rather the name of the project from the path -get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) - -add_library(${PROJECT_NAME}_USER_CODE INTERFACE) - -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) - -target_sources( - ${PROJECT_NAME}_USER_CODE - INTERFACE - main.c - ../Core/Src/adc.c - ../Core/Src/crc.c - ../Core/Src/dma.c - ../Core/Src/gpio.c - ../Core/Src/i2c.c - ../Core/Src/spi.c - ../Core/Src/stm32g4xx_hal_msp.c - ../Core/Src/stm32g4xx_it.c - ../Core/Src/tim.c - ../Core/Src/usart.c -) - -target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) diff --git a/G4CANTESTING/STRESS_TEST/main.c b/G4CANTESTING/STRESS_TEST/main.c deleted file mode 100644 index 964b7d405..000000000 --- a/G4CANTESTING/STRESS_TEST/main.c +++ /dev/null @@ -1,274 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * - * Copyright (c) 2024 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "main.h" - -#include "adc.h" -#include "can.h" // Assume this works -#include "can_tests.h" -#include "dma.h" -#include "fdcan.h" -#include "gpio.h" -#include "i2c.h" -#include "spi.h" -#include "tim.h" -#include "usart.h" - -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include "Logomatic.h" -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ -/* Enable ITM for SWO output */ -static void ITM_Enable(void) -{ - LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); - LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = LL_GPIO_PIN_3; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_0; - LL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; - - /* Enable TRC (Trace) */ - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - - /* Configure TPI for SWO output (set prescaler for 2MHz SWO clock) */ - TPI->SPPR = 2U; /* 2 = Manchester/async UART mode */ - TPI->ACPR = 84U; /* Prescaler: (170 MHz / (84+1) / 2) ≈ 1MHz SWO */ - - ITM->TER |= (1UL << 0); - ITM->TCR |= (ITM_TCR_ITMENA_Msk | ITM_TCR_SWOENA_Msk); -} -// static int toggleze = 0; -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) -{ - /* USER CODE BEGIN 1 */ - - /* USER CODE END 1 */ - - /* MCU - * Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the - * Systick. */ - HAL_Init(); - /* USER CODE BEGIN Init */ - ITM_Enable(); - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_DMA_Init(); - // MX_FDCAN2_Init(); - MX_ADC1_Init(); - MX_LPUART1_UART_Init(); - MX_I2C2_Init(); - MX_USART1_UART_Init(); - MX_SPI3_Init(); - MX_TIM2_Init(); - - /* USER CODE BEGIN 2 */ - - LOGOMATIC("Booted!\n"); - - LOGOMATIC("running can_stress_test:\n"); - can_stress_test(); - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - while (1) { - /* USER CODE END WHILE */ - LOGOMATIC("Main Loop\n"); - LL_mDelay(1000); - - // Receive on GPIOs - // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, toggleze ? GPIO_PIN_SET - // : GPIO_PIN_RESET); HAL_Delay(1000); msg.data[0] = toggleze ? - // 0x00 : 0x80; can_send(data_can, &msg); - - // RCC->CFGR |= RCC_CFGR_SW; - /* USER CODE BEGIN 3 */ - } -} - -/** - * @brief System Clock Configuration - * @retval None - */ - -// void SystemClock_Config(void) -// { -// LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); -// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) { -// } -// LL_PWR_EnableRange1BoostMode(); -// LL_RCC_HSE_Enable(); - -// /* Wait till HSE is ready */ -// while (LL_RCC_HSE_IsReady() != 1) { -// } - -// LL_RCC_HSE_EnableCSS(); -// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 20, -// LL_RCC_PLLR_DIV_2); -// //LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, ); -// LL_RCC_PLL_EnableDomain_SYS(); -// LL_RCC_PLL_Enable(); -// /* Wait till PLL is ready */ -// while (LL_RCC_PLL_IsReady() != 1) { -// } - -// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); -// /* Wait till System clock is ready */ -// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { -// } - -// /* Insure 1us transition state at intermediate medium speed clock*/ -// for (__IO uint32_t i = (170 >> 1); i != 0; i--) -// ; - -// /* Set AHB prescaler*/ -// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); -// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); -// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); -// LL_SetSystemCoreClock(160000000); - -// /* Update the time base */ -// if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { -// Error_Handler(); -// } -// }*/ -void SystemClock_Config(void) -{ - LL_FLASH_SetLatency(LL_FLASH_LATENCY_4); - while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {} - LL_PWR_EnableRange1BoostMode(); - LL_RCC_HSI_Enable(); - /* Wait till HSI is ready */ - while (LL_RCC_HSI_IsReady() != 1) {} - - LL_RCC_HSI_SetCalibTrimming(64); - LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_4, 85, LL_RCC_PLLR_DIV_2); - LL_RCC_PLL_EnableDomain_SYS(); - LL_RCC_PLL_Enable(); - /* Wait till PLL is ready */ - while (LL_RCC_PLL_IsReady() != 1) {} - - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - // LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - /* Wait till System clock is ready */ - while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {} - - /* Insure 1us transition state at intermediate medium speed clock*/ - for (__IO uint32_t i = (170 >> 1); i != 0; i--) - ; - - /* Set AHB prescaler*/ - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); - LL_SetSystemCoreClock(170000000); - - /* Update the time base */ - if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ - -/* USER CODE END 4 */ - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) -{ - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return - * state */ - __disable_irq(); - while (1) {} - /* USER CODE END Error_Handler_Debug */ -} -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line - number, ex: printf("Wrong parameters value: file %s on line %d\r\n", - file, line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ From 432295c5db95eb39e5107c1a9cd55ae0c73b71b4 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 07:20:31 +0000 Subject: [PATCH 32/44] Automatic Json Format: Standardized formatting automatically --- .vscode/launch.json | 12 ++++++++---- .vscode/tasks.json | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9055b3e9e..1ea38b3a9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -467,7 +467,8 @@ } ] } - },{ + }, + { "cwd": "${workspaceFolder}", "executable": "${command:cmake.buildDirectory}/CAN_EXTERNAL_TEST.elf", "name": "CAN_EXTERNAL_TEST", @@ -497,7 +498,8 @@ } ] } - },{ + }, + { "cwd": "${workspaceFolder}", "executable": "${command:cmake.buildDirectory}/CAN_INTERNAL_TEST.elf", "name": "CAN_INTERNAL_TEST", @@ -527,7 +529,8 @@ } ] } - },{ + }, + { "cwd": "${workspaceFolder}", "executable": "${command:cmake.buildDirectory}/CAN_STRESS_TEST.elf", "name": "CAN_STRESS_TEST", @@ -557,7 +560,8 @@ } ] } - },{ + }, + { "cwd": "${workspaceFolder}", "executable": "${command:cmake.buildDirectory}/CAN_RELEASE_TEST.elf", "name": "CAN_RELEASE_TEST", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 59fd7226d..72190ae69 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -152,7 +152,8 @@ "CMake: configure" ], "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target W3_G4SPI_Receive" - },{ + }, + { "label": "CMake: configure and build CAN_EXTERNAL_TEST", "type": "shell", "dependsOrder": "sequence", @@ -160,7 +161,8 @@ "CMake: configure" ], "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target CAN_EXTERNAL_TEST" - },{ + }, + { "label": "CMake: configure and build CAN_INTERNAL_TEST", "type": "shell", "dependsOrder": "sequence", @@ -168,7 +170,8 @@ "CMake: configure" ], "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target CAN_INTERNAL_TEST" - },{ + }, + { "label": "CMake: configure and build CAN_RELEASE_TEST", "type": "shell", "dependsOrder": "sequence", @@ -176,7 +179,8 @@ "CMake: configure" ], "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target CAN_RELEASE_TEST" - },{ + }, + { "label": "CMake: configure and build CAN_STRESS_TEST", "type": "shell", "dependsOrder": "sequence", From 92d882e25772f382ad54d3e604b188d276f6a1b7 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 07:21:38 +0000 Subject: [PATCH 33/44] Automatic CMake Format: Standardized formatting automatically --- G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt | 7 +++++-- G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt | 7 +++++-- G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt | 7 +++++-- G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt | 4 ---- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt index 97c066be9..18addd99c 100644 --- a/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt @@ -43,8 +43,11 @@ target_sources( ../Core/Src/usart.c ) -set_target_properties(${NAME} PROPERTIES - OUTPUT_NAME "CAN_${NAME}" +set_target_properties( + ${NAME} + PROPERTIES + OUTPUT_NAME + "CAN_${NAME}" ) target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt index 701da5ea0..1d53bfec6 100644 --- a/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt @@ -43,8 +43,11 @@ target_sources( ../Core/Src/usart.c ) -set_target_properties(${NAME} PROPERTIES - OUTPUT_NAME "CAN_${NAME}" +set_target_properties( + ${NAME} + PROPERTIES + OUTPUT_NAME + "CAN_${NAME}" ) target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) diff --git a/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt b/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt index 97c066be9..18addd99c 100644 --- a/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt @@ -43,8 +43,11 @@ target_sources( ../Core/Src/usart.c ) -set_target_properties(${NAME} PROPERTIES - OUTPUT_NAME "CAN_${NAME}" +set_target_properties( + ${NAME} + PROPERTIES + OUTPUT_NAME + "CAN_${NAME}" ) target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) diff --git a/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt b/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt index b6163b1bb..c3f9b49d1 100644 --- a/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt @@ -27,8 +27,6 @@ get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) add_library(${PROJECT_NAME}_USER_CODE INTERFACE) - - target_sources( ${PROJECT_NAME}_USER_CODE INTERFACE @@ -45,8 +43,6 @@ target_sources( ../Core/Src/usart.c ) - - target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) From 9b062ac366055eb212104dbcc8cda106e5835b3a Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 07:23:01 +0000 Subject: [PATCH 34/44] Automatic Clang-Format: Standardized formatting automatically --- G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h | 3 +- G4CANTESTING/CAN_EXTERNAL_TEST/main.c | 2 +- G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h | 3 +- G4CANTESTING/CAN_INTERNAL_TEST/main.c | 2 +- G4CANTESTING/CAN_RELEASE_TEST/can_conf.h | 3 +- G4CANTESTING/CAN_RELEASE_TEST/main.c | 2 +- G4CANTESTING/CAN_STRESS_TEST/can_conf.h | 3 +- G4CANTESTING/CAN_STRESS_TEST/main.c | 2 +- Lib/Peripherals/CAN/Inc/can.h | 3 +- Lib/Peripherals/CAN/Src/can.c | 19 ++++++----- Lib/Peripherals/CAN/Test/can_external_test.c | 32 ++++++++++--------- Lib/Peripherals/CAN/Test/can_init_test.c | 2 -- Lib/Peripherals/CAN/Test/can_internal_test.c | 33 +++++++++++--------- Lib/Peripherals/CAN/Test/can_release_test.c | 20 ++++++------ Lib/Peripherals/CAN/Test/can_stress_test.c | 31 +++++++++--------- Lib/Peripherals/CAN/Test/can_test_helpers.c | 14 ++++----- Lib/Peripherals/CAN/Test/can_tests.h | 8 ++--- 17 files changed, 88 insertions(+), 94 deletions(-) diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h b/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h index d9fa87b8a..f12a970f3 100644 --- a/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h @@ -2,11 +2,10 @@ #ifndef CAN_CONF_H #define CAN_CONF_H - #define USECAN1 #define TX_BUFFER_1_SIZE 10 #define USECAN2 #define TX_BUFFER_2_SIZE 10 -#endif +#endif diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/main.c b/G4CANTESTING/CAN_EXTERNAL_TEST/main.c index 7926c9850..0e46a98e6 100644 --- a/G4CANTESTING/CAN_EXTERNAL_TEST/main.c +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/main.c @@ -133,7 +133,7 @@ int main(void) LOGOMATIC("Booted!\n"); - //LOGOMATIC("running can_external_test:\n"); + // LOGOMATIC("running can_external_test:\n"); can_external_test(); /* Infinite loop */ diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h b/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h index d9fa87b8a..f12a970f3 100644 --- a/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h +++ b/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h @@ -2,11 +2,10 @@ #ifndef CAN_CONF_H #define CAN_CONF_H - #define USECAN1 #define TX_BUFFER_1_SIZE 10 #define USECAN2 #define TX_BUFFER_2_SIZE 10 -#endif +#endif diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/main.c b/G4CANTESTING/CAN_INTERNAL_TEST/main.c index b9186b648..9c2f2b7a4 100644 --- a/G4CANTESTING/CAN_INTERNAL_TEST/main.c +++ b/G4CANTESTING/CAN_INTERNAL_TEST/main.c @@ -133,7 +133,7 @@ int main(void) LOGOMATIC("Booted!\n"); - //LOGOMATIC("running can_internal_test:\n"); + // LOGOMATIC("running can_internal_test:\n"); can_internal_test(); /* Infinite loop */ diff --git a/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h b/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h index d9fa87b8a..f12a970f3 100644 --- a/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h +++ b/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h @@ -2,11 +2,10 @@ #ifndef CAN_CONF_H #define CAN_CONF_H - #define USECAN1 #define TX_BUFFER_1_SIZE 10 #define USECAN2 #define TX_BUFFER_2_SIZE 10 -#endif +#endif diff --git a/G4CANTESTING/CAN_RELEASE_TEST/main.c b/G4CANTESTING/CAN_RELEASE_TEST/main.c index ece53ba15..a3197bb29 100644 --- a/G4CANTESTING/CAN_RELEASE_TEST/main.c +++ b/G4CANTESTING/CAN_RELEASE_TEST/main.c @@ -133,7 +133,7 @@ int main(void) LOGOMATIC("Booted!\n"); - //LOGOMATIC("running can_release_test:\n"); + // LOGOMATIC("running can_release_test:\n"); can_release_test(); /* Infinite loop */ diff --git a/G4CANTESTING/CAN_STRESS_TEST/can_conf.h b/G4CANTESTING/CAN_STRESS_TEST/can_conf.h index d9fa87b8a..f12a970f3 100644 --- a/G4CANTESTING/CAN_STRESS_TEST/can_conf.h +++ b/G4CANTESTING/CAN_STRESS_TEST/can_conf.h @@ -2,11 +2,10 @@ #ifndef CAN_CONF_H #define CAN_CONF_H - #define USECAN1 #define TX_BUFFER_1_SIZE 10 #define USECAN2 #define TX_BUFFER_2_SIZE 10 -#endif +#endif diff --git a/G4CANTESTING/CAN_STRESS_TEST/main.c b/G4CANTESTING/CAN_STRESS_TEST/main.c index 6939cbe9f..3e6f61c53 100644 --- a/G4CANTESTING/CAN_STRESS_TEST/main.c +++ b/G4CANTESTING/CAN_STRESS_TEST/main.c @@ -133,7 +133,7 @@ int main(void) LOGOMATIC("Booted!\n"); - //LOGOMATIC("running can_stress_test:\n"); + // LOGOMATIC("running can_stress_test:\n"); can_stress_test(); /* Infinite loop */ diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index 6821ba43c..484d36ce2 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -57,7 +57,7 @@ typedef struct { // RX Callback CAN_RXCallback rx_callback; - uint8_t rx_interrupt_priority; //only 4 bits + uint8_t rx_interrupt_priority; // only 4 bits uint8_t tx_interrupt_priority; // for release @@ -94,5 +94,4 @@ void can_set_clksource(uint32_t clksource); // ex. LL_RCC_FDCAN_CLKSOURCE_PCLK1 // TODO: Add thread mode vs handler mode checking (None of these functions should be called in handler mode) - #endif // End Header Guard diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 04b6253f0..169af55c4 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -7,8 +7,8 @@ #include "Logomatic.h" -//#include "can_conf.h" -// TODO: Figure out how to move these defines into the application code +// #include "can_conf.h" +// TODO: Figure out how to move these defines into the application code #define USECAN1 #define TX_BUFFER_1_SIZE 10 @@ -19,7 +19,6 @@ #define USECAN3 #define TX_BUFFER_3_SIZE 10 - // HAL handles #ifdef USECAN1 #ifndef TX_BUFFER_1_SIZE @@ -364,10 +363,10 @@ int can_send(CANHandle *canHandle, FDCANTxMessage *message) // stop can_tx_dequeue_helper from from interleaving uint32_t basepri = __get_BASEPRI(); - __set_BASEPRI( (canHandle->tx_interrupt_priority) << 4); + __set_BASEPRI((canHandle->tx_interrupt_priority) << 4); uint32_t free = 0; - if ( (free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP)) > 0) { + if ((free = HAL_FDCAN_GetTxFifoFreeLevel(canHandle->hal_fdcanP)) > 0) { HAL_StatusTypeDef status = HAL_FDCAN_AddMessageToTxFifoQ(canHandle->hal_fdcanP, &(message->tx_header), message->data); uint32_t val = 0; @@ -721,8 +720,8 @@ static int can_msp_deinit(CANHandle *canHandle) // TODO: used to disable GPIOs clocks, but that might affect other peripherals // RCC - //fdcan_disable_shared_clock(); - //can only disable clock after resetting all FDCAN instances + // fdcan_disable_shared_clock(); + // can only disable clock after resetting all FDCAN instances return CAN_SUCCESS; } @@ -736,12 +735,11 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) // Disable interrupts //__HAL_FDCAN_DISABLE_IT(hfdcan, FDCAN_IT_LIST_RX_FIFO0 | FDCAN_IT_LIST_RX_FIFO1 | FDCAN_IT_LIST_SMSG | FDCAN_IT_LIST_TX_FIFO_ERROR | FDCAN_IT_LIST_MISC | //FDCAN_IT_LIST_BIT_LINE_ERROR | - //FDCAN_IT_LIST_PROTOCOL_ERROR); + // FDCAN_IT_LIST_PROTOCOL_ERROR); // CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1)); - // Clear filters // TODO: fix magic numbers memset((void *)hfdcan->msgRam.StandardFilterSA, 0, 0x0070); @@ -751,7 +749,8 @@ static void FDCAN_InstanceDeInit(FDCAN_HandleTypeDef *hfdcan) // Exit INIT mode hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT; - while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT); + while (hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) + ; // Update handle state hfdcan->State = HAL_FDCAN_STATE_RESET; diff --git a/Lib/Peripherals/CAN/Test/can_external_test.c b/Lib/Peripherals/CAN/Test/can_external_test.c index 437927741..682f191be 100644 --- a/Lib/Peripherals/CAN/Test/can_external_test.c +++ b/Lib/Peripherals/CAN/Test/can_external_test.c @@ -13,10 +13,10 @@ return 0; }*/ -//#define USECAN1 -//#define TX_BUFFER_1_SIZE 10 -//#define USECAN2 -//#define TX_BUFFER_2_SIZE 10 +// #define USECAN1 +// #define TX_BUFFER_1_SIZE 10 +// #define USECAN2 +// #define TX_BUFFER_2_SIZE 10 // TODO: could make creating these callbacks a macro, rather than defining each one separately static volatile uint32_t rx_2_received = 0; @@ -71,7 +71,6 @@ int can_external_test(void) can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); - //============================================================================================= if ((primary_can = can_init(&cfg1)) == NULL) { LOGOMATIC("Could not initialize primary_can\n"); @@ -117,15 +116,14 @@ int can_external_test(void) uint32_t error = false; - - //TODO: Create testing functions to check state of can instance - if ((rx_1_received!=num_messages)) { + // TODO: Create testing functions to check state of can instance + if ((rx_1_received != num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx1\n"); } else { LOGOMATIC("SUCCESS: can_internal_test: received all rx1\n"); } - if ((rx_2_received!=num_messages)) { + if ((rx_2_received != num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx2\n"); } else { @@ -133,21 +131,25 @@ int can_external_test(void) } if (primary_can->tx_elements > 0) { - LOGOMATIC("can_internal_test: FAIL: did not send all messages from tx_buffer\n"); + LOGOMATIC("can_internal_test: FAIL: did not send all messages from tx_buffer\n"); } LOGOMATIC("\n"); uint32_t rc; - if ( (rc = can_release(primary_can))) LOGOMATIC("FAIL: can_external_test; could not release primary_can\n"); + if ((rc = can_release(primary_can))) { + LOGOMATIC("FAIL: can_external_test; could not release primary_can\n"); + } error |= rc; - if ( (rc = can_release(data_can))) LOGOMATIC("FAIL: can_external_test; could not release data_can\n"); + if ((rc = can_release(data_can))) { + LOGOMATIC("FAIL: can_external_test; could not release data_can\n"); + } error |= rc; - if (error) {return ERROR;} - + if (error) { + return ERROR; + } LOGOMATIC("can_external_test: SUCCESS\n"); - return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_init_test.c b/Lib/Peripherals/CAN/Test/can_init_test.c index 4300e6e34..a58e253b3 100644 --- a/Lib/Peripherals/CAN/Test/can_init_test.c +++ b/Lib/Peripherals/CAN/Test/can_init_test.c @@ -1,8 +1,6 @@ #include "can.h" #include "can_tests.h" - - int can_init_test(CANConfig *cfg) { CANHandle *handle; diff --git a/Lib/Peripherals/CAN/Test/can_internal_test.c b/Lib/Peripherals/CAN/Test/can_internal_test.c index 86f3e5572..2976feecf 100644 --- a/Lib/Peripherals/CAN/Test/can_internal_test.c +++ b/Lib/Peripherals/CAN/Test/can_internal_test.c @@ -13,10 +13,10 @@ return 0; }*/ -//#define USECAN1 1 -//#define TX_BUFFER_1_SIZE 10 -//#define USECAN2 1 -//#define TX_BUFFER_2_SIZE 10 +// #define USECAN1 1 +// #define TX_BUFFER_1_SIZE 10 +// #define USECAN2 1 +// #define TX_BUFFER_2_SIZE 10 // TODO: Make creating these callbacks a macro, rather than defining each one separately static volatile uint32_t rx_2_received = 0; @@ -76,14 +76,13 @@ int can_internal_test(void) LOGOMATIC("Could not initialize primary_can\n"); return ERROR; } - //HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); + // HAL_FDCAN_ConfigGlobalFilter(primary_can->hal_fdcanP, 0, 0, 0, 0); if ((data_can = can_init(&cfg2)) == NULL) { LOGOMATIC("Could not initialize data_can\n"); return ERROR; } - //HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); - + // HAL_FDCAN_ConfigGlobalFilter(data_can->hal_fdcanP, 0, 0, 0, 0); //============================================================================================= if (can_start(primary_can)) { @@ -117,13 +116,13 @@ int can_internal_test(void) uint32_t error = false; - if ((rx_1_received!=num_messages)) { + if ((rx_1_received != num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx1\n"); } else { LOGOMATIC("SUCCESS: can_internal_test: received all rx1\n"); } - if ((rx_2_received!=num_messages)) { + if ((rx_2_received != num_messages)) { error = true; LOGOMATIC("FAIL: can_internal_test: did not receive all rx2\n"); } else { @@ -131,21 +130,25 @@ int can_internal_test(void) } if (primary_can->tx_elements > 0) { - LOGOMATIC("can_internal_test: FAIL: did not send all messages from tx_buffer\n"); + LOGOMATIC("can_internal_test: FAIL: did not send all messages from tx_buffer\n"); } LOGOMATIC("\n"); - uint32_t rc; - if ( (rc = can_release(primary_can)) ) LOGOMATIC("FAIL: can_internal_test; could not release primary_can\n"); + if ((rc = can_release(primary_can))) { + LOGOMATIC("FAIL: can_internal_test; could not release primary_can\n"); + } error |= rc; - if ( (rc = can_release(data_can)) ) LOGOMATIC("FAIL: can_internal_test; could not release data_can\n"); + if ((rc = can_release(data_can))) { + LOGOMATIC("FAIL: can_internal_test; could not release data_can\n"); + } error |= rc; - if (error) {return ERROR;} + if (error) { + return ERROR; + } LOGOMATIC("can_internal_test: SUCCESS\n"); - return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_release_test.c b/Lib/Peripherals/CAN/Test/can_release_test.c index 42025e3b7..0dcd710a0 100644 --- a/Lib/Peripherals/CAN/Test/can_release_test.c +++ b/Lib/Peripherals/CAN/Test/can_release_test.c @@ -1,21 +1,21 @@ #include "can.h" #include "can_tests.h" -//#define USECAN1 -//#define TX_BUFFER_1_SIZE 10 +// #define USECAN1 +// #define TX_BUFFER_1_SIZE 10 // TODO: int can_release_test() { - LOGOMATIC("running can_release_test\n"); + LOGOMATIC("running can_release_test\n"); - CANConfig cfg; + CANConfig cfg; if (get_cfg(FDCAN1, NULL, &cfg, FDCAN_MODE_NORMAL)) { LOGOMATIC("Could not get config for FDCAN1\n"); return ERROR; } - CANHandle *can = NULL; + CANHandle *can = NULL; //============================================================================================= if ((can = can_init(&cfg)) == NULL) { @@ -23,17 +23,17 @@ int can_release_test() return ERROR; } - FDCAN_HandleTypeDef * temp = can->hal_fdcanP; - if (can_release(can)) { + FDCAN_HandleTypeDef *temp = can->hal_fdcanP; + if (can_release(can)) { LOGOMATIC("can_release: Could not release can\n"); return ERROR; } - //test state of canHandle after release - if (temp != can->hal_fdcanP) { + // test state of canHandle after release + if (temp != can->hal_fdcanP) { LOGOMATIC("can_release: cleared handle incorrectly\n"); return ERROR; } - return SUCCESS; + return SUCCESS; } diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c index 7daa77826..cbdbe1b94 100644 --- a/Lib/Peripherals/CAN/Test/can_stress_test.c +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -3,8 +3,8 @@ #include "can.h" #include "can_tests.h" -//#define USECAN1 -//#define TX_BUFFER_1_SIZE 10 +// #define USECAN1 +// #define TX_BUFFER_1_SIZE 10 // TODO: static volatile uint32_t can_stress_test_received = 0; @@ -19,7 +19,7 @@ void can_stress_test_rx_callback(uint32_t id, void *data, uint32_t size) int can_stress_test(void) { - LOGOMATIC("running can_stress_test\n"); + LOGOMATIC("running can_stress_test\n"); uint32_t status, loop; UNUSED(status); @@ -36,7 +36,6 @@ int can_stress_test(void) can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); - FDCAN_TxHeaderTypeDef TxHeader = { .Identifier = 1, @@ -67,7 +66,7 @@ int can_stress_test(void) size_t i = 0; size_t rounds = 5; size_t messages = primary_can->tx_capacity * 2; - uint32_t successes = 0; + uint32_t successes = 0; while (loop < rounds) { loop++; can_stress_test_received = 0; @@ -79,7 +78,7 @@ int can_stress_test(void) } i++; } - LOGOMATIC("Sent %u/%u CAN msgs...\n", (unsigned int)i, (unsigned int) messages); + LOGOMATIC("Sent %u/%u CAN msgs...\n", (unsigned int)i, (unsigned int)messages); HAL_Delay(1000); LOGOMATIC("Received %u/%u CAN msgs after 1 second.\n", (unsigned int)can_stress_test_received, (unsigned int)messages); @@ -92,23 +91,21 @@ int can_stress_test(void) } LOGOMATIC("\n"); - if (can_stress_test_received == messages) { - successes += 1; - } - //msg.data[0] = 0x10; - //can_send(data_can, &msg); - //HAL_Delay(1000); + if (can_stress_test_received == messages) { + successes += 1; + } + // msg.data[0] = 0x10; + // can_send(data_can, &msg); + // HAL_Delay(1000); } - - if (can_release(primary_can)) { LOGOMATIC("can_stress_test: FAIL: could not release primary_can\n"); - return ERROR; + return ERROR; } - //FINAL CHECK - LOGOMATIC("can_stress_test: succeeded %u/%u rounds\n",successes,rounds); + // FINAL CHECK + LOGOMATIC("can_stress_test: succeeded %u/%u rounds\n", successes, rounds); if (successes < rounds) { LOGOMATIC("can_stress_test: FAIL\n"); } else { diff --git a/Lib/Peripherals/CAN/Test/can_test_helpers.c b/Lib/Peripherals/CAN/Test/can_test_helpers.c index 27e4f0cc3..28ff67898 100644 --- a/Lib/Peripherals/CAN/Test/can_test_helpers.c +++ b/Lib/Peripherals/CAN/Test/can_test_helpers.c @@ -66,8 +66,8 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback canCfg.rx_callback = callback; -//TODO: Recheck these once you figure out how to define in application code -//#ifdef USECAN1 + // TODO: Recheck these once you figure out how to define in application code + // #ifdef USECAN1 if (instance == FDCAN1) { canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; @@ -81,9 +81,9 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } -//#endif + // #endif -//#ifdef USECAN2 + // #ifdef USECAN2 if (instance == FDCAN2) { canCfg.fdcan_instance = FDCAN2; canCfg.rx_gpio = GPIOB; @@ -97,10 +97,10 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } -//#endif + // #endif -//#ifdef USECAN3 -//#endif + // #ifdef USECAN3 + // #endif return ERROR; } diff --git a/Lib/Peripherals/CAN/Test/can_tests.h b/Lib/Peripherals/CAN/Test/can_tests.h index 922cf2b09..e202c3079 100644 --- a/Lib/Peripherals/CAN/Test/can_tests.h +++ b/Lib/Peripherals/CAN/Test/can_tests.h @@ -6,10 +6,10 @@ #include "can_platform_deps.h" // Tested STM32 Families -//#define USECAN1 -//#define TX_BUFFER_2_SIZE 10 -//#define USECAN2 -//#define TX_BUFFER_3_SIZE 10 +// #define USECAN1 +// #define TX_BUFFER_2_SIZE 10 +// #define USECAN2 +// #define TX_BUFFER_3_SIZE 10 // abstract families extern int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); From c823f4e2f733ac4c22ae31eaf42227eb106ff7d4 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:23:59 -0700 Subject: [PATCH 35/44] fixed for Release and Debug --- Lib/Peripherals/CAN/Test/can_stress_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c index cbdbe1b94..a587fa56e 100644 --- a/Lib/Peripherals/CAN/Test/can_stress_test.c +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -105,7 +105,7 @@ int can_stress_test(void) } // FINAL CHECK - LOGOMATIC("can_stress_test: succeeded %u/%u rounds\n", successes, rounds); + LOGOMATIC("can_stress_test: succeeded %u/%u rounds\n",(unsigned int) successes,(unsigned int) rounds); if (successes < rounds) { LOGOMATIC("can_stress_test: FAIL\n"); } else { From f2e9b20010cfb6dbbfe801b9c8b652db081cd894 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 07:32:00 +0000 Subject: [PATCH 36/44] Automatic Clang-Format: Standardized formatting automatically --- Lib/Peripherals/CAN/Test/can_stress_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/Peripherals/CAN/Test/can_stress_test.c b/Lib/Peripherals/CAN/Test/can_stress_test.c index a587fa56e..cf3715f5c 100644 --- a/Lib/Peripherals/CAN/Test/can_stress_test.c +++ b/Lib/Peripherals/CAN/Test/can_stress_test.c @@ -105,7 +105,7 @@ int can_stress_test(void) } // FINAL CHECK - LOGOMATIC("can_stress_test: succeeded %u/%u rounds\n",(unsigned int) successes,(unsigned int) rounds); + LOGOMATIC("can_stress_test: succeeded %u/%u rounds\n", (unsigned int)successes, (unsigned int)rounds); if (successes < rounds) { LOGOMATIC("can_stress_test: FAIL\n"); } else { From c759e4353a1cc506e53631de86ca1c1860cef253 Mon Sep 17 00:00:00 2001 From: "vihanjay@gmail.com" <55373538+VihanJ@users.noreply.github.com> Date: Thu, 12 Mar 2026 01:03:19 -0700 Subject: [PATCH 37/44] added documentation with my good friend chat gibidi --- Lib/Peripherals/CAN/Inc/can.h | 4 + Lib/Peripherals/CAN/README.md | 248 +++++++++++++----- .../can_cfg_helpers.c} | 0 Lib/Peripherals/CAN/TESTING.md | 207 +++++++++++++++ Lib/Peripherals/CAN/common.cmake | 6 +- 5 files changed, 403 insertions(+), 62 deletions(-) rename Lib/Peripherals/CAN/{Test/can_test_helpers.c => Src/can_cfg_helpers.c} (100%) create mode 100644 Lib/Peripherals/CAN/TESTING.md diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index 484d36ce2..770ae841b 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -94,4 +94,8 @@ void can_set_clksource(uint32_t clksource); // ex. LL_RCC_FDCAN_CLKSOURCE_PCLK1 // TODO: Add thread mode vs handler mode checking (None of these functions should be called in handler mode) + +//Configuration helpers +int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); + #endif // End Header Guard diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index a50d350c4..cbacedf62 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -1,79 +1,207 @@ -- USAGE: +# Gaucho Racing CAN API Reference -- Somewhere in your application, define USECAN1 and TX_BUFFER_1_SIZE +This document provides an overview of the Gaucho Racing CAN API, a simplified wrapper for STM32 FDCAN peripherals (specifically STM32G4). It handles hardware initialization, interrupt-driven message transmission with software buffering, and simplified receiver callbacks. +--- -CANHandle* can_init(CANConfig *config); //user must supply an rx callback function +# Build Usage -void can_set_clksource(uint32_t LL_RCC_FDCAN_CLKSOURCE); //ex LL_RCC_FDCAN_CLKSOURCE_PCLK1 for STM32G474RE +Somewhere in your application, define: -int can_start(CANHandle*handle); -int can_stop(CANHandle*handle); -int can_send(CANHandle*handle, FDCANMessage* buffer, size_t send); -int can_release(CANHandle* handle); //deinit circular buffer and turn off can peripheral and gpios -int can_add_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef * filter); -int can_add_global_filter(CANHandle* handle, HAL_FDCAN_FilterTypeDef* filter); +```c +#define USECAN1 +#define TX_BUFFER_1_SIZE +``` -//alternatively instead use the HAL filter functions -//HAL_FDCAN_ConfigGlobalFilter(canHandle->hal_fdcanP, filterTypeDef) -//HAL_FDCAN_ConfigFilter(ca) +--- -If no filters are set, the default behaviour is to accept all standard and extended frames into the RXFIFO0 +# 1. Quick Start Workflow -PROBLEMS: -Verify ISR safety, no race conditions, atomic read/writes - - Interrupts keep firing while trying to can_release() - - Could try to set the NVIC register to selectively disable interrupts (preferably using a bitmask) -- Need to discuss expected behaviour of API - - particularly can_start, can_stop - - can_release -- Freeing within ISRs whenever popping from CircularBuffer (yes its faster, than stack copies, but heap is getting fragmented) -- ISRS might take too long to resolve because popping and freeing circular buffer. +1. **Set Clock Source** + Call `can_set_clksource` before any other operation. -- HARDCODE Platform Usage Flag for compiler definitions -- CAN.H expects #STM32G4 to be defined, +2. **Define Callback** + Create a function to handle incoming messages. -- RX Callback must perform deep copy of data supplied to it - could also malloc, but not safe to do inside ISRs +3. **Configure** + Use `get_cfg` helper or fill a `CANConfig` struct. --Shouldn't disable GPIOs in the MSP layers when releasing, might affect other peripherals +4. **Initialize** + Call `can_init`. -IDEAS for other features: -- -- DMA support for copying 64 bytes from circular buffer -- abstract to different STM families besides STM32G4 -- Rx Buffering -- TX Buffering policy, do we spread them out over multiple TX buffers -- DMA support for copying from circular buffer, circular buffer could then be stack allocated -- Smaller can headers for tx and rx (right now its just use the TXHeaderTypeDef) -- TX FIFO vs Queue policy (only allow FIFOS) -- Add support for RXFifo1 +5. **Start** + Call `can_start` to enable the peripheral and interrupts. -TESTING- ---------------------------------------------- -USE LOGOMATIC for return status - -either returns through semihosting or debug cores -LOGOMATIC is defined platform by platform +6. **Communicate** + Use `can_send` to transmit data. -Testing framework -- Can operate on API states and behaviours, but API should work across platforms -- All API tests are defined in can_test.c -- All tests are run from the top level function in can_test.c +--- -- can_test.c should initialize everything properly. -- use LOGOMATIC to return errors or throw asserts +# 2. Global Configuration -- Platform testing, such as in G4PERTESTING just needs include "can_test.h" and call top level function -in main. +## `can_set_clksource` -Two approaches: -Platform centric -- In G4PERTesting, include "can_tests.h" and call the top level function in can_test.c -- This approach is better because we can abstract the logging and debug method +Sets the FDCAN kernel clock, which must be common across all CAN instances. -Library Centric Testing: -- Test the implementation in each library. +**Parameter** -HAL_Rewrite: -- Alternatively, rewrite without using HAL, just use CMSIS definitions. -- There isn't actually that much going on underneath HAL, it just looks painful because of CMSIS -- PROS: Would look good on your Github. -- CONS: takes too long +```c +uint32_t clksource +``` + +Example: + +```c +LL_RCC_FDCAN_CLKSOURCE_PCLK1 +``` + +**Usage** + +Must be called once before `can_init`. + +--- + +# 3. Initialization and Setup + +## `CANConfig` Structure + +This structure contains all parameters required to bridge the Gaucho API with the underlying STM32 HAL. + +| Field | Description | +|------|-------------| +| `fdcan_instance` | Base address (e.g., `FDCAN1`, `FDCAN2`). | +| `hal_fdcan_init` | Standard HAL `FDCAN_InitTypeDef` struct (baud rate, etc). | +| `rx_callback` | Your custom handler for received messages. | +| `rx_interrupt_priority` | Priority for RX interrupts (0–15). | +| `tx_interrupt_priority` | Priority for TX interrupts (0–15). | +| `rx_gpio` / `tx_gpio` | GPIO Port and Init structures for CAN pins. | + +--- + +## Configuration Helper + +Instead of filling the `CANConfig` manually, use the helper function in `can_cfg_helpers.c`: + +```c +int get_cfg( + FDCAN_GlobalTypeDef *instance, + CAN_RXCallback callback, + CANConfig *out_cfg, + uint32_t Mode +); +``` + +--- + +# 4. Example Usage + +## Define RX Callback + +```c +void on_receive(uint32_t ID, void *data, uint32_t size) +{ + uint8_t my_data[64]; + + memcpy(my_data, data, size); + + // Process my_data... +} +``` + +--- + +## Initialize CAN + +```c +can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); + +CANConfig my_cfg; + +get_cfg(FDCAN1, on_receive, &my_cfg, FDCAN_MODE_NORMAL); + +CANHandle *h1 = can_init(&my_cfg); +``` + +--- + +## Start and Send + +```c +can_start(h1); + +FDCANTxMessage msg = { ... }; // Fill header and data + +can_send(h1, &msg); +``` + +--- + +# 5. Callback Definition + +```c +void MyCAN_RxCallback(uint32_t ID, void *data, uint32_t size); +``` + +--- + +# 6. Communication + +## `can_send` + +Sends a message using a `FDCANTxMessage` struct. + +**Behavior** + +If the hardware FIFO is full, the message is automatically queued in a software buffer. + +**Returns** + +``` +CAN_SUCCESS +CAN_ERROR +``` + +--- + +## `can_add_filter` + +Adds a hardware-level filter to the instance. + +**Constraint** + +Must be called while the peripheral is initialized but **not yet started**. + + + +# Implementation Notes and Constraints + +- `RX Callback` must perform a **deep copy** of the data supplied to it. +- Allocating memory using `malloc` inside ISRs is **not safe**. +- `can.h` expects `STM32G4` to be defined as a compiler definition. +- Platform usage flags may be **hardcoded through compiler definitions**. +- GPIOs should **not be disabled in MSP layers during release**, as they may affect other peripherals. + +--- + +# Known Issues / Current Problems + +- ISRs may take **too long to resolve** due to popping and freeing the circular buffer. + +--- + +# Ideas and Future Improvements + +- DMA support for copying **64 bytes from circular buffer** +- Abstract support for **different STM32 families** besides STM32G4 +- RX buffering support +- TX buffering policy improvements + - Possibly distribute messages across multiple TX buffers +- DMA support for copying from circular buffer + - Circular buffer could then be **stack allocated** +- Smaller CAN headers for TX/RX + - Currently uses `TXHeaderTypeDef` +- TX FIFO vs Queue policy + - Possibly only allow **FIFO** +- Add support for **RXFifo1** + +--- diff --git a/Lib/Peripherals/CAN/Test/can_test_helpers.c b/Lib/Peripherals/CAN/Src/can_cfg_helpers.c similarity index 100% rename from Lib/Peripherals/CAN/Test/can_test_helpers.c rename to Lib/Peripherals/CAN/Src/can_cfg_helpers.c diff --git a/Lib/Peripherals/CAN/TESTING.md b/Lib/Peripherals/CAN/TESTING.md new file mode 100644 index 000000000..8b1e82cd7 --- /dev/null +++ b/Lib/Peripherals/CAN/TESTING.md @@ -0,0 +1,207 @@ + +# Initializing a CAN Test + +This section describes how to initialize and run a CAN test using the project `CAN_STRESS_TEST` as an example. +The test entry point is implemented in `main.c`, and the project is built through the top-level `CMakeLists.txt`. + +--- + +# 1. Enabling the Test in CMake + +CAN tests are built as independent firmware projects through the helper macro: + +``` +add_gr_project() +``` + +In `CMakeLists.txt`, the stress test is enabled with: + +``` +add_gr_project(STM32G474xE G4CANTESTING CAN_STRESS_TEST) +``` + +This line instructs CMake to: + +- Create a firmware target for the **STM32G474xE platform** +- Use the **G4CANTESTING project template** +- Build the firmware located in the **CAN_STRESS_TEST directory** + +Other CAN test variants are defined in the same section: + +``` +add_gr_project(STM32G474xE G4CANTESTING CAN_EXTERNAL_TEST) +add_gr_project(STM32G474xE G4CANTESTING CAN_INTERNAL_TEST) +add_gr_project(STM32G474xE G4CANTESTING CAN_RELEASE_TEST) +add_gr_project(STM32G474xE G4CANTESTING CAN_STRESS_TEST) +``` + +These targets allow different test scenarios to be compiled independently. + +--- + +# 2. Required CAN Library Inclusion + +The CAN API and related utilities are included through CMake modules: + +``` +include("${lib_path}/Peripherals/CAN/common.cmake") +``` + +These modules provide: + +- CAN peripheral drivers +- configuration helpers +- buffer utilities +- CAN configuration code + +--- + +# 3. Entry Point (`main.c`) + +The CAN stress test is started from `main.c`. + +Key includes: + +``` +#include "can.h" +#include "can_tests.h" +#include "Logomatic.h" +``` + +These provide: + +- the CAN API +- the test framework +- logging utilities + +--- + +# 4. System Initialization + +Before running the test, the firmware initializes the MCU and all required peripherals in main.c. + +Typical initialization sequence: + +``` +HAL_Init(); + +SystemClock_Config(); + +MX_GPIO_Init(); +MX_LPUART1_UART_Init(); +``` + +This setup ensures that: + +- clocks are configured +- debugging output works +- peripherals required by the test environment are initialized + +--- + +# 5. Logging Setup + +Logging is performed using the `LOGOMATIC` utility. + +Example: + +``` +LOGOMATIC("Booted!\n"); +``` + +This typically outputs through: + +- semihosting +- SWO +- a debug UART + +--- + +# 6. Starting the CAN Stress Test + +After initialization, the test is executed directly from `main()`: + +``` +can_stress_test(); +``` + +This function is defined in the CAN test framework (``can_tests.h`) and performs the following tasks: + +- initializes CAN peripherals +- configures loopback or external modes +- transmits multiple test messages +- verifies message reception +- logs test results + +--- + +# 7. Main Loop + +After the test completes, the firmware enters the main loop: + +``` +while (1) { + LOGOMATIC("Main Loop\n"); + LL_mDelay(1000); +} +``` + +This loop keeps the firmware alive and allows continued debugging output. + +--- + +# 8. Typical CAN Test Flow + +A typical CAN test function performs the following steps: + +1. Configure CAN instances +2. Set the CAN clock source +3. Initialize the CAN handles +4. Start the CAN peripherals +5. Send test messages +6. Verify received messages +7. Release the CAN resources + +Example flow: + +``` +get_cfg(FDCAN1, rx_callback1, &cfg1, FDCAN_MODE_INTERNAL_LOOPBACK); +get_cfg(FDCAN2, rx_callback2, &cfg2, FDCAN_MODE_INTERNAL_LOOPBACK); + +can_set_clksource(LL_RCC_FDCAN_CLKSOURCE_PCLK1); + +CANHandle *can1 = can_init(&cfg1); +CANHandle *can2 = can_init(&cfg2); + +can_start(can1); +can_start(can2); + +can_send(can1, &msg); +can_send(can2, &msg); + +can_release(can1); +can_release(can2); +``` + +--- + +# 9. Summary + +To initialize and run a CAN test: + +1. Enable the test in `CMakeLists.txt` using `add_gr_project`. +2. Build the project using the desired CMake preset. +3. Flash the firmware containing `CAN_STRESS_TEST`. +4. The test is executed automatically from `main()` through: + +``` +can_stress_test(); +``` + +5. Results and diagnostics are printed through `LOGOMATIC`. + +This design allows each CAN test to run as a standalone firmware target while sharing the same CAN API implementation. + + + +--- diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 9efce16b9..321a2ca86 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -7,7 +7,10 @@ target_link_libraries( CircularBuffer_Lib ) -target_sources(PERIPHERAL_CAN_LIB INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Src/can.c) +target_sources(PERIPHERAL_CAN_LIB INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/Src/can.c + ${CMAKE_CURRENT_LIST_DIR}/Src/can_cfg_helpers.c +) # Make headers accessible as #include "Peripherals/CAN/can.h" target_include_directories( @@ -25,7 +28,6 @@ target_sources( ${CMAKE_CURRENT_LIST_DIR}/Test/can_internal_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_release_test.c ${CMAKE_CURRENT_LIST_DIR}/Test/can_stress_test.c - ${CMAKE_CURRENT_LIST_DIR}/Test/can_test_helpers.c #${CMAKE_CURRENT_LIST_DIR}/Test/can.c #${CMAKE_CURRENT_LIST_DIR}/Test/can_tests.c ) From 39616ea4d27d5e6232d997eb269f674542ede6e3 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 08:04:13 +0000 Subject: [PATCH 38/44] Automatic CMake Format: Standardized formatting automatically --- Lib/Peripherals/CAN/common.cmake | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/Peripherals/CAN/common.cmake b/Lib/Peripherals/CAN/common.cmake index 321a2ca86..12536205d 100644 --- a/Lib/Peripherals/CAN/common.cmake +++ b/Lib/Peripherals/CAN/common.cmake @@ -7,9 +7,11 @@ target_link_libraries( CircularBuffer_Lib ) -target_sources(PERIPHERAL_CAN_LIB INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/Src/can.c - ${CMAKE_CURRENT_LIST_DIR}/Src/can_cfg_helpers.c +target_sources( + PERIPHERAL_CAN_LIB + INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/Src/can.c + ${CMAKE_CURRENT_LIST_DIR}/Src/can_cfg_helpers.c ) # Make headers accessible as #include "Peripherals/CAN/can.h" From 65d0e3d0b3dfd8d0c3c2ec287e749a2995ceb388 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 08:05:48 +0000 Subject: [PATCH 39/44] Automatic Clang-Format: Standardized formatting automatically --- Lib/Peripherals/CAN/Inc/can.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index 770ae841b..a0e697853 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -94,8 +94,7 @@ void can_set_clksource(uint32_t clksource); // ex. LL_RCC_FDCAN_CLKSOURCE_PCLK1 // TODO: Add thread mode vs handler mode checking (None of these functions should be called in handler mode) - -//Configuration helpers +// Configuration helpers int get_cfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback, CANConfig *out_cfg, uint32_t Mode); #endif // End Header Guard From 7ad041e89ebd8286094d64ecda960570f0f685af Mon Sep 17 00:00:00 2001 From: Aagrim Hoysal <36976269+ahoysal@users.noreply.github.com> Date: Thu, 12 Mar 2026 20:36:17 -0700 Subject: [PATCH 40/44] Revert ADC testing name from CAN (probably merge shenanagains) Co-authored-by: Daniel Hansen <105574022+dchansen06@users.noreply.github.com> Signed-off-by: Aagrim Hoysal <36976269+ahoysal@users.noreply.github.com> --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 76d70a13e..03e6398b3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -418,7 +418,7 @@ "target/stm32g4x.cfg" ], "searchDir": [], - "preLaunchTask": "CMake: configure and build G4CANTESTING", + "preLaunchTask": "CMake: configure and build G4ADCTESTING", "showDevDebugOutput": "raw", "svdPath": "${workspaceFolder}/Lib/Vendor/CMSIS_5/SVD/STM32G474.svd", "swoConfig": { From 178f1f0b445f1930da38df02e2c3c219f715a49c Mon Sep 17 00:00:00 2001 From: Aagrim Hoysal <36976269+ahoysal@users.noreply.github.com> Date: Thu, 12 Mar 2026 20:37:06 -0700 Subject: [PATCH 41/44] Clean up tests in CMakeLists.txt Co-authored-by: Daniel Hansen <105574022+dchansen06@users.noreply.github.com> Signed-off-by: Aagrim Hoysal <36976269+ahoysal@users.noreply.github.com> --- CMakeLists.txt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e9b2b0415..49495dcc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,18 +81,12 @@ add_gr_project(STM32G474xE TireTemp) # Development add_gr_project(STM32G474xE G4ADCTESTING) add_gr_project(STM32G474xE G4PERTESTING) -#add_gr_project(STM32G474xE G4CANTESTING) -#CAN Peripheral Testing -#add_gr_project(STM32G474xE G4CANTESTING FILTER_TEST) +# CAN Peripheral Testing add_gr_project(STM32G474xE G4CANTESTING CAN_EXTERNAL_TEST) add_gr_project(STM32G474xE G4CANTESTING CAN_INTERNAL_TEST) -#add_gr_project(STM32G474xE G4CANTESTING INIT_TEST) add_gr_project(STM32G474xE G4CANTESTING CAN_RELEASE_TEST) add_gr_project(STM32G474xE G4CANTESTING CAN_STRESS_TEST) - -#add_gr_project(STM32G474xE G4CANTESTING) - add_gr_project(STM32G474xE G4NEOTESTING) # BLINKY Demos From 464dc1222e0912432471f8b686c004cbf8b15f81 Mon Sep 17 00:00:00 2001 From: ahoysal Date: Thu, 12 Mar 2026 21:13:08 -0700 Subject: [PATCH 42/44] added `can_cfg.h` to existing projects + cmake --- .vscode/launch.json | 31 ------------------- .vscode/tasks.json | 9 ------ CCU/Application/Inc/can_cfg.h | 7 +++++ DashPanel/Application/Inc/can_cfg.h | 7 +++++ ECU/Application/Inc/can_cfg.h | 10 ++++++ G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt | 7 ++++- .../{can_conf.h => can_cfg.h} | 0 G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt | 8 ++++- .../{can_conf.h => can_cfg.h} | 0 G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt | 7 ++++- .../{can_conf.h => can_cfg.h} | 0 G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt | 7 ++++- .../CAN_STRESS_TEST/{can_conf.h => can_cfg.h} | 0 Lib/Peripherals/CAN/Inc/can.h | 1 + Lib/Peripherals/CAN/README.md | 18 +++++++++-- Lib/Peripherals/CAN/Src/can.c | 12 ------- Lib/Peripherals/CAN/Src/can_cfg_helpers.c | 8 ++--- 17 files changed, 69 insertions(+), 63 deletions(-) create mode 100644 CCU/Application/Inc/can_cfg.h create mode 100644 DashPanel/Application/Inc/can_cfg.h create mode 100644 ECU/Application/Inc/can_cfg.h rename G4CANTESTING/CAN_EXTERNAL_TEST/{can_conf.h => can_cfg.h} (100%) rename G4CANTESTING/CAN_INTERNAL_TEST/{can_conf.h => can_cfg.h} (100%) rename G4CANTESTING/CAN_RELEASE_TEST/{can_conf.h => can_cfg.h} (100%) rename G4CANTESTING/CAN_STRESS_TEST/{can_conf.h => can_cfg.h} (100%) diff --git a/.vscode/launch.json b/.vscode/launch.json index 03e6398b3..a274e79e8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -437,37 +437,6 @@ ] } }, - { - "cwd": "${workspaceFolder}", - "executable": "${command:cmake.buildDirectory}/G4CANTESTING.elf", - "name": "G4CANTESTING", - "request": "launch", - "type": "cortex-debug", - "servertype": "openocd", - "configFiles": [ - "interface/stlink.cfg", - "target/stm32g4x.cfg" - ], - "searchDir": [], - "preLaunchTask": "CMake: configure and build G4CANTESTING", - "showDevDebugOutput": "raw", - "svdPath": "${workspaceFolder}/Lib/Vendor/CMSIS_5/SVD/STM32G474.svd", - "swoConfig": { - "enabled": true, - "cpuFrequency": 160000000, - "swoFrequency": 2000000, - "source": "probe", - "decoders": [ - { - "type": "console", - "label": "ITM", - "showOnStartup": true, - "port": 0, - "encoding": "ascii" - } - ] - } - }, { "cwd": "${workspaceFolder}", "executable": "${command:cmake.buildDirectory}/G4NEOTESTING.elf", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4f439adb8..6894f28f5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -90,15 +90,6 @@ ], "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target G4ADCTESTING" }, - { - "label": "CMake: configure and build G4CANTESTING", - "type": "shell", - "dependsOrder": "sequence", - "dependsOn": [ - "CMake: configure" - ], - "command": "cmake --build --preset ${command:cmake.activeBuildPresetName} --target G4CANTESTING" - }, { "label": "CMake: configure and build G4NEOTESTING", "type": "shell", diff --git a/CCU/Application/Inc/can_cfg.h b/CCU/Application/Inc/can_cfg.h new file mode 100644 index 000000000..2bc5b60c7 --- /dev/null +++ b/CCU/Application/Inc/can_cfg.h @@ -0,0 +1,7 @@ +#ifndef CAN_CONF_H +#define CAN_CONF_H + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#endif diff --git a/DashPanel/Application/Inc/can_cfg.h b/DashPanel/Application/Inc/can_cfg.h new file mode 100644 index 000000000..2bc5b60c7 --- /dev/null +++ b/DashPanel/Application/Inc/can_cfg.h @@ -0,0 +1,7 @@ +#ifndef CAN_CONF_H +#define CAN_CONF_H + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#endif diff --git a/ECU/Application/Inc/can_cfg.h b/ECU/Application/Inc/can_cfg.h new file mode 100644 index 000000000..4ba9da5ab --- /dev/null +++ b/ECU/Application/Inc/can_cfg.h @@ -0,0 +1,10 @@ +#ifndef CAN_CONF_H +#define CAN_CONF_H + +#define USECAN1 +#define TX_BUFFER_1_SIZE 10 + +#define USECAN2 +#define TX_BUFFER_2_SIZE 10 + +#endif diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt index 18addd99c..ccedc8c6d 100644 --- a/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/CMakeLists.txt @@ -52,4 +52,9 @@ set_target_properties( target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) +target_include_directories( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Inc + . +) diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h b/G4CANTESTING/CAN_EXTERNAL_TEST/can_cfg.h similarity index 100% rename from G4CANTESTING/CAN_EXTERNAL_TEST/can_conf.h rename to G4CANTESTING/CAN_EXTERNAL_TEST/can_cfg.h diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt index 1d53bfec6..ccedc8c6d 100644 --- a/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_INTERNAL_TEST/CMakeLists.txt @@ -51,4 +51,10 @@ set_target_properties( ) target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) + +target_include_directories( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Inc + . +) diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h b/G4CANTESTING/CAN_INTERNAL_TEST/can_cfg.h similarity index 100% rename from G4CANTESTING/CAN_INTERNAL_TEST/can_conf.h rename to G4CANTESTING/CAN_INTERNAL_TEST/can_cfg.h diff --git a/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt b/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt index 18addd99c..ccedc8c6d 100644 --- a/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_RELEASE_TEST/CMakeLists.txt @@ -52,4 +52,9 @@ set_target_properties( target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) +target_include_directories( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Inc + . +) diff --git a/G4CANTESTING/CAN_RELEASE_TEST/can_conf.h b/G4CANTESTING/CAN_RELEASE_TEST/can_cfg.h similarity index 100% rename from G4CANTESTING/CAN_RELEASE_TEST/can_conf.h rename to G4CANTESTING/CAN_RELEASE_TEST/can_cfg.h diff --git a/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt b/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt index c3f9b49d1..3be5c86bd 100644 --- a/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt +++ b/G4CANTESTING/CAN_STRESS_TEST/CMakeLists.txt @@ -45,4 +45,9 @@ target_sources( target_link_libraries(${PROJECT_NAME}_USER_CODE INTERFACE PERIPHERAL_CAN_LIB) -target_include_directories(${PROJECT_NAME}_USER_CODE INTERFACE ../Core/Inc) +target_include_directories( + ${PROJECT_NAME}_USER_CODE + INTERFACE + ../Core/Inc + . +) diff --git a/G4CANTESTING/CAN_STRESS_TEST/can_conf.h b/G4CANTESTING/CAN_STRESS_TEST/can_cfg.h similarity index 100% rename from G4CANTESTING/CAN_STRESS_TEST/can_conf.h rename to G4CANTESTING/CAN_STRESS_TEST/can_cfg.h diff --git a/Lib/Peripherals/CAN/Inc/can.h b/Lib/Peripherals/CAN/Inc/can.h index a0e697853..aa1a37363 100644 --- a/Lib/Peripherals/CAN/Inc/can.h +++ b/Lib/Peripherals/CAN/Inc/can.h @@ -8,6 +8,7 @@ #error "Unsupported STM32 Family" #endif +#include "can_cfg.h" #include "can_platform_deps.h" #include "circularBuffer.h" diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index cbacedf62..f3aaaad85 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -6,13 +6,25 @@ This document provides an overview of the Gaucho Racing CAN API, a simplified wr # Build Usage -Somewhere in your application, define: +In your application*, add a file called `can_cfg.h`, containing at least: ```c -#define USECAN1 -#define TX_BUFFER_1_SIZE +#ifndef CAN_CONF_H +#define CAN_CONF_H + +#define USECAN<1/2/3> +#define TX_BUFFER_<1/2/3>_SIZE + +// ... potentially other USECANM + TX_BUFFER_M_SIZE defines... + +#endif ``` +for each CAN peripheral you want to use. + +\* Make sure `can_cfg.h` is in a folder included by `target_include_directories` in the project's `CMakeLists.txt`! + + --- # 1. Quick Start Workflow diff --git a/Lib/Peripherals/CAN/Src/can.c b/Lib/Peripherals/CAN/Src/can.c index 169af55c4..2054b61e4 100644 --- a/Lib/Peripherals/CAN/Src/can.c +++ b/Lib/Peripherals/CAN/Src/can.c @@ -7,18 +7,6 @@ #include "Logomatic.h" -// #include "can_conf.h" -// TODO: Figure out how to move these defines into the application code - -#define USECAN1 -#define TX_BUFFER_1_SIZE 10 - -#define USECAN2 -#define TX_BUFFER_2_SIZE 10 - -#define USECAN3 -#define TX_BUFFER_3_SIZE 10 - // HAL handles #ifdef USECAN1 #ifndef TX_BUFFER_1_SIZE diff --git a/Lib/Peripherals/CAN/Src/can_cfg_helpers.c b/Lib/Peripherals/CAN/Src/can_cfg_helpers.c index 28ff67898..f50941713 100644 --- a/Lib/Peripherals/CAN/Src/can_cfg_helpers.c +++ b/Lib/Peripherals/CAN/Src/can_cfg_helpers.c @@ -67,7 +67,7 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback canCfg.rx_callback = callback; // TODO: Recheck these once you figure out how to define in application code - // #ifdef USECAN1 + #ifdef USECAN1 if (instance == FDCAN1) { canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; @@ -81,9 +81,9 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } - // #endif + #endif - // #ifdef USECAN2 + #ifdef USECAN2 if (instance == FDCAN2) { canCfg.fdcan_instance = FDCAN2; canCfg.rx_gpio = GPIOB; @@ -97,7 +97,7 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } - // #endif + #endif // #ifdef USECAN3 // #endif From 844f5d55e86d23534a7081515d4a42a3763c5f9e Mon Sep 17 00:00:00 2001 From: ahoysal Date: Thu, 12 Mar 2026 21:15:30 -0700 Subject: [PATCH 43/44] updated CAN_CONF_H --> CAN_CFG_H for consistency --- CCU/Application/Inc/can_cfg.h | 4 ++-- DashPanel/Application/Inc/can_cfg.h | 4 ++-- ECU/Application/Inc/can_cfg.h | 4 ++-- G4CANTESTING/CAN_EXTERNAL_TEST/can_cfg.h | 4 ++-- G4CANTESTING/CAN_INTERNAL_TEST/can_cfg.h | 4 ++-- G4CANTESTING/CAN_RELEASE_TEST/can_cfg.h | 4 ++-- G4CANTESTING/CAN_STRESS_TEST/can_cfg.h | 4 ++-- Lib/Peripherals/CAN/README.md | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CCU/Application/Inc/can_cfg.h b/CCU/Application/Inc/can_cfg.h index 2bc5b60c7..0e987b82d 100644 --- a/CCU/Application/Inc/can_cfg.h +++ b/CCU/Application/Inc/can_cfg.h @@ -1,5 +1,5 @@ -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN1 #define TX_BUFFER_1_SIZE 10 diff --git a/DashPanel/Application/Inc/can_cfg.h b/DashPanel/Application/Inc/can_cfg.h index 2bc5b60c7..0e987b82d 100644 --- a/DashPanel/Application/Inc/can_cfg.h +++ b/DashPanel/Application/Inc/can_cfg.h @@ -1,5 +1,5 @@ -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN1 #define TX_BUFFER_1_SIZE 10 diff --git a/ECU/Application/Inc/can_cfg.h b/ECU/Application/Inc/can_cfg.h index 4ba9da5ab..8a18e8882 100644 --- a/ECU/Application/Inc/can_cfg.h +++ b/ECU/Application/Inc/can_cfg.h @@ -1,5 +1,5 @@ -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN1 #define TX_BUFFER_1_SIZE 10 diff --git a/G4CANTESTING/CAN_EXTERNAL_TEST/can_cfg.h b/G4CANTESTING/CAN_EXTERNAL_TEST/can_cfg.h index f12a970f3..fc11e3e23 100644 --- a/G4CANTESTING/CAN_EXTERNAL_TEST/can_cfg.h +++ b/G4CANTESTING/CAN_EXTERNAL_TEST/can_cfg.h @@ -1,6 +1,6 @@ -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN1 #define TX_BUFFER_1_SIZE 10 diff --git a/G4CANTESTING/CAN_INTERNAL_TEST/can_cfg.h b/G4CANTESTING/CAN_INTERNAL_TEST/can_cfg.h index f12a970f3..fc11e3e23 100644 --- a/G4CANTESTING/CAN_INTERNAL_TEST/can_cfg.h +++ b/G4CANTESTING/CAN_INTERNAL_TEST/can_cfg.h @@ -1,6 +1,6 @@ -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN1 #define TX_BUFFER_1_SIZE 10 diff --git a/G4CANTESTING/CAN_RELEASE_TEST/can_cfg.h b/G4CANTESTING/CAN_RELEASE_TEST/can_cfg.h index f12a970f3..fc11e3e23 100644 --- a/G4CANTESTING/CAN_RELEASE_TEST/can_cfg.h +++ b/G4CANTESTING/CAN_RELEASE_TEST/can_cfg.h @@ -1,6 +1,6 @@ -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN1 #define TX_BUFFER_1_SIZE 10 diff --git a/G4CANTESTING/CAN_STRESS_TEST/can_cfg.h b/G4CANTESTING/CAN_STRESS_TEST/can_cfg.h index f12a970f3..fc11e3e23 100644 --- a/G4CANTESTING/CAN_STRESS_TEST/can_cfg.h +++ b/G4CANTESTING/CAN_STRESS_TEST/can_cfg.h @@ -1,6 +1,6 @@ -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN1 #define TX_BUFFER_1_SIZE 10 diff --git a/Lib/Peripherals/CAN/README.md b/Lib/Peripherals/CAN/README.md index f3aaaad85..b33700fd0 100644 --- a/Lib/Peripherals/CAN/README.md +++ b/Lib/Peripherals/CAN/README.md @@ -9,8 +9,8 @@ This document provides an overview of the Gaucho Racing CAN API, a simplified wr In your application*, add a file called `can_cfg.h`, containing at least: ```c -#ifndef CAN_CONF_H -#define CAN_CONF_H +#ifndef CAN_CFG_H +#define CAN_CFG_H #define USECAN<1/2/3> #define TX_BUFFER_<1/2/3>_SIZE From 2569cbfb7f978236c630e7ec4e07917c8c968dd3 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 04:16:52 +0000 Subject: [PATCH 44/44] Automatic Clang-Format: Standardized formatting automatically --- Lib/Peripherals/CAN/Src/can_cfg_helpers.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/Peripherals/CAN/Src/can_cfg_helpers.c b/Lib/Peripherals/CAN/Src/can_cfg_helpers.c index f50941713..d9ae484f0 100644 --- a/Lib/Peripherals/CAN/Src/can_cfg_helpers.c +++ b/Lib/Peripherals/CAN/Src/can_cfg_helpers.c @@ -66,8 +66,8 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback canCfg.rx_callback = callback; - // TODO: Recheck these once you figure out how to define in application code - #ifdef USECAN1 +// TODO: Recheck these once you figure out how to define in application code +#ifdef USECAN1 if (instance == FDCAN1) { canCfg.fdcan_instance = FDCAN1; canCfg.rx_gpio = GPIOA; @@ -81,9 +81,9 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } - #endif +#endif - #ifdef USECAN2 +#ifdef USECAN2 if (instance == FDCAN2) { canCfg.fdcan_instance = FDCAN2; canCfg.rx_gpio = GPIOB; @@ -97,7 +97,7 @@ int defaultSTM32G4_CANCfg(FDCAN_GlobalTypeDef *instance, CAN_RXCallback callback *out_cfg = canCfg; return SUCCESS; } - #endif +#endif // #ifdef USECAN3 // #endif