Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MCUViewer v1.0.1 CSV streamer #89

Merged
merged 25 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0a0d70c
feature: working on csv data streaming
klonyyy Sep 16, 2024
07d0d65
fix: fixing bugs in the csv streamer
klonyyy Sep 20, 2024
ea07e03
feature: working on csv streaming
klonyyy Sep 20, 2024
a32b87b
refactor: method to automatically align text
klonyyy Sep 21, 2024
5fe6ebc
refactor: refactoring csvStreamer
klonyyy Sep 21, 2024
b5e8987
docs: added doxygen comments to CSVStreamer
klonyyy Sep 21, 2024
fbddf90
refactor: refactoring csvStreamer
klonyyy Sep 21, 2024
54d6640
feature: added log settings saving
klonyyy Sep 22, 2024
1612477
wip: trying to fix Fedora install
klonyyy Sep 23, 2024
6121b4c
wip: trying to fix Fedora install
klonyyy Sep 23, 2024
a1cd990
fix: fixed problems with Fedora install #83
klonyyy Sep 24, 2024
b6d32c8
fix: trying to fix Windows pipeline
klonyyy Sep 24, 2024
986fd2c
fix: trying to fix Windows pipeline
klonyyy Sep 24, 2024
2e0f3c4
fix: trying to fix Windows pipeline
klonyyy Sep 24, 2024
3b004f6
fix: implemented production cmake switch
klonyyy Sep 24, 2024
ea55321
docs: added SEGGER's SWO wiki link
klonyyy Sep 24, 2024
2c464a4
feature: added mcu type to the issue template
klonyyy Sep 24, 2024
3cf1966
fix: fixed small bugs in csv streamer
klonyyy Sep 24, 2024
f676869
fix: fixed JLink trace hanging on Linux
klonyyy Sep 25, 2024
4631f42
feature: improved drag&drop #86
klonyyy Sep 29, 2024
9a31947
feature: added coloring for delayed timestamp 1/2 indicators
klonyyy Sep 29, 2024
2be05e3
fix: fixed segfault bug due to csv buffers being uninitialized
klonyyy Oct 2, 2024
877cb25
fix: fixed statistics segfault #88
klonyyy Oct 2, 2024
0110419
feature: set version to 1.0.1
klonyyy Oct 3, 2024
0f21f84
Merge pull request #81 from klonyyy/csv_streamer
klonyyy Oct 3, 2024
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
7 changes: 7 additions & 0 deletions .github/ISSUE_TEMPLATE/issue_template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ body:
placeholder: "e.g. ST-Link V2, ST-Link V3 MINIE, J-Link Ultra"
validations:
required: true
- type: input
id: MCU
attributes:
label: "Microcontroller:"
placeholder: "e.g. STM32G474CC (ST), LPC1768FBD100 (NXP)"
validations:
required: true
- type: textarea
id: issue_description
attributes:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ test/MCUViewer_test/.settings/
# Executables
*.out
*.app

# Log files
*.csv
39 changes: 28 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ endif()

project(MCUViewer)

set(MCUVIEWER_VERSION 1.0.0)

set(CMAKE_BUILD_TYPE Release)
set(MCUVIEWER_VERSION 1.0.1)
set(CMAKE_CXX_STANDARD 20)

set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

if(PRODUCTION)
set(CMAKE_BUILD_TYPE Release)
message("Building for production!")
else()
set(CMAKE_BUILD_TYPE Debug)
endif()

if(WIN32 AND "${PLATFORM}" STREQUAL "native")
set(LLVM_DIR "C:/msys64/mingw64/bin")
set(CMAKE_PREFIX_PATH ${LLVM_DIR} ${CMAKE_PREFIX_PATH})
Expand All @@ -33,8 +37,8 @@ if(WIN32 AND "${PLATFORM}" STREQUAL "native")
endif()

if(CMAKE_BUILD_TYPE STREQUAL "ReleaseWithDbg")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g1")
endif()

