Skip to content

Commit

Permalink
Merge pull request #26 from klonyyy/devel
Browse files Browse the repository at this point in the history
Release v0.3.0
  • Loading branch information
klonyyy authored Dec 19, 2023
2 parents 4ee8555 + 9e30fb7 commit dd2d895
Show file tree
Hide file tree
Showing 46 changed files with 1,108 additions and 403 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
build/*
build_test/*
.vscode/*
.cache/*
src/gitversion.hpp

**/[Dd]ebug/
**/[Rr]elease/
Expand Down
17 changes: 14 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,19 @@ endif()

project(STMViewer)

set(STMVIEWER_VERSION 0.2.0)
set(STMVIEWER_VERSION 0.3.0)

set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)

set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

if(WIN32 AND "${PLATFORM}" STREQUAL "native")
set(LLVM_DIR "C:/msys64/mingw64/bin")
set(CMAKE_PREFIX_PATH ${LLVM_DIR} ${CMAKE_PREFIX_PATH})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
set(CMAKE_AR "C:/msys64/mingw64/bin/llvm-ar.exe")
endif()

if(CMAKE_BUILD_TYPE STREQUAL "ReleaseWithDbg")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
Expand Down Expand Up @@ -71,6 +80,7 @@ set(PROJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/Gui/GuiPlots.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Gui/GuiSwoPlots.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Gui/GuiSwoControl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Gui/GuiAbout.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/TargetMemoryHandler/TargetMemoryHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/TargetMemoryHandler/StlinkHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Plot/Plot.cpp
Expand Down Expand Up @@ -132,7 +142,8 @@ target_include_directories(${EXECUTABLE} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/FileHandler
${CMAKE_CURRENT_SOURCE_DIR}/src/PlotHandler
${CMAKE_CURRENT_SOURCE_DIR}/src/TraceReader
${CMAKE_CURRENT_SOURCE_DIR}/src/RingBuffer)
${CMAKE_CURRENT_SOURCE_DIR}/src/RingBuffer
${CMAKE_CURRENT_SOURCE_DIR}/src/Statistics)

