Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ list(FILTER STLIB_HIGH_CPP_NO_ETH EXCLUDE REGEX "${STLIB_HIGH_ETH_REGEX}")
# Librería STLIB_LIBRARY
# ============================

set(RTT_SOURCES
${CMAKE_CURRENT_LIST_DIR}/Middlewares/Third_Party/RTT/RTT/SEGGER_RTT.c
${CMAKE_CURRENT_LIST_DIR}/Middlewares/Third_Party/RTT/RTT/SEGGER_RTT_printf.c
${CMAKE_CURRENT_LIST_DIR}/Middlewares/Third_Party/RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c
)

add_library(${STLIB_LIBRARY} STATIC
$<$<BOOL:${CMAKE_CROSSCOMPILING}>:${HAL_SOURCES_COMMON}>
$<$<AND:$<BOOL:${CMAKE_CROSSCOMPILING}>,$<BOOL:${USE_ETHERNET}>>:${HAL_SOURCES_ETH}>
Expand All @@ -220,8 +226,9 @@ add_library(${STLIB_LIBRARY} STATIC
$<$<BOOL:${CMAKE_CROSSCOMPILING}>:${STLIB_HIGH_CPP_NO_ETH}>
$<$<AND:$<BOOL:${CMAKE_CROSSCOMPILING}>,$<BOOL:${USE_ETHERNET}>>:${STLIB_HIGH_C_ETH}>
$<$<AND:$<BOOL:${CMAKE_CROSSCOMPILING}>,$<BOOL:${USE_ETHERNET}>>:${STLIB_HIGH_CPP_ETH}>
${CMAKE_CURRENT_LIST_DIR}/Src/ST-LIB.cpp
$<$<BOOL:${CMAKE_CROSSCOMPILING}>:${RTT_SOURCES}>

$<$<BOOL:${CMAKE_CROSSCOMPILING}>:${CMAKE_CURRENT_LIST_DIR}/Src/ST-LIB.cpp>
)

set_target_properties(${STLIB_LIBRARY} PROPERTIES
Expand Down Expand Up @@ -266,6 +273,7 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:-Wno-address-of-packed-member>
)


target_include_directories(${STLIB_LIBRARY} PUBLIC
# CMSIS + HAL
$<$<BOOL:${CMAKE_CROSSCOMPILING}>:${STM32CUBEH7}/Drivers/CMSIS/Device/ST/STM32H7xx/Include>
Expand Down Expand Up @@ -294,7 +302,8 @@ target_include_directories(${STLIB_LIBRARY} PUBLIC
$<$<AND:$<BOOL:${CMAKE_CROSSCOMPILING}>,$<BOOL:${USE_ETHERNET}>>:${STM32CUBEH7}/Drivers/BSP/Components/lan8742>
$<$<AND:$<BOOL:${CMAKE_CROSSCOMPILING}>,$<BOOL:${USE_ETHERNET}>>:${CMAKE_CURRENT_LIST_DIR}/LWIP/App>
$<$<AND:$<BOOL:${CMAKE_CROSSCOMPILING}>,$<BOOL:${USE_ETHERNET}>>:${CMAKE_CURRENT_LIST_DIR}/LWIP/Target>

$<$<BOOL:${CMAKE_CROSSCOMPILING}>:${CMAKE_CURRENT_LIST_DIR}/Middlewares/Third_Party/RTT/RTT>
$<$<BOOL:${CMAKE_CROSSCOMPILING}>:${CMAKE_CURRENT_LIST_DIR}/Middlewares/Third_Party/RTT/Config>
${CMAKE_CURRENT_LIST_DIR}/Inc
${CMAKE_CURRENT_LIST_DIR}/Inc/ST-LIB_LOW
${CMAKE_CURRENT_LIST_DIR}/Inc/ST-LIB_HIGH
Expand Down
119 changes: 119 additions & 0 deletions Inc/HALAL/Benchmarking_toolkit/Benchmarking.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#pragma once

#include <array>
#include <inttypes.h>
#include <algorithm>
#include <string_view>

#include "stm32h723xx.h"
#include "core_cm7.h"
#include "SEGGER_RTT.h"

enum class BenchmarkType : uint8_t{
NONE,
RUNTIME,
GDB
};
enum BenchmarkLoggingTypes{
_NONE,
_SD = 1,
_RTT = 2
};

struct TimeStamp{
uint32_t id;
uint32_t cycles;
};


static inline TimeStamp timestamp;
/**
* This hash is used to send a lightweight identifier via RTT
* on the host the source code is searched for BENCHMARK_MACROS
* and hashed using the same hash algorithm, thus creating a 1:1
* match between hash and string
*/
consteval uint32_t custom_hash(std::string_view str){
uint32_t hash = 2166136261u; // FNV offset basis

for (char c : str) {
hash ^= (unsigned char)c;
hash *= 16777619u; // FNV prime
}

return hash;
}
#if defined(RUNTIME_BENCHMARK) && defined(GDB_BENCHMARK)
#error "Cannot use RUNTIME_BENCHMARK and GDB_BENCHMARK SIMULTANEOUSLY"
#endif

extern "C"{
#ifdef RUNTIME_BENCHMARK
constexpr BenchmarkType benchmark_type = BenchmarkType::RUNTIME;
static const char BENCHMARK_TYPE_RUNTIME[] __attribute__((used)) = "BENCHMARK_RUNTIME";
#elif defined(GDB_BENCHMARK)
constexpr BenchmarkType benchmark_type = BenchmarkType::GDB;
static const char BENCHMARK_TYPE_GDB[] __attribute__((used)) = "BENCHMARK_GDB";
#else
constexpr BenchmarkType benchmark_type = BenchmarkType::NONE;
static const char BENCHMARK_TYPE_NONE[] __attribute__((used)) = "BENCHMARK_NONE";
#endif

}

#if defined(RUNTIME_BENCHMARK)
#define RUNTIME_BENCHMARK_TAG _RTT
#else
#define RUNTIME_BENCHMARK_TAG _NONE
#endif

#if defined(SD)
#define SD_BENCHMARK_TAG _SD
#else
#define SD_BENCHMARK_TAG _NONE
#endif
inline constexpr int logging_type = RUNTIME_BENCHMARK_TAG | SD_BENCHMARK_TAG;
template<BenchmarkType Type>
class Benchmarker{
public:
Benchmarker(){
DWT->CTRL |= 1;
DWT->CYCCNT = 0;
if constexpr(benchmark_type == BenchmarkType::RUNTIME){
SEGGER_RTT_Init();
}
}
Comment on lines +79 to +85
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Benchmarker constructor initializes DWT registers (DWT->CTRL and DWT->CYCCNT) without checking if the trace infrastructure is unlocked or enabled via CoreDebug->DEMCR. This could fail silently on some targets. The initialization should call CoreDebug->DEMCR |= DEMCR_TRCENA first, and potentially unlock DWT if needed.

Copilot uses AI. Check for mistakes.
template<uint32_t Id>
__attribute__((always_inline)) inline static void __benchmark_start__(){
if constexpr(benchmark_type == BenchmarkType::GDB){
__asm__ volatile("BKPT \n");
} else if constexpr(benchmark_type == BenchmarkType::RUNTIME){
uint32_t cycles = DWT->CYCCNT;
if constexpr( logging_type & _RTT){
timestamp.id = Id;
timestamp.cycles = cycles;
SEGGER_RTT_Write(0,&timestamp,sizeof(TimeStamp));
}
}
}
template<uint32_t Id>
__attribute__((always_inline)) inline static void __benchmark_end__(){
if constexpr(benchmark_type == BenchmarkType::GDB){
__asm__ volatile("BKPT \n");
} else if constexpr(benchmark_type == BenchmarkType::RUNTIME){
uint32_t cycles = DWT->CYCCNT;
if constexpr( logging_type & _RTT){
timestamp.id = Id;
timestamp.cycles = cycles;
SEGGER_RTT_Write(0,&timestamp,sizeof(TimeStamp));
}
}
}
Comment on lines +86 to +111
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The benchmark_start and benchmark_end functions read DWT->CYCCNT without any mechanism to handle or account for counter overflows. The num_overflows variable is declared in DataWatchpointTrace but never incremented. When the 32-bit counter wraps around, timing measurements will be incorrect. Consider implementing overflow detection and handling.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overflow logic is implemented on the host side, to make the target measuremetns as lightweight as possible

};

#define BENCHMARK_SETUP() \
Benchmarker<benchmark_type> __b;
#define BENCHMARK_START(NAME) \
Benchmarker<benchmark_type>::__benchmark_start__<custom_hash(NAME)>();
#define BENCHMARK_END(NAME)\
Benchmarker<benchmark_type>::__benchmark_end__<custom_hash(NAME)>();
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "ErrorHandler/ErrorHandler.hpp"
#include "HALAL/Models/PinModel/Pin.hpp"
#include "core_cm7.h"

#include "HALAL/Benchmarking_toolkit/Benchmarking.hpp"
#if !defined DWT_LSR_Present_Msk
#define DWT_LSR_Present_Msk ITM_LSR_Present_Msk
#endif
Expand All @@ -14,6 +14,8 @@
#define DWT_LAR_KEY 0xC5ACCE55
#define DEMCR_TRCENA 0x01000000
#define DWT_CTRL_CYCCNTENA 0x00000001


/*
This class is designed to study the efficiency of an algorithm
by counting the number of clock cycles required for execution.
Expand All @@ -28,36 +30,24 @@
*/
class DataWatchpointTrace {
public:
static void start() {
unlock_dwt();
reset_cnt();
}
static unsigned int start_count() {
DWT->CTRL |= DWT_CTRL_CYCCNTENA; // enables the counter
DWT->CYCCNT = 0;
return DWT->CYCCNT;
static uint32_t num_overflows;
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The static member variable num_overflows is declared but never defined or initialized. This will cause a linker error. Add a definition in the corresponding .cpp file (e.g., uint32_t DataWatchpointTrace::num_overflows = 0;) or make it inline if using C++17 or later.

Suggested change
static uint32_t num_overflows;
inline static uint32_t num_overflows = 0;

Copilot uses AI. Check for mistakes.
static void enable() {
DWT->CTRL |= DWT_CTRL_CYCCNTENA | DWT_CTRL_EXCTRCENA_Msk | DWT_CTRL_EXCEVTENA_Msk; // enables the counter
DWT->FUNCTION0 |= (1 << 7) | 0b1000; // enable comparison
DWT->COMP0 = 0xFFFFFFFF; // detect overflow
}
Comment on lines +34 to 38
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The enable() function modifies DWT hardware registers but does not verify that CoreDebug->DEMCR has the TRCENA bit set, which is required before accessing DWT registers. This could cause the DWT operations to fail silently. Consider adding CoreDebug->DEMCR |= DEMCR_TRCENA before accessing DWT registers.

Copilot uses AI. Check for mistakes.
static unsigned int stop_count() {

static void disable(){
DWT->CTRL &= ~DWT_CTRL_CYCCNTENA; // disable the counter
return DWT->CYCCNT;
}

static unsigned int get_count() {
return DWT->CYCCNT; // returns the current value of the counter
}

private:
static void reset_cnt() {
CoreDebug->DEMCR |= DEMCR_TRCENA;
DWT->CYCCNT = 0; // reset the counter
DWT->CTRL = 0;
}

static void unlock_dwt() { // unlock the dwt
uint32_t lsr = DWT->LSR;
if ((lsr & DWT_LSR_Present_Msk) != 0) {
if ((lsr & DWT_LSR_Access_Msk) != 0) {
DWT->LAR = DWT_LAR_KEY;
}
}
}
Comment on lines 49 to 52
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reset_cnt() private method is declared but has an empty function body, and it no longer performs its intended reset operation. This appears to be dead code that should either be removed or properly implemented to reset the counter as its name suggests.

Copilot uses AI. Check for mistakes.
};
4 changes: 4 additions & 0 deletions Inc/HALAL/HALAL.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@

#include "HALAL/Models/BoardID/BoardID.hpp"
#include "HALAL/Models/Concepts/Concepts.hpp"
#include "HALAL/Models/TimerPeripheral/TimerPeripheral.hpp"
#include "HALAL/Benchmarking_toolkit/DataWatchpointTrace/DataWatchpointTrace.hpp"
#include "HALAL/Benchmarking_toolkit/Benchmarking.hpp"


#ifdef STLIB_ETH
#include "HALAL/Models/Packets/Packet.hpp"
Expand Down
Loading