add_compile_options(-Wall
Expand All @@ -44,6 +48,10 @@ add_compile_options(-Wall
-Wno-unused-parameter
-Wno-missing-field-initializers)

if(WIN32)
add_compile_options(-Wa,-mbig-obj)
endif()

set(JLINK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/jlink/inc/)

if(UNIX)
Expand Down Expand Up @@ -74,6 +82,9 @@ if(UNIX)
set(LIB_INSTALL_PATH /usr/local/lib)
set(DESKTOP_FILE_PATH /usr/share/applications)

set(LIB_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/launch/install/Unix/MCUViewer.conf)
set(LIB_CONF_FILE_PATH /etc/ld.so.conf.d/)

if(APPLE)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
Expand All @@ -87,7 +98,7 @@ endif()

if(WIN32)
enable_language("RC")
set(ICON_RC "${CMAKE_CURRENT_SOURCE_DIR}/launch/icon.rc")
set(ICON_RC "${CMAKE_CURRENT_SOURCE_DIR}/launch/install/Windows/icon.rc")
set(GLFW3_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/GLFW/lib/windows/glfw3.dll)
set(STLINK_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/stlink/lib/windows/libstlink.a)
set(JLINK_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/jlink/lib/windows/JLink_x64.dll)
Expand Down Expand Up @@ -124,7 +135,8 @@ set(PROJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/TraceReader/TraceReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/TraceReader/StlinkTraceProbe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/TraceReader/JlinkTraceProbe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/GdbParser/GdbParser.cpp)
${CMAKE_CURRENT_SOURCE_DIR}/src/GdbParser/GdbParser.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/CSVStreamer/CSVStreamer.cpp)

set(IMGUI_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/third_party/imgui/imgui.cpp
Expand Down Expand Up @@ -188,7 +200,8 @@ target_include_directories(${EXECUTABLE} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/TraceReader
${CMAKE_CURRENT_SOURCE_DIR}/src/RingBuffer
${CMAKE_CURRENT_SOURCE_DIR}/src/Statistics
${CMAKE_CURRENT_SOURCE_DIR}/src/GdbParser)
${CMAKE_CURRENT_SOURCE_DIR}/src/GdbParser
${CMAKE_CURRENT_SOURCE_DIR}/src/CSVStreamer)

target_include_directories(${EXECUTABLE} SYSTEM PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/third_party/stlink/inc/
Expand Down Expand Up @@ -260,13 +273,16 @@ if(WIN32)
endif()

if(UNIX)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/launch/icon.png DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/launch/MCUViewer.desktop
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/launch/install/Unix/icon.png DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/launch/install/Unix/MCUViewer.desktop
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${DESKTOP_FILE_PATH})
install(FILES ${JLINK_LINUX}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${LIB_INSTALL_PATH})
install(FILES ${LIB_CONF_FILE}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${LIB_CONF_FILE_PATH})
set(CPACK_GENERATOR "DEB;RPM")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libglfw3 | libglfw3-wayland, libgl1, libglib2.0-0, libgtk-3-0, libstdc++6, libusb-1.0-0, gdb")
endif()
Expand All @@ -283,4 +299,5 @@ set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set(CPACK_NSIS_MODIFY_PATH ON)
set(CPACK_ALL_INSTALL_TYPES Full Developer)
set(CPACK_COMPONENT_APPLICATIONS_INSTALL_TYPES Full)
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${PROJECT_SOURCE_DIR}/launch/install/Unix/postinst")
include(CPack)
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ It works similar with other probes such as JLink, so be sure to check the maximu
Example project with MCUViewer config file is located in test/MCUViewer_test directory.

FAQ and common issues:

1. Problem: My trace doesn't look like it's supposed to and I get a lot of error frames
Answer: Try lowering the trace prescaller and check the SWO pin connection - the SWO pin output is high frequency and it shouldn't be too long.

Expand All @@ -100,6 +101,7 @@ Answer: Try logging fewer channels simultaneously. It could be that you've satur
3. Problem: My trace looks like it's supposed to but I get the "delayed timestamp 1" indicator
Answer: This is not a critical error, however, you should be cautious as some of the trace frames may be delayed. To fix try logging fewer channels simultaneously.