target_include_directories(${EXECUTABLE} SYSTEM PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/third_party/stlink/inc/
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The only piece of hardware required is an ST-Link programmer.

Variable Viewer can be used to visualize your embedded application data in real time with no overhead in a non-intrusive way. The software works by reading variables' values directly from RAM using the ST-link programmer debug interface. Addresses are read from the *.elf file which is created when you build your embedded project. This approach's main downside is that the object's address must stay constant throughout the whole program's lifetime, which means the object has to be global. Even though it seems to be a small price to pay in comparison to running some debug protocol over for example UART which is also not free in terms of intrusiveness.

Variable Viewer is a great tool for debugging, but might be of little use with highly optimized release builds (which usually lack debug info), or very fast-changing signals.
Variable Viewer is a great tool for debugging, but might be of little use with highly optimized release builds (which usually lack debug info), or high frequency signals.

### Trace Viewer
![_](./docs/TraceViewer.gif)
Expand All @@ -25,14 +25,16 @@ TraceViewer is not influenced by optimizations, which means it is a great tool t

## Installation

First make sure you've got GDB installed and that it's at least 12.1.

Linux:
1. Download the *.deb package and install it using:
`sudo apt install ./STMViewer-x.y.z-Linux.deb`
All dependencies should be installed and you should be ready to go.
Optional: make sure you have the rights to access usb port. When installing ST's software such as Cube Programmer it will most probably also install needed udev rules.

Windows:
1. Make sure you've got GDB installed (v12.1 or later) and added to your PATH (the easiest way is to install using [MinGW](https://www.mingw-w64.org))
1. Make sure you've got GDB installed and added to your PATH (the easiest way is to install using [MinGW](https://www.mingw-w64.org))
2. Download and run the STMViewer installer. Make sure the ST-link is in "STM32 Debug + Mass Storage + VCP" mode as for some reason "STM32 Debug + VCP" throws libusb errors on Windows. This needs further investigation.

You can assign the external GPU to STMViewer for improved performance.
Expand Down Expand Up @@ -68,7 +70,7 @@ or

```
uint16_t a = getAdcSample(); // some super fast signal to trace
ITM->PORT[x].u16 = a; // type-punn to desired size
ITM->PORT[x].u16 = a;
```

The ITM registers are defined in CMSIS headers so no additional includes should be necessary.
Expand Down
39 changes: 33 additions & 6 deletions imgui.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[Window][DockSpaceViewport_11111111]
Pos=0,19
Size=1920,998
Size=32,32
Collapsed=0

[Window][Debug##Default]
Expand All @@ -22,7 +22,7 @@ DockId=0x00000002,0

[Window][Var Viewer]
Pos=0,19
Size=522,998
Size=15,32
Collapsed=0
DockId=0x00000001,0

Expand Down Expand Up @@ -59,15 +59,25 @@ DockId=0x00000002,0

[Window][Trace Viewer]
Pos=0,19
Size=522,998
Size=15,32
Collapsed=0
DockId=0x00000001,1

[Window][Save?]
Pos=60,60
Pos=764,449
Size=16,35
Collapsed=0

[Window][Info]
Pos=882,484
Size=156,48
Collapsed=0

[Window][Statistics]
Pos=495,90
Size=336,347
Collapsed=0

[Table][0xC16CD03B,3]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Expand Down Expand Up @@ -97,8 +107,25 @@ Column 1 Weight=1.0000
Column 2 Weight=1.0000
Column 3 Weight=1.0000

[Table][0x992CA3EB,3]
Column 0 Weight=2.2112
Column 1 Weight=0.6078
Column 2 Weight=0.1810

[Table][0xBF76FCBC,4]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Column 2 Weight=1.0000
Column 3 Weight=1.0000

[Table][0x99AE4CF8,4]
Column 0 Weight=1.0000
Column 1 Weight=1.0000
Column 2 Weight=1.0000
Column 3 Weight=1.0000

[Docking][Data]
DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,19 Size=1920,998 Split=X Selected=0x350511F3
DockNode ID=0x00000001 Parent=0x8B93E3BD SizeRef=522,981 Selected=0x350511F3
DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,19 Size=32,32 Split=X Selected=0x350511F3
DockNode ID=0x00000001 Parent=0x8B93E3BD SizeRef=522,981 Selected=0x155D1E03
DockNode ID=0x00000002 Parent=0x8B93E3BD SizeRef=1396,981 CentralNode=1 Selected=0xE8A2D1AC

46 changes: 35 additions & 11 deletions src/ConfigHandler/ConfigHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "ConfigHandler.hpp"

#include <memory>
#include <random>
#include <variant>

ConfigHandler::ConfigHandler(const std::string& configFilePath, PlotHandler* plotHandler, TracePlotHandler* tracePlotHandler, std::shared_ptr<spdlog::logger> logger) : configFilePath(configFilePath), plotHandler(plotHandler), tracePlotHandler(tracePlotHandler), logger(logger)
{
Expand Down Expand Up @@ -32,17 +34,39 @@ bool ConfigHandler::readConfigFile(std::map<std::string, std::shared_ptr<Variabl
auto varFieldFromID = [](uint32_t id)
{ return std::string("var" + std::to_string(id)); };

globalSettings.version = atoi(ini->get("settings").get("version").c_str());
viewerSettings.samplePeriod = atoi(ini->get("settings").get("sample_period").c_str());
viewerSettings.maxPoints = atoi(ini->get("settings").get("max_points").c_str());
viewerSettings.maxViewportPoints = atoi(ini->get("settings").get("max_viewport_points").c_str());

traceSettings.coreFrequency = atoi(ini->get("trace_settings").get("core_frequency").c_str());
traceSettings.tracePrescaler = atoi(ini->get("trace_settings").get("trace_prescaler").c_str());
traceSettings.maxPoints = atoi(ini->get("trace_settings").get("max_points").c_str());
traceSettings.maxViewportPointsPercent = atoi(ini->get("trace_settings").get("max_viewport_points_percent").c_str());
traceSettings.triggerChannel = atoi(ini->get("trace_settings").get("trigger_channel").c_str());
traceSettings.triggerLevel = atof(ini->get("trace_settings").get("trigger_level").c_str());
auto getValue = [&](std::string&& category, std::string&& field, auto&& result)
{
try
{
std::string value = ini->get(category).get(field);
parseValue(value, result);
}
catch (const std::exception& ex)
{
logger->error("{}", ex.what());
}
};

getValue("settings", "version", globalSettings.version);
getValue("settings", "sample_period", viewerSettings.samplePeriod);
getValue("settings", "max_points", viewerSettings.maxPoints);
getValue("settings", "max_viewport_points", viewerSettings.maxViewportPoints);

getValue("trace_settings", "core_frequency", traceSettings.coreFrequency);
getValue("trace_settings", "trace_prescaler", traceSettings.tracePrescaler);
getValue("trace_settings", "max_points", traceSettings.maxPoints);
getValue("trace_settings", "max_viewport_points_percent", traceSettings.maxViewportPointsPercent);
getValue("trace_settings", "trigger_channel", traceSettings.triggerChannel);
getValue("trace_settings", "trigger_level", traceSettings.triggerLevel);

if (traceSettings.maxViewportPointsPercent == 0 && traceSettings.maxPoints == 0)
traceSettings.triggerChannel = -1;

if (traceSettings.maxViewportPointsPercent == 0)
traceSettings.maxViewportPointsPercent = 50;

if (traceSettings.maxPoints == 0)
traceSettings.maxPoints = 10000;

if (viewerSettings.samplePeriod == 0)
viewerSettings.samplePeriod = 10;
Expand Down
14 changes: 13 additions & 1 deletion src/ConfigHandler/ConfigHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define _CONFIGHANDLER_HPP

#include <map>
#include <memory>
#include <string>

#include "PlotHandler.hpp"
Expand All @@ -15,7 +16,7 @@ class ConfigHandler
public:
typedef struct
{
uint32_t version = 0;
uint32_t version = 1;
} GlobalSettings;

ConfigHandler(const std::string& configFilePath, PlotHandler* plotHandler, TracePlotHandler* tracePlotHandler, std::shared_ptr<spdlog::logger> logger);
Expand All @@ -25,6 +26,17 @@ class ConfigHandler
bool readConfigFile(std::map<std::string, std::shared_ptr<Variable>>& vars, std::string& elfPath);
bool saveConfigFile(std::map<std::string, std::shared_ptr<Variable>>& vars, const std::string& elfPath, const std::string newPath);

template <typename T>
void parseValue(const std::string& value, T& result)
{
if constexpr (std::is_integral_v<T>)
result = std::stoi(value);
else if constexpr (std::is_same_v<T, float>)
result = std::stof(value);
else
throw std::invalid_argument("Unsupported type");
}

private:
GlobalSettings globalSettings;
std::string configFilePath;
Expand Down
30 changes: 30 additions & 0 deletions src/ElfReader/ElfReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@
#include <memory>
#include <sstream>
#include <string>
#include <utility>

#if defined(unix) || defined(__unix__) || defined(__unix)
#define _UNIX
#endif

ElfReader::ElfReader(std::string& filename, std::shared_ptr<spdlog::logger> logger) : elfname(filename), logger(logger)
{
auto version = extractGDBVersionNumber(executeCommand("gdb -v"));

if (version == 0)
logger->error("Failed to read GDB version! Make sure it's installed and added to your PATH!");
else
{
logger->info("GDB version: {}", version);
if (version < gdbMinimumVersion)
logger->error("Your GDB is too old, please update it to at least 12.1");
}
}

bool ElfReader::updateVariableMap(std::map<std::string, std::shared_ptr<Variable>>& vars)
Expand Down Expand Up @@ -122,4 +133,23 @@ std::string ElfReader::executeCommand(const char* cmd)
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
result += buffer.data();
return result;
}

int32_t ElfReader::extractGDBVersionNumber(const std::string&& versionString)
{
int32_t majorVersion = 0;
int32_t minorVersion = 0;
char dot;

std::istringstream iss(versionString);

while (!isdigit(iss.peek()) && iss.peek() != EOF)
iss.ignore();

iss >> majorVersion;

if (iss >> dot >> minorVersion)
return majorVersion * 10 + minorVersion;
else
return majorVersion * 10;
}
4 changes: 4 additions & 0 deletions src/ElfReader/ElfReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "Variable.hpp"
Expand All @@ -17,7 +18,10 @@ class ElfReader
bool updateVariableMap(std::map<std::string, std::shared_ptr<Variable>>& vars);
Variable::type getTypeFromString(const std::string& strType);

int32_t extractGDBVersionNumber(const std::string&& versionString);

private:
static constexpr int32_t gdbMinimumVersion = 120;
static constexpr uint8_t maxNameLength = 100;
static constexpr uint16_t maxGdbCmdLendth = 8160;
std::string& elfname;
Expand Down
3 changes: 3 additions & 0 deletions src/FileHandler/NFDFileHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include <NFDFileHandler.hpp>
#include <algorithm>
#include <string>
#include <utility>

#include "nfd.h"


bool NFDFileHandler::init()
{
return NFD_Init() != NFD_ERROR;
Expand Down
5 changes: 4 additions & 1 deletion src/FileHandler/NFDFileHandler.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#ifndef _NFDFILEHANDLER_HPP
#define _NFDFILEHANDLER_HPP

#include <IFileHandler.hpp>
#include <string>
#include <utility>

#include "IFileHandler.hpp"

class NFDFileHandler : public IFileHandler
{
Expand Down
Loading

0 comments on commit dd2d895

Please sign in to comment.