diff --git a/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.cpp b/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.cpp index b54cd66..85105e2 100644 --- a/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.cpp +++ b/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.cpp @@ -151,13 +151,45 @@ void EthEcatPdoFMMU::process() { //read(0, process_data); - process_read_queue(pdo_read.data(), pdo_read.size()); + #if PROFILE_LEVEL > 0 + { + #pragma message ( "Profiling for RPDO subscribers is enabled !" ) + PROFILE(process_read_queue, PROFILE_SAMPLES, 0); + + process_read_queue(pdo_read.data(), pdo_read.size()); + } + #else + process_read_queue(pdo_read.data(), pdo_read.size()); + #endif + + #if PROFILE_LEVEL > 0 + { + #pragma message ( "Profiling for process callback is enabled !" ) + + PROFILE(callback_, PROFILE_SAMPLES, 0); + + if(callback_ != nullptr) { + callback_(); + } + } + #else if(callback_ != nullptr) { callback_(); } + #endif + #if PROFILE_LEVEL > 0 + { + #pragma message ( "Profiling for TPDO subscribers is enabled !" ) + + PROFILE(process_write_queue, PROFILE_SAMPLES, 0); + + process_write_queue(pdo_write.data(), pdo_write.size()); + } + #else process_write_queue(pdo_write.data(), pdo_write.size()); + #endif //write(0, process_data); @@ -186,13 +218,45 @@ void EthEcatPdoFMMU::process_fake(uint32_t period_microsec, ecat_pdo_fmmu::Proce ecat_timer.Wait(); //DebugP_log("Tick !\r\n"); - process_read_queue(pdo_read.data(), pdo_read.size()); + #if PROFILE_LEVEL > 0 + { + #pragma message ( "Profiling for RPDO subscribers is enabled !" ) - if(callback != nullptr) { - callback(); + PROFILE(process_read_queue, PROFILE_SAMPLES, 0); + + process_read_queue(pdo_read.data(), pdo_read.size()); } + #else + process_read_queue(pdo_read.data(), pdo_read.size()); + #endif + #if PROFILE_LEVEL > 0 + { + #pragma message ( "Profiling for process callback is enabled !" ) + + PROFILE(callback_, PROFILE_SAMPLES, 0); + + if(callback_ != nullptr) { + callback_(); + } + } + #else + if(callback_ != nullptr) { + callback_(); + } + #endif + + #if PROFILE_LEVEL > 0 + { + #pragma message ( "Profiling for TPDO subscribers is enabled !" ) + + PROFILE(process_write_queue, PROFILE_SAMPLES, 0); + + process_write_queue(pdo_write.data(), pdo_write.size()); + } + #else process_write_queue(pdo_write.data(), pdo_write.size()); + #endif pdo_counter_++; } diff --git a/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.hpp b/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.hpp index 5f8c6cd..49aed0a 100644 --- a/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.hpp +++ b/components/free_rtos/ethernet_industry/CoE/eth_ecat_pdo_fmmu.hpp @@ -8,11 +8,15 @@ #ifndef FREE_RTOS_ETHERNET_INDUSTRY_COE_ETH_ECAT_PDO_FMMU_HPP_ #define FREE_RTOS_ETHERNET_INDUSTRY_COE_ETH_ECAT_PDO_FMMU_HPP_ +#define PROFILE_LEVEL 1 +#define PROFILE_SAMPLES 64 + #include "free_rtos/semaphore/semaphore.hpp" #include "free_rtos/mutex/mutex.hpp" #include "free_rtos/ethernet_industry/eth_ecat_buffer.hpp" #include "free_rtos/ethernet_industry/eth_ecat_custom_promise.hpp" +#include "free_rtos/profiler/quick_profiler.hpp" namespace free_rtos { diff --git a/components/free_rtos/profiler/quick_profiler.hpp b/components/free_rtos/profiler/quick_profiler.hpp new file mode 100644 index 0000000..a28c1f0 --- /dev/null +++ b/components/free_rtos/profiler/quick_profiler.hpp @@ -0,0 +1,114 @@ +/* + * quick_profiler.hpp + * + * Created on: Aug 10, 2023 + * Author: algin + */ + +#ifndef FREE_RTOS_PROFILER_QUICK_PROFILER_HPP_ +#define FREE_RTOS_PROFILER_QUICK_PROFILER_HPP_ + + +#include +#include + +#include +#include + +namespace free_rtos { + +#define PROFILE(name, size, id) static QuickProfiler name##_profiler{#name}; \ + QuickProfilerItem name##_profile_item_##id{name##_profiler} + +#define CREATE_PROFILER(name, size) static QuickProfiler name##_profiler{#name}; + +#define ADD_PROFILE_ITEM(name, size, id) QuickProfilerItem name##_profile_item_##id{name##_profiler} + +static void QuickProfiler_init(const uint64_t cpuFreqHz) { + CycleCounterP_init(cpuFreqHz); + CycleCounterP_reset(); + + uint64_t nsToTicks = CycleCounterP_nsToTicks(1000); + + DebugP_log((char *)"%lld ticks in 1000 nanoseconds\r\n", nsToTicks); +} + +template +class QuickProfiler { +public: + QuickProfiler(const char *name) + : name_{name} { }; + + void collect(uint32_t diff) { + uint32_t counter = counter_; + buffer_[counter] = diff; + + counter++; + + if(counter >= size) { + counter = 0; + + dump(); + } + + counter_ = counter; + } + +private: + const char *name_; + size_t counter_{0}; + std::array buffer_; + + void dump() { + uint64_t average{0x0000000000000000}; + uint32_t min{0xFFFFFFFF}; + uint32_t max{0x00000000}; + + for(uint32_t value : buffer_) { + average += value; + + if(value < min) { + min = value; + } + + if(value > max) { + max = value; + } + } + + average /= size; + + DebugP_log((char *)"Profiler %s average: %lld min: %d max: %d\r\n", name_, average, min, max); + } +}; + +template +class QuickProfilerItem { +public: + QuickProfilerItem(QuickProfiler& profiler) + : profiler_{profiler} { + start_cycle_ = CycleCounterP_getCount32(); + }; + + ~QuickProfilerItem() { + uint32_t end_cycle = CycleCounterP_getCount32(); + uint32_t start_cycle = start_cycle_; + uint32_t diff; + + if(end_cycle > start_cycle) { + diff = end_cycle - start_cycle; + } else { + diff = (0xFFFFFFFFU - start_cycle) + end_cycle; + } + + profiler_.collect(diff); + } + +private: + QuickProfiler& profiler_; + uint32_t start_cycle_; +}; + +} // namespace free_rtos + +#endif /* FREE_RTOS_PROFILER_QUICK_PROFILER_HPP_ */