Please remember that although SWO is ARM standardized, there might be some differences the setup process. It should work without problems in most cases, but some MCUs might require some additional steps. Please see the [SEGGER's wiki page](https://wiki.segger.com/SWO) for more information.

## Building

Expand Down
12 changes: 10 additions & 2 deletions example/STMViewer_test/MCUViewer_project/MCUViewer_test.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ file_path = ../example/MCUViewer_test/Debug/MCUViewer_test.elf

[settings]
version = 0
sample_frequency_hz = 1000
sample_frequency_hz = 1000000
max_points = 10000
max_viewport_points = 5000
refresh_on_elf_change = true
stop_acq_on_elf_change = true
probe_type = 1
target_name = STM32G474CC
probe_mode = 1
probe_speed_khz = 50000
probe_speed_khz = 20000
probe_sn = 506003225
should_log = false
log_directory =

[trace_settings]
core_frequency = 150000
Expand All @@ -22,6 +24,12 @@ max_viewport_points_percent = 10
trigger_channel = -1
trigger_level = 0.000000
timeout = 2
probe_type = 1
target_name = STM32G474CC
probe_speed_khz = 10000
probe_sn = 506003225
should_log = true
log_directory = C:/Users/klonyyy/PROJECTS/MCUViewer_/MCUViewer/example/STMViewer_test/MCUViewer_project

[var0]
name = test.a
Expand Down
1 change: 1 addition & 0 deletions launch/install/Unix/MCUViewer.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/usr/local/lib
File renamed without changes.
File renamed without changes
File renamed without changes.
3 changes: 3 additions & 0 deletions launch/install/Unix/postinst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo "Running postinstall script..."
sudo ldconfig
File renamed without changes.
File renamed without changes.
109 changes: 109 additions & 0 deletions src/CSVStreamer/CSVStreamer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "CSVStreamer.hpp"

#include <fstream>
#include <future>
#include <iostream>
#include <string>

bool CSVStreamer::Buffer::appendLine(std::string& line)
{
if (isFull())
return false;

buffer[index] = line;
index++;
return true;
}

bool CSVStreamer::Buffer::isFull() const
{
return (index + 1) >= buffer.size();
}

CSVStreamer::CSVStreamer(spdlog::logger* logger) : logger(logger)
{
currentBuffer = &buffer1;
buffer1.nextBuffer = &buffer2;
buffer2.nextBuffer = &buffer1;
}

CSVStreamer::~CSVStreamer()
{
finishLogging();
}

bool CSVStreamer::prepareFile(std::string& directory)
{
filePath = directory + logFileName;
csvFile.open(filePath, std::ios::out);
if (!csvFile.is_open())
{
logger->error("Failed to open file: {}", filePath);
return false;
}
return true;
}

void CSVStreamer::createHeader(const std::vector<std::string>& values)
{
std::string header = "time,";
for (const auto& value : values)
{
header += value + ",";
}
header.back() = '\n';
currentBuffer->appendLine(header);
}

void CSVStreamer::writeLine(double time, const std::vector<double>& values)
{
std::string line = std::to_string(time) + ",";
for (const auto& value : values)
{
line += std::to_string(value) + ",";
}
line.back() = '\n';

currentBuffer->appendLine(line);

if (currentBuffer->isFull())
{
exchangeBuffers();

if (saveTask.valid() && saveTask.wait_for(std::chrono::seconds(0)) != std::future_status::ready)
logger->error("Buffer overrun in CSVStreamer object!");

saveTask = std::async(std::launch::async, &CSVStreamer::writeFile, this);
}
}

void CSVStreamer::exchangeBuffers()
{
processingBuffer = currentBuffer;
currentBuffer = currentBuffer->nextBuffer;
currentBuffer->index = 0;
}

void CSVStreamer::writeFile()
{
if (!csvFile.is_open())
{
logger->error("CSV file is not open!");
return;
}

for (size_t i = 0; i < processingBuffer->index; i++)
{
csvFile << processingBuffer->buffer[i];
}
}

void CSVStreamer::finishLogging()
{
if (csvFile.is_open())
{
exchangeBuffers();
writeFile();
csvFile.close();
}
}
63 changes: 63 additions & 0 deletions src/CSVStreamer/CSVStreamer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#ifndef _CSV_STREAMER_HPP
#define _CSV_STREAMER_HPP

#include <fstream>
#include <future>
#include <iostream>
#include <string>

#include "spdlog/spdlog.h"

class CSVStreamer
{
public:
struct Buffer
{
bool appendLine(std::string& line);
bool isFull() const;

std::array<std::string, 1000> buffer;
size_t index;
Buffer* nextBuffer;
};

CSVStreamer(spdlog::logger* logger);
~CSVStreamer();

/// @brief Creates file in given directory with a fixed name
/// @param directory directory string
/// @return
bool prepareFile(std::string& directory);

/// @brief create csv file header from given argument, first column - time - is added internally
/// @param values table headers
void createHeader(const std::vector<std::string>& values);

/// @brief writes single line to internal buffer
/// @param time
/// @param values
void writeLine(double time, const std::vector<double>& values);

/// @brief exchanges the buffer that is being processed with the one that's being written to
void exchangeBuffers();

/// @brief writes the processing buffer to the opened csv file
void writeFile();

/// @brief writes the rest of the buffer to the file and closes it
void finishLogging();

private:
const char* logFileName = "/logfile.csv";

spdlog::logger* logger;
std::future<void> saveTask{};
std::string filePath;
std::ofstream csvFile;
Buffer buffer1{};
Buffer buffer2{};
Buffer* currentBuffer;
Buffer* processingBuffer;
};

#endif
Loading