diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..3e2e0ba --- /dev/null +++ b/.clang-format @@ -0,0 +1,46 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: BlockIndent +AlignConsecutiveBitFields: + Enabled: true + PadOperators: true +AlignConsecutiveDeclarations: + Enabled: true + PadOperators: true +AlignConsecutiveMacros: + PadOperators: true +AlignEscapedNewlines: Left +AllowShortBlocksOnASingleLine: Empty +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +BreakInheritanceList: AfterColon +ColumnLimit: 120 +EmptyLineBeforeAccessModifier: Always +IncludeCategories: + - Regex: '^<.*>' + Priority: 1 + SortPriority: 1 + - Regex: '^".*"' + SortPriority: 2 +IncludeIsMainRegex: '$' +IndentCaseLabels: true +IndentExternBlock: NoIndent +IndentPPDirectives: BeforeHash +IndentRequiresClause: false +IndentWidth: 4 +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: false +PackConstructorInitializers: NextLine +PointerAlignment: Left +SeparateDefinitionBlocks: Always +ShortNamespaceLines: 0 +SortIncludes: Never +SpaceInEmptyBlock: true +SpacesBeforeTrailingComments: 2 +TabWidth: 4 +... + diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..fd05192 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,60 @@ +--- +Checks: + -*, + bugprone-*, + -bugprone-easily-swappable-parameters, + -bugprone-narrowing-conversions, + -bugprone-dynamic-static-initializers, + clang-*, + -clang-diagnostic-unused-command-line-argument, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-avoid-do-while, + -cppcoreguidelines-pro-type-union-access, + google-*, + llvm-*, + -llvm-header-guard, + misc-*, + -misc-include-cleaner, + -misc-const-correctness, + -misc-use-anonymous-namespace, + modernize-*, + -modernize-use-nodiscard, + -modernize-use-trailing-return-type, + performance-*, + readability-*, + -readability-duplicate-include, + -readability-magic-numbers, +WarningsAsErrors: '*' +HeaderFileExtensions: + - '' + - h + - hh + - hpp + - hxx +ImplementationFileExtensions: + - c + - cc + - cpp + - cxx +HeaderFilterRegex: '(include|config)/.*.hpp' +FormatStyle: none +CheckOptions: + readability-magic-numbers.IgnorePowersOf2IntegerValues: true + readability-magic-numbers.IgnoreBitFieldsWidths: true + readability-magic-numbers.IgnoreUserDefinedLiterals: true + readability-identifier-length.MinimumVariableNameLength: 2 + readability-identifier-length.IgnoredVariableNames: ^[nxyz]$ + readability-identifier-length.MinimumParameterNameLength: 2 + readability-identifier-length.IgnoredParameterNames: ^[nxyz]$ + misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: true + cppcoreguidelines-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion: false + readability-function-cognitive-complexity.Threshold: 30 +SystemHeaders: false +ExtraArgsBefore: + - '--target=arm-none-eabi' + - '--sysroot=/usr/lib/arm-none-eabi/' + - '-I/usr/lib/arm-none-eabi/include/c++/13.2.1/' + - '-I/usr/lib/arm-none-eabi/include/c++/13.2.1/arm-none-eabi/' +... diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 0000000..18a2677 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,26 @@ +{ + "name": "STM32 Template Container", + "dockerComposeFile": "compose.yaml", + "service": "dev", + "shutdownAction": "stopCompose", + "workspaceFolder": "/project", + "overrideCommand": true, + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools", + "cschlosser.doxdocgen", + "davidanson.vscode-markdownlint", + "marus25.Cortex-Debug", + "dan-c-underwood.arm", + "streetsidesoftware.code-spell-checker", + "streetsidesoftware.code-spell-checker-portuguese-brazilian", + "twxs.cmake", + "ms-vscode.cmake-tools", + "seatonjiang.gitmoji-vscode", + "mhutchie.git-graph", + "xaver.clang-format", + ] + } + } +} diff --git a/.docker/.dockerignore b/.docker/.dockerignore new file mode 100644 index 0000000..cc0981b --- /dev/null +++ b/.docker/.dockerignore @@ -0,0 +1,18 @@ +.git/ +.github/ +.vscode/ +.cache/ +.idea/ +build/ +cube/ +!**.ioc + +.devcontainer +.gitignore +.gitmodules +Doxyfile +LICENSE + +*.yaml +*.md +*.iml diff --git a/.docker/Dockerfile b/.docker/Dockerfile new file mode 100644 index 0000000..3c1e772 --- /dev/null +++ b/.docker/Dockerfile @@ -0,0 +1,39 @@ +################################## +# Base image for STM32 Template # +################################## +FROM thunderatz/stm32cubemx:6.13.0-f1 AS base + +RUN apt-get update -y > /dev/null && \ + apt-get upgrade -y > /dev/null && \ + apt-get install -y \ + gcc-arm-none-eabi \ + make \ + cmake \ + clang-tidy \ + clang-format > /dev/null\ + && apt-get clean > /dev/null + +WORKDIR /project +COPY ./cube/*.ioc /project/cube/ + +ENV CUBE_CMD=${CUBE_PATH}/STM32CubeMX + +ENV DISPLAY=:10 +ARG PROJECT_NAME=stm32_project_template + +RUN Xvfb :10 -ac & \ + echo "config load /project/cube/${PROJECT_NAME}.ioc\nproject generate\nexit\n" > .cube && \ + $CUBE_PATH/STM32CubeMX -q /project/.cube && \ + rm .cube && \ + pkill -f Xvfb + +RUN rm /tmp/.X10-lock + +RUN echo "trap 'chown -R ubuntu /project' EXIT" >> "/root/.bashrc" + +################################### +# Build image for STM32 Template # +################################### +FROM base AS build + +COPY . /project diff --git a/.docker/scripts/build.sh b/.docker/scripts/build.sh new file mode 100755 index 0000000..fbb346f --- /dev/null +++ b/.docker/scripts/build.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +BUILD_ARG=$1 + +rm -rf /project/build || exit 1 +mkdir -p /project/build || exit 1 +cd /project/build || exit 1 +cmake .. -DBUILD_TYPE=Release $BUILD_ARG || exit 1 + +echo "Compiling main..." | sed 's/.*/\x1b[34m&\x1b[0m/' + +make -j + +if [ $? -eq 0 ]; then + echo "Compilation successful." | sed 's/.*/\x1b[32m&\x1b[0m/' +else + echo "Compilation failed." | sed 's/.*/\x1b[31m&\x1b[0m/' + exit 1 +fi + +echo "Compiling tests..." | sed 's/.*/\x1b[34m&\x1b[0m/' + +make test_all -j + +if [ $? -eq 0 ]; then + echo "Tests compiled successfully." | sed 's/.*/\x1b[32m&\x1b[0m/' +else + echo "Tests compilation failed." | sed 's/.*/\x1b[31m&\x1b[0m/' + exit 1 +fi diff --git a/.docker/scripts/check_format.sh b/.docker/scripts/check_format.sh new file mode 100755 index 0000000..b034cf6 --- /dev/null +++ b/.docker/scripts/check_format.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +FILES=$(find . \( -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) \ + -not \( -path "*/cube/*" -o -path "*/build/*" -o -path "*/libs/*" \)) + +for FILE in $FILES; do + clang-format -style=file -output-replacements-xml $FILE | grep "/dev/null + if [ $? -eq 0 ]; then + echo "Code not properly formatted (File: $FILE). Please run make format." | sed 's/.*/\x1b[31m&\x1b[0m/' + exit 1 + fi +done + +echo "Code properly formatted." | sed 's/.*/\x1b[32m&\x1b[0m/' diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 1fc951e..0000000 --- a/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 4 - -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false - -[Makefile] -indent_style = tab diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 10bb493..425d8d9 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -4,8 +4,8 @@ cd "$( dirname "${BASH_SOURCE[0]}" )"/.. for file in $(git diff --cached --name-only --diff-filter=ACMRT | grep "\.[ch]$") do - uncrustify -q -f $file -c uncrustify.cfg --check > /dev/null 2> /dev/null - if [ $? -ne 0 ]; then + clang-format -style=file -output-replacements-xml $file | grep "/dev/null + if [ $? -eq 0 ]; then echo "Code not properly formatted. Please run make format and git add again." git reset -q HEAD exit 1 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..926c3df --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,66 @@ +name: Build lint and check formatting + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: + - develop + - main + push: + branches: + - develop + - main + +jobs: + build: + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + steps: + - name: 🔀 Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: 🗃️ Check cache + id: cache + uses: actions/cache/restore@v4 + with: + path: .docker/Dockerfile + key: ${{ hashFiles('.github/*', 'cmake/*', '**/*.cpp', '**/*.hpp', '**/*.ioc', '.clang*', 'CMakeLists.txt', '.docker/*') }} + lookup-only: true + + - name: 🔧 Set up Docker Buildx + if: steps.cache.outputs.cache-hit != 'true' + uses: docker/setup-buildx-action@v3 + + - name: 🐋 Build Docker image + if: steps.cache.outputs.cache-hit != 'true' + uses: docker/build-push-action@v6 + with: + context: . + file: .docker/Dockerfile + target: build + load: true + cache-from: type=gha + cache-to: type=gha,mode=max + no-cache-filters: build + tags: project:build + + - name: 🎨 Check code formatting + if: steps.cache.outputs.cache-hit != 'true' + run: docker run --rm project:build /bin/bash /project/.docker/scripts/check_format.sh + + - name: 🔨 Build project + if: steps.cache.outputs.cache-hit != 'true' + run: docker run --rm project:build /bin/bash /project/.docker/scripts/build.sh + + - name: 🚨 Lint project + if: steps.cache.outputs.cache-hit != 'true' + run: docker run --rm project:build /bin/bash /project/.docker/scripts/build.sh -DLINTER_MODE=ON + + - name: 🗃️ Save cache + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: .docker/Dockerfile + key: ${{ steps.cache.outputs.cache-primary-key }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..2187bd1 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,42 @@ +name: Add binaries to release + +on: + release: + types: [published] + +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: 🔀 Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: 🔧 Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: 🐋 Build Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: .docker/Dockerfile + target: build + load: true + cache-from: type=gha + cache-to: type=gha,mode=max + no-cache-filters: build + tags: project:build + + - name: 🔨 Build project + run: | + docker run --name release project:build /bin/bash /project/.docker/scripts/build.sh + docker cp release:/project/build/ output/ + + - name: ⬆️ Upload binaries + run: gh release upload ${{ github.event.release.tag_name }} output/*.hex output/*.elf + env: + GITHUB_TOKEN: ${{ github.token }} diff --git a/.gitignore b/.gitignore index 7e94689..c4eafad 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ build/ -g .jlink-flash .cube +docs # Created by https://www.gitignore.io/api/visualstudiocode,c @@ -66,7 +67,6 @@ dkms.conf ### VisualStudioCode ### .vscode/* !.vscode/settings.json -!.vscode/tasks.json !.vscode/extensions.json diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 2daa810..0000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "lib/stm32-cmake"] - path = lib/stm32-cmake - url = git@github.com:ThundeRatz/stm32-cmake.git - branch = master diff --git a/.vscode/extensions.json b/.vscode/extensions.json index dcc196a..15415b6 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -6,10 +6,16 @@ "recommendations": [ "ms-vscode.cpptools", "cschlosser.doxdocgen", - "editorconfig.editorconfig", "davidanson.vscode-markdownlint", - "zachflower.uncrustify", "marus25.Cortex-Debug", + "dan-c-underwood.arm", + "streetsidesoftware.code-spell-checker", + "streetsidesoftware.code-spell-checker-portuguese-brazilian", + "twxs.cmake", + "ms-vscode.cmake-tools", + "seatonjiang.gitmoji-vscode", + "mhutchie.git-graph", + "xaver.clang-format", ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. diff --git a/.vscode/settings.json b/.vscode/settings.json index 3eaff06..04adefe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,14 +8,20 @@ "files.insertFinalNewline": true, "files.eol": "\n", "files.encoding": "utf8", + + "editor.defaultFormatter": "xaver.clang-format", "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", - "[c]": { + "[c, cpp]": { "editor.formatOnSave": true }, - "[markdown]": { - "files.trimTrailingWhitespace": false, - "files.trimFinalNewlines": false - } + "doxdocgen.generic.dateFormat": "MM/YYYY", + "doxdocgen.file.fileOrder": [ + "file", + "empty", + "brief", + "empty", + "custom" + ], } diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index f6361ee..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "Build Project", - "type": "shell", - "command": "make", - "group": "build", - "presentation": { - "reveal": "always", - "panel": "new" - }, - "problemMatcher": [] - }, - { - "label": "Clean Project", - "type": "shell", - "command": "make clean", - "group": "build", - "presentation": { - "reveal": "silent", - "panel": "dedicated" - }, - "problemMatcher": [] - }, - { - "label": "Rebuild Project", - "group": "build", - "dependsOn": [ - "Clean Project", - "Build Project", - ], - "problemMatcher": [], - }, - { - "label": "Flash Program", - "type": "shell", - "command": "make flash", - "group": "build", - "presentation": { - "reveal": "always", - "panel": "new" - }, - "problemMatcher": [], - }, - { - "label": "Build and Flash", - "group": "build", - "dependsOn": [ - "Build Project", - "Flash Program", - ], - "problemMatcher": [], - } - ] -} diff --git a/CMakeLists.txt b/CMakeLists.txt index 11b7187..2e2c322 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,231 +2,158 @@ # ThundeRatz Robotics Team # Brief: This file contains the configuration of the CMake project ## and all the files that you should edit to configure your project -# 04/2023 +# 03/2025 -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 3.22) ############################################################################### -## CMake Configuration +## Project Configuration ############################################################################### -set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/lib/stm32-cmake/cmake/stm32_gcc.cmake) -set(CMAKE_C_STANDARD 11) - -## Options: -# Release: high optimization level, no debug info, code or asserts. -# Debug: No optimization, asserts enabled, [custom debug (output) code enabled], debug info included in executable (so you can step through the code with a debugger and have address to source-file:line-number translation). -# RelWithDebInfo: optimized, with debug info, but no debug (output) code or asserts. -# MinSizeRel: same as Release but optimizing for size rather than speed. -# @see: https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html -set(CMAKE_BUILD_TYPE Debug) - -# Generate compile_commands.json for compatibility with LSPs -# @see: https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -# Cube file name without .ioc extension -project(stm32_project_template C ASM) +set(CMAKE_PROJECT_NAME stm32_project_template) # Set the board version to an empty string if your board doesn't have a version set(BOARD_VERSION "") -# Device Configuration -set(DEVICE_CORTEX F3) -set(DEVICE_FAMILY STM32F3xx) -set(DEVICE_TYPE STM32F303xx) -set(DEVICE_DEF STM32F303xE) -set(DEVICE STM32F303RE) - -# DEVICE_FAMILY_COMPACT is the same as DEVICE_FAMILY but without the STM32 prefix -string(REPLACE "STM32" "" DEVICE_FAMILY_COMPACT ${DEVICE}) - if(BOARD_VERSION STREQUAL "") - set(PROJECT_RELEASE ${PROJECT_NAME}) + set(PROJECT_RELEASE ${CMAKE_PROJECT_NAME}) else() - set(PROJECT_RELEASE ${PROJECT_NAME}_${BOARD_VERSION}) + set(PROJECT_RELEASE ${CMAKE_PROJECT_NAME}_${BOARD_VERSION}) endif() -set(TARGET_BOARD target_${PROJECT_RELEASE}) ############################################################################### -## Global compilation config +## CMake Configuration ############################################################################### -set(LAUNCH_JSON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/.vscode/launch.json) -set(DEBUG_FILE_NAME ${PROJECT_NAME}) - -include(cmake/config_validation.cmake) -include(cmake/workspace.cmake) -include(cmake/targets.cmake) +set(CMAKE_C_STANDARD 17) +set(CMAKE_CXX_STANDARD 26) -find_package(CMSIS COMPONENTS ${DEVICE} REQUIRED) -find_package(HAL COMPONENTS STM32${DEVICE_CORTEX} REQUIRED) - -add_compile_options( - -Wall - -Wextra - -Wfatal-errors - -mthumb - -fdata-sections - -ffunction-sections - -fmessage-length=0 - -MMD - -MP -) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) -add_compile_definitions(${DEVICE_DEF} USE_HAL_DRIVER) +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) ############################################################################### -## Project dependencies +## Global compilation config ############################################################################### -set(DEPENDENCIES - m # math library - - HAL::STM32::${DEVICE_CORTEX} +set(LAUNCH_JSON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/.vscode/launch.json) +set(DEBUG_FILE_NAME ${CMAKE_PROJECT_NAME}) - HAL::STM32::${DEVICE_CORTEX}::ADCEx - HAL::STM32::${DEVICE_CORTEX}::DMA - HAL::STM32::${DEVICE_CORTEX}::GPIO - HAL::STM32::${DEVICE_CORTEX}::I2C - HAL::STM32::${DEVICE_CORTEX}::SPI - HAL::STM32::${DEVICE_CORTEX}::TIMEx - HAL::STM32::${DEVICE_CORTEX}::UARTEx - HAL::STM32::${DEVICE_CORTEX}::WWDG +include(cmake/config_validation.cmake) - HAL::STM32::${DEVICE_CORTEX}::RCCEx - HAL::STM32::${DEVICE_CORTEX}::CORTEX +set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cube) +include(cube/cmake/gcc-arm-none-eabi.cmake) +set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - CMSIS::STM32::${DEVICE_FAMILY_COMPACT} - STM32::NoSys -) +project(${CMAKE_PROJECT_NAME} C CXX ASM) -# Add libraries .c files here -set(LIB_SOURCES - # lib/lib_name/src/file1.c - # lib/lib_name/src/file2.c -) +include(cmake/targets.cmake) +include(cmake/utilities.cmake) -# Add libraries include directories here -set(LIB_INCLUDE_DIRECTORIES - # lib/lib_name/inc/ -) +add_subdirectory(cube/cmake/stm32cubemx) ############################################################################### -## Include directories +## CubeMX Configuration ############################################################################### -set(C_INCLUDE_DIRECTORIES - ./inc - ./cube/Inc -) +get_target_property(CUBE_INCLUDE_DIRECTORIES stm32cubemx INTERFACE_INCLUDE_DIRECTORIES) +get_target_property(CUBE_SOURCES stm32cubemx INTERFACE_SOURCES) +get_target_property(CUBE_COMPILE_DEFINITIONS stm32cubemx INTERFACE_COMPILE_DEFINITIONS) -set(TEST_INCLUDE_DIRECTORIES - ./tests/inc +# Remove warnings from Cube sources +set_source_files_properties( + ${CUBE_SOURCES} + PROPERTIES + COMPILE_FLAGS "-w" ) +add_compile_definitions(${CUBE_COMPILE_DEFINITIONS}) + ############################################################################### ## Input files ############################################################################### -file(GLOB_RECURSE C_SOURCES CONFIGURE_DEPENDS "src/*.c") -file(GLOB_RECURSE C_HEADERS CONFIGURE_DEPENDS "inc/*.h") +file(GLOB_RECURSE FORMAT_SOURCES CONFIGURE_DEPENDS "src/*.cpp" "config/*.cpp" "tests/*.cpp") +file(GLOB_RECURSE FORMAT_HEADERS CONFIGURE_DEPENDS "include/*.hpp" "config/*.hpp" "tests/*.hpp") -file(GLOB_RECURSE TESTS_SOURCES CONFIGURE_DEPENDS "tests/src/*.c") -file(GLOB_RECURSE TESTS_HEADERS CONFIGURE_DEPENDS "tests/inc/*.h") -file(GLOB_RECURSE TESTS_BIN CONFIGURE_DEPENDS "tests/bin/*.c") +generate_format_target(FORMAT_SOURCES FORMAT_HEADERS) -file(GLOB_RECURSE CUBE_SOURCES CONFIGURE_DEPENDS "cube/Src/*.c") +file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "src/**.cpp") +file(GLOB_RECURSE PROJECT_TESTS CONFIGURE_DEPENDS "tests/src/**.cpp") -# Remove system_xxx.c file from CubeMX, as it is already included in CMSIS -string(TOLOWER ${DEVICE_FAMILY} DEVICE_FAMILY_LOWER) -list(REMOVE_ITEM CUBE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cube/Src/system_${DEVICE_FAMILY_LOWER}.c) - -# Add here the headers to be included in all files -set(FORCED_INCLUDE_HEADERS -) - -targets_generate_format_target(C_SOURCES C_HEADERS TESTS_SOURCES TESTS_HEADERS TESTS_BIN) +list(FILTER PROJECT_SOURCES EXCLUDE REGEX "main.cpp") ############################################################################### -## Main executable target +## Project library ############################################################################### -add_executable(${PROJECT_NAME} - ${CUBE_SOURCES} - ${C_SOURCES} - ${LIB_SOURCES} +add_library(${PROJECT_NAME}_static STATIC + ${PROJECT_SOURCES} +) + +target_include_directories(${PROJECT_NAME}_static SYSTEM PUBLIC + ${CUBE_INCLUDE_DIRECTORIES} +) + +target_include_directories(${PROJECT_NAME}_static PUBLIC + include + config ) -target_include_directories(${PROJECT_NAME} PUBLIC - ${C_INCLUDE_DIRECTORIES} - ${LIB_INCLUDE_DIRECTORIES} - ${CMSIS_INCLUDE_DIRS} - ${HAL_INCLUDE_DIRS} +target_link_libraries(${PROJECT_NAME}_static PRIVATE + stm32cubemx ) -target_precompile_headers(${PROJECT_NAME} PUBLIC - ${FORCED_INCLUDE_HEADERS} +add_library(${PROJECT_NAME}_lib INTERFACE) +target_link_libraries(${PROJECT_NAME}_lib INTERFACE + "-Wl,--whole-archive" ${PROJECT_NAME}_static "-Wl,--no-whole-archive" ) -target_link_libraries(${PROJECT_NAME} - ${DEPENDENCIES} +############################################################################### +## Main executable target +############################################################################### + +add_executable(${PROJECT_NAME} + "${CMAKE_SOURCE_DIR}/src/main.cpp" ) -target_link_options(${PROJECT_NAME} PUBLIC - --specs=nano.specs +target_link_libraries(${PROJECT_NAME} PRIVATE + ${PROJECT_NAME}_lib ) -stm32_print_size_of_target(${PROJECT_NAME}) -stm32_generate_hex_file(${PROJECT_NAME}) +generate_hex_file(${PROJECT_NAME}) +print_size_of_target(${PROJECT_NAME}) -targets_generate_vsfiles_target(${PROJECT_NAME}) -targets_generate_flash_target(${PROJECT_NAME}) -targets_generate_helpme_target() +generate_helpme_text() +generate_vscode_tasks_json() +generate_debug_target(${PROJECT_NAME}) +generate_flash_target(${PROJECT_NAME}) ############################################################################### ## Generate test executables ############################################################################### -# Since each test has its own main function, we don't need the main.c from the project -list(REMOVE_ITEM C_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c) - -foreach(TEST_FILE ${TESTS_BIN}) - - # If TEST_FILE contains /dir1/dir2/file.c, TEST_NAME will be 'file' +foreach(TEST_FILE ${PROJECT_TESTS}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WLE) add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} - ${CUBE_SOURCES} - ${C_SOURCES} - ${TESTS_SOURCES} - ${LIB_SOURCES} - ) - - target_include_directories(${TEST_NAME} PUBLIC - ${C_INCLUDE_DIRECTORIES} - ${LIB_INCLUDE_DIRECTORIES} - ${CMSIS_INCLUDE_DIRS} - ${HAL_INCLUDE_DIRS} - ${TEST_INCLUDE_DIRECTORIES} - ) - - target_precompile_headers(${TEST_NAME} PUBLIC - ${FORCED_INCLUDE_HEADERS} ) - target_link_libraries(${TEST_NAME} - ${DEPENDENCIES} + target_link_libraries(${TEST_NAME} PRIVATE + ${PROJECT_NAME}_lib ) - target_link_options(${TEST_NAME} PUBLIC - --specs=nano.specs + target_include_directories(${TEST_NAME} PUBLIC + tests/include ) - stm32_generate_hex_file(${TEST_NAME}) - - targets_generate_vsfiles_target(${TEST_NAME}) - targets_generate_flash_target(${TEST_NAME}) + generate_hex_file(${TEST_NAME}) + print_size_of_target(${TEST_NAME}) + generate_debug_target(${TEST_NAME}) + generate_flash_target(${TEST_NAME}) endforeach() + +generate_test_all_target(${PROJECT_TESTS}) diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..9ee6eaa --- /dev/null +++ b/Doxyfile @@ -0,0 +1,26 @@ +PROJECT_NAME = "STM32 Project Template" +OUTPUT_DIRECTORY = docs/ +DISTRIBUTE_GROUP_DOC = YES +NUM_PROC_THREADS = 0 +EXTRACT_PRIVATE = YES +EXTRACT_PRIV_VIRTUAL = YES +EXTRACT_STATIC = YES +CASE_SENSE_NAMES = YES +SHOW_INCLUDE_FILES = NO +RECURSIVE = YES +EXCLUDE = "tests/" \ + "cube/" \ + "build/" +EXCLUDE_PATTERNS = "*/libs/*" +INPUT_FILTER = "sed -e 's/#include <.*>/ /'" +VERBATIM_HEADERS = NO +GENERATE_HTML = NO +UML_LOOK = YES +UML_LIMIT_NUM_FIELDS = 50 +DOT_WRAP_THRESHOLD = 100 +TEMPLATE_RELATIONS = YES +CALL_GRAPH = YES +CALLER_GRAPH = YES +DOT_GRAPH_MAX_NODES = 100 +MAX_DOT_GRAPH_DEPTH = 1 +DOT_MULTI_TARGETS = YES diff --git a/LICENSE b/LICENSE index 5cdda2d..c66c12b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 ThundeRatz Robotics Team +Copyright (c) 2025 ThundeRatz Robotics Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/PreLoad.cmake b/PreLoad.cmake deleted file mode 100644 index 6afeb47..0000000 --- a/PreLoad.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# Name: PreLoad.cmake -# ThundeRatz Robotics Team -# Brief: This file sets the CMAKE_GENERATOR to MSYS Makefiles if a Windows OS is being used -# @see: https://stackoverflow.com/questions/11269833/cmake-selecting-a-generator-within-cmakelists-txt -# 04/2023 - -if(CMAKE_HOST_WIN32) - set(CMAKE_GENERATOR "MSYS Makefiles" CACHE INTERNAL "" FORCE) - message(STATUS "Windows Host - CMAKE_GENERATOR set to: ${CMAKE_GENERATOR}") -endif() diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..4f46f5c --- /dev/null +++ b/README.en.md @@ -0,0 +1,472 @@ + +
+ +# STM32 Project Template + +Template for projects with STM32 microcontrollers using STM32CubeMX and CMake + +
+ +
+ Made with C++ + Uses STM32CubeMX + For Embedded Systems + MIT License + Leia em português +
+ + +## 📑 Table of Contents + +- [📑 Table of Contents](#-table-of-contents) +- [📁 Folder Structure](#-folder-structure) +- [🛠 Configuration](#-configuration) + - [Dependencies](#dependencies) + - [1. CubeMX Project](#1-cubemx-project) + - [2. CMakeLists.txt](#2-cmakeliststxt) +- [🔨 Compilation](#-compilation) +- [🚀 Execution](#-execution) +- [🧪 Tests](#-tests) +- [🐛 Debugging](#-debugging) +- [💄 Code Style](#-code-style) + - [🎨 Formatting](#-formatting) + - [🚨 Linter](#-linter) +- [📦 Submodules](#-submodules) +- [🐋 Docker](#-docker) +- [📝 Documentation](#-documentation) +- [🛠️ Windows Development Environment (WSL)](#️-windows-development-environment-wsl) +- [👥 Contribution Guidelines](#-contribution-guidelines) + - [💬 Git Commit Messages](#-git-commit-messages) + - [🔀 GitHub Flow](#-github-flow) +- [🙌 Acknowledgements](#-acknowledgements) + +## 📁 Folder Structure + +- **.docker/** - Docker configurations and scripts +- **.github/** - GitHub Actions configurations +- **.vscode/** - Visual Studio Code configurations +- **cmake/** - Custom functions for CMake +- **config/** - Project configurations +- **cube/** - STM32CubeMX project (.ioc and generated files) +- **include/** - Header files +- **lib/** - Submodules and external libraries +- **src/** - Main application source code +- **test/** - Tests + +Additionally, the following folders contain generated files and are not versioned: + +- **build/** - Files generated during compilation +- **docs/** - Generated documentation + +## 🛠 Configuration + +### Dependencies + +To make the most of this template, from basic compilation to debugging and flashing, some tools are essential and others are optional, depending on your workflow. Below we describe the main ones, with example commands for installation on Debian/Ubuntu systems (like Ubuntu, Mint). If you use another Linux distribution (Fedora, Arch) or macOS, adapt the commands for your package manager (`dnf`, `pacman`, `brew`, etc.). + +#### Essential to Start + +You will need these tools just to clone and compile the project: + +* **`git`**: The fundamental version control system for downloading this template, managing your changes, and handling any external libraries included as submodules. + ```bash + sudo apt install git + ``` +* **`cmake`**: The heart of the build system. It interprets the instructions in the `CMakeLists.txt` file and generates the necessary files (Makefiles) for compilation to occur in your specific environment. + ```bash + sudo apt install cmake + ``` +* **`make`**: This tool reads the Makefiles generated by CMake and executes the compilation commands in the correct order. It's what you usually invoke to compile (`make -j`). + ```bash + sudo apt install make + ``` +* **`gcc-arm-none-eabi` Toolchain**: This is the set of cross-compilation tools (C/C++ compiler, linker, etc.) that transforms your source code into executable binary code for STM32 microcontrollers (based on ARM Cortex-M). + ```bash + sudo apt install gcc-arm-none-eabi + ``` +* **`STM32CubeMX`**: To visually configure your STM32 peripherals, clock system, and generate the base initialization code (including the `.ioc` file), you will need this graphical tool from ST. Download the installer directly from the [STMicroelectronics website](https://www.st.com/en/development-tools/stm32cubemx.html). For CMake to interact with it (useful for generating code), ensure the executable is in your system's `PATH` or that the `CUBE_CMD` environment variable points to it. *(Manual installation via download)*. + +> [!WARNING] +> Currently, this template does not support CubeMX versions above 6.13. + +* **`STM32CubeProgrammer`**: Essential for flashing the compiled firmware onto your microcontroller using an ST-LINK programmer. It is required to use the `make flash` command. Download the installer from the [STMicroelectronics website](https://www.st.com/en/development-tools/stm32cubeprog.html) and ensure the command-line executable (`STM32_Programmer_CLI`) is in your `PATH`. *(Manual installation via download)*. + +#### Additional Tools for Extra Features + +These tools enable features such as graphical configuration, flashing, advanced debugging, code standardization, and documentation. Install the ones relevant to you: + +* **`Segger J-Link Software`**: If you use a J-Link programmer/debugger, you will need Segger's software package. It provides the necessary drivers and the GDB server (`JLinkGDBServer`) for debugging and for the `make jflash` command. Get the "J-Link Software and Documentation Pack" from the [Segger website](https://www.segger.com/downloads/jlink/). The GDB server needs to be accessible (via `PATH` or the `JLINK_CMD` variable). *(Manual installation via download)*. +* **`openocd`**: A popular open-source alternative as a debug server (GDB Server). The Open On-Chip Debugger supports various adapters, including ST-LINK, and is one of the options configured for debugging in this template. + ```bash + sudo apt install openocd + ``` +* **`stlink-tools`**: A set of command-line tools specific to ST-LINK adapters. Includes `st-flash` for flashing and `st-util` which can act as a simple GDB server, being another option for debugging. + ```bash + sudo apt install stlink-tools + ``` +* **`gdb-multiarch`**: The GNU Debugger client, capable of understanding multiple architectures like ARM. This is what you use to connect to GDB servers (JLinkGDBServer, OpenOCD, st-util) and control program execution step-by-step, inspect variables, etc. Often installed alongside the `gcc-arm-none-eabi` toolchain, but otherwise, install with: + ```bash + sudo apt install gdb-multiarch + ``` +* **`clang-format`**: To keep the code consistently and automatically formatted, we use `clang-format`. It applies the rules defined in the `.clang-format` file to your code when you run `make format`. + ```bash + sudo apt install clang-format + ``` +* **`clang-tidy`**: A static analysis tool (linter) that helps identify potential problems, bugs, and deviations from good practices in C/C++ code. It uses the rules from the `.clang-tidy` file and runs during compilation if you configure CMake with `-DLINTER_MODE=ON` or `-DLINTER_MODE=FIX`. + ```bash + sudo apt install clang-tidy + ``` +* **`doxygen` & Co.**: To automatically generate documentation from comments in the code, we use `doxygen`. To generate diagrams (like call graphs), it can use `graphviz`. And if you want the documentation also in PDF, it uses `LaTeX` (provided by `texlive`). Run `make docs` to generate the documentation. Install the necessary tools with: + ```bash + sudo apt install doxygen graphviz texlive-latex-extra texlive-fonts-extra + ``` + *(Note that the `texlive` installation can take up considerable disk space).* + +> [!TIP] +> Remember to consult the specific sections of this README (Compilation, Execution, Debugging, Code Style, Documentation) to better understand how and when each of these optional tools comes into play in the workflow provided by the template. + +### 1. CubeMX Project + +Starting an STM32 project is done in STM32CubeMX. For this, you need to install [STM32CubeMX](https://www.st.com/en/development-tools/stm32cubemx.html) and configure the project: + +> [!IMPORTANT] +> For CMake to find and use STM32CubeMX automatically (e.g., when generating code), ensure that the CubeMX executable is in your system's `PATH` or set the `CUBE_CMD` environment variable with the full path to the executable. + +1. Create a new project in the `cube/` folder +2. Settings: + - **Project Manager > Project > Application Structure:** Basic + - **Project Manager > Project > Toolchain/IDE:** CMake + - **Project Manager > Code Generator > Generate peripheral initialization:** Pair of .c/.h files per peripheral + - **Project Manager > Code Generator > Delete previous generated files when not regenerated:** Enabled + +### 2. CMakeLists.txt + +Edit the main `CMakeLists.txt` file with your project information: + +```cmake +# Project name (same as the .ioc file without extension) +set(CMAKE_PROJECT_NAME my_project) + +# Board version (optional) +set(BOARD_VERSION "") +``` + +## 🔨 Compilation + +Before compiling for the first time, make sure Git submodules (if any) have been initialized: + +```bash +git submodule update --init --recursive +``` + +Now, create a `build/` folder in the project root (if it doesn't exist yet) and enter it: + +```bash +mkdir -p build +cd build +``` + +Inside it, configure the environment with CMake: + +```bash +cmake .. +``` + +Then, compile the project: + +```bash +make -j +``` + +> The `-j` parameter enables parallel compilation, using more of your processor cores to speed up the process. + +### Clean files + +```bash +make clear # User code +make clear_cube # Cube libraries +make clear_all # Everything +``` + +### Manual + +To get a complete list of available `make` commands (defined in CMake), use: + +```bash +make helpme +``` + +## 🚀 Execution + +To flash the main firmware onto the microcontroller, you can use one of the following commands (requires the corresponding tool to be installed): + +### Flashing via [STM32CubeProgrammer](https://www.st.com/en/development-tools/stm32cubeprog.html) + +> [!IMPORTANT] +> The `STM32_Programmer_CLI` executable needs to be in your system's `PATH` for this command to work. + +```bash +make flash +``` + +### Flashing via J-Link + +> [!IMPORTANT] +> `JLinkExe` needs to be in your `PATH`, or the `JLINK_CMD` environment variable needs to be set with the path to the executable. + +```bash +make jflash +``` + +If the project hasn't been compiled yet, these commands will automatically compile it before flashing. + +## 🧪 Tests + +Each test should be an independent file in the `test/` folder with its own `main()` function. + +To compile a specific test, use `make `. For example, to compile the test `test/test_gpio.c`: + +```bash +make test_gpio -j +``` + +To flash a specific test, use `make flash_` or `make jflash_`: + +```bash +make flash_test_gpio +``` + +or + +```bash +make jflash_test_gpio +``` + +To compile all tests defined in the project, use `make test_all`: + +```bash +make test_all -j +``` + +## 🐛 Debugging + +1. **Configure the build for Debug:** + Run CMake with the `BUILD_TYPE` variable set to `Debug` (includes debug symbols, no optimizations) or `RelWithDebInfo` (includes symbols, with optimizations). + + ```bash + # Inside the build/ folder + cmake .. -DBUILD_TYPE=Debug + ``` + + or + + ```bash + cmake .. -DBUILD_TYPE=RelWithDebInfo + ``` + +2. **Compile the project:** + + ```bash + make -j + ``` + +3. **Generate debug configurations (Optional, for VS Code):** + If you are using VS Code with the Cortex-Debug extension, generate the `launch.json` configuration files: + + ```bash + make debug # For the main executable + ``` + + To generate configurations for a specific test: + + ```bash + make debug_test_gpio + ``` + +4. **Start the Debug Session:** + Use the [Cortex-Debug](https://marketplace.visualstudio.com/items?marus25.Cortex-Debug) extension in VS Code with one of the configurations generated in the previous step, or manually start a GDB server and connect with `gdb-multiarch`. The default configurations use one of the following GDB servers (install the one you will use): + + * **[J-Link](https://www.segger.com/downloads/jlink/):** You might need to flash the firmware beforehand with `make jflash` or `make jflash_my_test`. + * **[OpenOCD](https://openocd.org/):** `sudo apt install openocd` (Ubuntu/Debian) + * **[ST-Util](https://github.com/stlink-org/stlink):** `sudo apt install stlink-tools` (Ubuntu/Debian) + +## 💄 Code Style + +To maintain code consistency and quality, we use formatting and linting tools. + +### 🎨 Formatting + +We use `clang-format` to standardize the formatting of C/C++ code. The style rules are defined in the `.clang-format` file in the project root. + +To format all source code (`src/`, `include/`, `test/`) according to the rules, run in the `build/` folder: + +```bash +make format +``` + +### 🚨 Linter + +We use `clang-tidy` for static analysis, helping to identify potential bugs, enforce good practices, and ensure adherence to coding standards. The linting rules are defined in the `.clang-tidy` file in the project root. + +The linter runs during compilation when the CMake variable `LINTER_MODE` is enabled. Configure CMake (inside the `build/` folder) with one of the following options: + +* **Enable Linter (analysis only):** + ```bash + cmake .. -DLINTER_MODE=ON + ``` +* **Enable Linter and apply automatic fixes:** + ```bash + cmake .. -DLINTER_MODE=FIX + ``` +* **Disable Linter (default):** + ```bash + cmake .. -DLINTER_MODE=OFF + ``` + +After configuring CMake, compile the project normally to run the linter (if enabled): + +```bash +make -j +``` + +## 📦 Submodules + +To add an external library as a Git submodule in the `lib/` folder: + +```bash +git submodule add --name lib/ +# Example: +# git submodule add --name lib_cmsis_dsp git@github.com:ARM-software/CMSIS-DSP.git lib/cmsis_dsp +``` + +To clone a project that uses submodules for the first time, or to update existing submodules: + +```bash +git submodule update --init --recursive +``` + +## 🐋 Docker + +It is possible to use Docker to create a containerized development and compilation environment, ensuring consistency across different machines and facilitating continuous integration (CI/CD). You need to have [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed. + +The base Docker configuration for this template can be found at https://github.com/ThundeRatz/stm32cubemx_docker. Adapt the files in `.docker/` as needed for your project. + +### Compile using container + +Run the compilation directly from outside the container: + +```bash +docker compose run build # Compiles the main project +docker compose run format # Formats the code +docker compose run lint # Runs the linter (requires LINTER_MODE=ON in build) +``` + +### Interactive development environment + +To enter a shell inside the container and execute commands manually: + +```bash +docker compose run dev +``` + +And once inside the container, you can use the normal commands: + +```bash +mkdir -p build +cd build +cmake .. +make -j +``` + +> [!TIP] +> If you use Visual Studio Code, the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension allows you to open the project directly *inside* the container defined in `docker-compose.yml`, providing an integrated development experience. + +## 📝 Documentation + +This template is configured to generate source code documentation using [Doxygen](https://www.doxygen.nl/). + +To generate the documentation (HTML and PDF, if LaTeX is installed) in the `docs/` folder, run the following command inside the `build/` folder: + +```bash +make docs +``` + +The Doxygen configuration is controlled by the `Doxyfile` file in the project root. Edit it to customize the documentation generation. + +## 🛠️ Windows Development Environment (WSL) + +If you are developing on a Windows machine using the [**Windows Subsystem for Linux (WSL)**](https://learn.microsoft.com/en-us/windows/wsl/), we recommend the following workflow for a better experience: + +1. **Install Build/Code Tools in WSL:** + * `cmake`, `make`, `gcc-arm-none-eabi`, `git`, `clang-format`, `clang-tidy`, `doxygen`, etc. (using your Linux distribution's package manager, like `apt`), as described in the [Dependencies section](#dependencies). +2. **Install Hardware/Interface Tools on Windows:** + * [STM32CubeMX](https://www.st.com/en/development-tools/stm32cubemx.html) + * [STM32CubeProgrammer](https://www.st.com/en/development-tools/stm32cubeprog.html) + * Drivers and Software for your Debugger (e.g., [J-Link Software and Documentation Pack](https://www.segger.com/downloads/jlink/), ST-LINK Drivers). +3. **Add Windows Tools to PATH:** + This makes it easier to call `STM32_Programmer_CLI.exe` or `JLinkGDBServerCL.exe` directly from the WSL terminal. Since WSL automatically imports the Windows PATH, edit your Windows PATH to include the installation directories of the tools. +4. **Recommended Workflow:** + * Use the WSL terminal to clone, compile (`cmake`, `make`), format (`make format`), etc. + * Run STM32CubeMX on Windows to configure hardware and generate code (CMake can detect it via PATH). + * Use the `make flash` or `make jflash` commands in WSL (they will call the Windows tools via PATH). + * For debugging, run the appropriate GDB Server (e.g., `JLinkGDBServerCL.exe`, `openocd.exe`, `st-util`) on **Windows** and connect to it from `gdb-multiarch` in WSL or via VS Code (see note below). + +> [!NOTE] +> **WSL Networking for Debugging:** When running a GDB Server on Windows (port `localhost:XXXX`), for GDB inside WSL to connect to it, you might need to configure [**Mirrored mode networking**](https://learn.microsoft.com/en-us/windows/wsl/networking#mirrored-mode-networking) in WSL (requires recent Windows 11 builds). This makes WSL share the same IP address as Windows, facilitating localhost communication. + +**Alternatives:** +* You can define the `JLINK_CMD` and `PROGRAMMER_CMD` environment variables in CMake or the WSL environment to explicitly point to the executables on Windows (`/mnt/c/...`), if you don't want to add them to the PATH. +* It is possible to install and use tools like OpenOCD or stlink-tools directly in WSL and try to pass the USB device to WSL using `usbipd-win`. Consult the [official WSL documentation on USB](https://learn.microsoft.com/en-us/windows/wsl/connect-usb) for more details, but this approach might be less stable than using the native Windows tools. + +## 👥 Contribution Guidelines + +To contribute to this project (or projects derived from this template), please follow these guidelines: + +### 💬 Git Commit Messages + +To maintain a clear, consistent, and globally understandable history, commit messages **must be written in English**. Follow these guidelines when writing your messages: + +1. **Use the Present Tense and Imperative Mood:** + * Describe what the commit *does*, as if giving an order. + * Example: Write `✨ Add user profile feature` instead of `Added user profile feature` or `Adds user profile feature`. + +2. **Start with a Descriptive Emoji:** + * An emoji at the beginning of the subject line helps quickly identify the type of change. + * Common examples (Emoji `code`: Example Message - *Context/Meaning*): + * `🐛 Fix issue with timer interrupt` - *Fixes a problem with the timer interrupt* + * `✨ Implement SPI communication module` - *Implements the SPI communication module* + * `📝 Update README with setup instructions` - *Updates the README with setup instructions* + * `🎨 Format code using clang-format` - *Formats code using clang-format* + * `⚡ Optimize ADC reading loop` - *Optimizes the ADC reading loop* + * `♻️ Refactor GPIO initialization logic` - *Refactors the GPIO initialization logic* + * `🔧 Adjust CMake toolchain file` - *Adjusts the CMake toolchain file* + * `🧪 Add unit tests for calculation function` - *Adds unit tests for the calculation function* + * `⬆️ Update HAL library to version 1.8.0` - *Updates HAL library to version 1.8.0* + * `⬇️ Downgrade external library due to bug` - *Downgrades an external library due to a bug* + * `🚑 Hotfix critical issue in motor control` - *Applies an urgent fix for a critical issue in motor control* + * For more emoji suggestions, see: [Gitmoji](https://gitmoji.dev/) + +3. **Keep the Subject Line Concise:** + * The first line (subject) should be a direct summary of the change, ideally 50-72 characters long. + * If more detail is needed, leave a blank line after the subject and write an explanatory body. + +Following these conventions makes the Git history easier to navigate and understand for all contributors. + +### 🔀 GitHub Flow + +1. **Follow [GitHub Flow](https://docs.github.com/en/get-started/quickstart/github-flow):** + * Create a branch from `develop` for each new feature or fix (`git checkout -b feature-name`). + * Make atomic and descriptive commits on your branch. + * Open a Pull Request (PR) when the work is ready for review. + * Discuss and review the code in the PR. Make changes as necessary. + * After approval and CI checks pass, merge the PR into `develop`. +2. **Maintain code and documentation cohesion:** Ensure that new code integrates well with the existing codebase and that documentation (comments, README, Doxygen) is updated as needed. +3. **Test your changes:** Before submitting a Pull Request, compile and test your modifications locally. If there are automated tests, ensure they pass. + +## 🙌 Acknowledgements + +This project would not have been possible without the support and collaboration of the entire **ThundeRatz** team. +The architectural and organizational decisions were heavily based on the best practices adopted in the team's projects, ensuring more modular, efficient, and scalable code. + +We would also like to acknowledge the **[Micras](https://github.com/Team-Micras/MicrasFirmware)** project, whose development served as a basis for several decisions adopted here. +The technical discussions and challenges faced in Micras helped shape the structure and best practices of this template. diff --git a/README.md b/README.md index 6e1fa8d..35c3afe 100644 --- a/README.md +++ b/README.md @@ -1,234 +1,475 @@ -# STM32 Project Template - -Template para projetos usando microcontroladores da ST e o STM32CubeMX. -Consiste numa estrutura especifica de pastas, um Makefile e -alguns arquivos de configuração. - -## Requisitos + +
+ +# Template para Projetos STM32 + +Template para projetos com microcontroladores STM32 usando STM32CubeMX e CMake + +
+ +
+ Made with C++ + Usa STM32CubeMX + Para Sistemas Embarcados + Licença MIT +
+ Read in English +
+ + + +## 📑 Sumário + +- [📑 Sumário](#-sumário) +- [📁 Estrutura de Pastas](#-estrutura-de-pastas) +- [🛠 Configuração](#-configuração) + - [Dependências](#dependências) + - [Projeto CubeMX](#1-projeto-cubemx) + - [CMakeLists.txt](#2-cmakeliststxt) +- [🔨 Compilação](#-compilação) +- [🚀 Execução](#-execução) +- [🧪 Testes](#-testes) +- [🐛 Debug](#-debug) +- [💄 Estilo de Código](#-estilo-de-código) + - [🎨 Formatação](#-formatação) + - [🚨 Linter](#-linter) +- [📦 Submódulos](#-submódulos) +- [🐋 Docker](#-docker) +- [📝 Documentação](#-documentação) +- [🛠️ Ambiente de Desenvolvimento Windows (WSL)](#️-ambiente-de-desenvolvimento-windows-wsl) +- [👥 Diretrizes de Contribuição](#-diretrizes-de-contribuição) + - [💬 Mensagens de Commit Git](#-mensagens-de-commit-git) + - [🔀 GitHub Flow](#-github-flow) +- [🙌 Agradecimentos](#-agradecimentos) + +## 📁 Estrutura de Pastas + +- **.docker/** - Configurações e scripts do Docker +- **.github/** - Configurações do GitHub Actions +- **.vscode/** - Configurações do Visual Studio Code +- **cmake/** - Funções customizadas para CMake +- **config/** - Configurações do projeto +- **cube/** - Projeto do STM32CubeMX (.ioc e arquivos gerados) +- **include/** - Cabeçalhos +- **lib/** - Submódulos e bibliotecas externas +- **src/** - Código fonte principal da aplicação +- **test/** - Testes + +Além disso, as seguintes pastas contém arquivos gerados e não são versionadas: + +- **build/** - Arquivos gerados durante a compilação +- **docs/** - Documentação gerada + +## 🛠 Configuração + +### Dependências + +Para aproveitar ao máximo este template, desde a compilação básica até debug e gravação, algumas ferramentas são essenciais e outras opcionais, dependendo do seu fluxo de trabalho. Abaixo descrevemos as principais, com comandos de exemplo para instalação em sistemas Debian/Ubuntu (como Ubuntu, Mint). Se você usa outra distribuição Linux (Fedora, Arch) ou macOS, adapte os comandos para seu gerenciador de pacotes (`dnf`, `pacman`, `brew`, etc.). + +#### Essenciais para Começar + +Você precisará destas ferramentas para simplesmente clonar e compilar o projeto: + +* **`git`**: O sistema de controle de versão fundamental para baixar este template, gerenciar suas alterações e lidar com quaisquer bibliotecas externas incluídas como submódulos. + ```bash + sudo apt install git + ``` +* **`cmake`**: O coração do sistema de build. Ele interpreta as instruções do arquivo `CMakeLists.txt` e gera os arquivos necessários (Makefiles) para que a compilação ocorra no seu ambiente específico. + ```bash + sudo apt install cmake + ``` +* **`make`**: Esta ferramenta lê os Makefiles gerados pelo CMake e executa os comandos de compilação na ordem correta. É o que você geralmente invoca para compilar (`make -j`). + ```bash + sudo apt install make + ``` +* **`gcc-arm-none-eabi` Toolchain**: Este é o conjunto de ferramentas de compilação cruzada (compilador C/C++, linker, etc.) que transforma seu código fonte em código binário executável para os microcontroladores STM32 (baseados em ARM Cortex-M). + ```bash + sudo apt install gcc-arm-none-eabi + ``` +* **`STM32CubeMX`**: Para configurar visualmente os periféricos do seu STM32, sistema de clock e gerar o código de inicialização base (incluindo o arquivo `.ioc`), você precisará desta ferramenta gráfica da ST. Baixe o instalador diretamente do [site da STMicroelectronics](https://www.st.com/en/development-tools/stm32cubemx.html). Para que o CMake possa interagir com ele (útil para gerar código), certifique-se de que o executável esteja no `PATH` do seu sistema ou que a variável de ambiente `CUBE_CMD` aponte para ele. *(Instalação manual via download)*. + +> [!WARNING] +> No momento esse template não suporta versões acima da 6.13 do CubeMX + +* **`STM32CubeProgrammer`**: Essencial para gravar o firmware compilado no seu microcontrolador usando um programador ST-LINK. É necessário para usar o comando `make flash`. Baixe o instalador no [site da STMicroelectronics](https://www.st.com/en/development-tools/stm32cubeprog.html) e garanta que o executável de linha de comando (`STM32_Programmer_CLI`) esteja no seu `PATH`. *(Instalação manual via download)*. + +#### Ferramentas Adicionais para Funcionalidades Extras + +Estas ferramentas habilitam funcionalidades como configuração gráfica, gravação, debug avançado, padronização de código e documentação. Instale as que forem relevantes para você: + +* **`Software J-Link da Segger`**: Se você utiliza um programador/debugger J-Link, precisará do pacote de software da Segger. Ele fornece os drivers e o servidor GDB (`JLinkGDBServer`) necessários para debug e para o comando `make jflash`. Obtenha o "J-Link Software and Documentation Pack" no [site da Segger](https://www.segger.com/downloads/jlink/). O servidor GDB precisa estar acessível (via `PATH` ou variável `JLINK_CMD`). *(Instalação manual via download)*. +* **`openocd`**: Uma alternativa open-source popular como servidor de debug (GDB Server). O Open On-Chip Debugger suporta diversos adaptadores, incluindo ST-LINK, e é uma das opções configuradas para debug neste template. + ```bash + sudo apt install openocd + ``` +* **`stlink-tools`**: Um conjunto de ferramentas de linha de comando específicas para adaptadores ST-LINK. Inclui `st-flash` para gravação e `st-util` que pode atuar como um servidor GDB simples, sendo outra opção para debug. + ```bash + sudo apt install stlink-tools + ``` +* **`gdb-multiarch`**: O cliente depurador GNU Debugger, capaz de entender múltiplas arquiteturas como ARM. É ele que você usa para se conectar aos servidores GDB (JLinkGDBServer, OpenOCD, st-util) e controlar a execução do programa passo a passo, inspecionar variáveis, etc. Frequentemente instalado junto com a toolchain `gcc-arm-none-eabi`, mas caso contrário, instale com: + ```bash + sudo apt install gdb-multiarch + ``` +* **`clang-format`**: Para manter o código formatado de maneira consistente e automática, usamos o `clang-format`. Ele aplica as regras definidas no arquivo `.clang-format` ao seu código quando você executa `make format`. + ```bash + sudo apt install clang-format + ``` +* **`clang-tidy`**: Uma ferramenta de análise estática (linter) que ajuda a identificar potenciais problemas, bugs e desvios de boas práticas no código C/C++. Ele usa as regras do arquivo `.clang-tidy` e é executado durante a compilação se você configurar o CMake com `-DLINTER_MODE=ON` ou `-DLINTER_MODE=FIX`. + ```bash + sudo apt install clang-tidy + ``` +* **`doxygen` & Cia**: Para gerar documentação automaticamente a partir dos comentários no código, usamos o `doxygen`. Para gerar diagramas (como grafos de chamadas), ele pode usar o `graphviz`. E se você quiser a documentação também em PDF, ele utiliza `LaTeX` (provido pelo `texlive`). Execute `make docs` para gerar a documentação. Instale o necessário com: + ```bash + sudo apt install doxygen graphviz texlive-latex-extra texlive-fonts-extra + ``` + *(Note que a instalação do `texlive` pode ocupar um espaço considerável).* + +> [!TIP] +> Lembre-se de consultar as seções específicas deste README (Compilação, Execução, Debug, Estilo de Código, Documentação) para entender melhor como e quando cada uma dessas ferramentas opcionais entra em ação no fluxo de trabalho proporcionado pelo template. + +### 1. Projeto CubeMX + +O início de um projeto STM32 é feito no STM32CubeMX. Para isso, é necessário instalar o [STM32CubeMX](https://www.st.com/en/development-tools/stm32cubemx.html) e configurar o projeto: + +> [!IMPORTANT] +> Para que o CMake encontre e utilize o STM32CubeMX automaticamente (por exemplo, ao gerar código), certifique-se de que o executável do CubeMX esteja no `PATH` do seu sistema ou defina a variável de ambiente `CUBE_CMD` com o caminho completo para o executável. + +1. Crie um novo projeto na pasta `cube/` +2. Configurações: + - **Project Manager > Project > Application Structure:** Basic + - **Project Manager > Project > Toolchain/IDE:** CMake + - **Project Manager > Code Generator > Generate peripheral initialization:** Pair of .c/.h files per peripheral + - **Project Manager > Code Generator > Delete previous generated files when not regenerated:** Ativado + +### 2. CMakeLists.txt + +Edite o arquivo principal `CMakeLists.txt` com as informações do seu projeto: + +```cmake +# Nome do projeto (igual ao arquivo .ioc sem extensão) +set(CMAKE_PROJECT_NAME meu_projeto) + +# Versão da placa (opcional) +set(BOARD_VERSION "") +``` -* [STM32CubeMX](https://www.st.com/en/development-tools/stm32cubemx.html) - > É necessário colocar o local de instalação na varíavel de ambiente `CUBE_PATH` +## 🔨 Compilação -* make - > Linux: `sudo apt install make` - > - > Windows: `msys2> pacman -S make` +Antes de compilar pela primeira vez, certifique-se de que os submódulos Git (se houver) foram inicializados: -* CMake - > Linux: `sudo apt install cmake` - > - > Windows: Baixe o zip ou o instalador no [Installing CMake](https://cmake.org/download/) - > - > É necessário que a pasta `bin` dessa instalação esteja no `PATH`. - > No instalador do Windows, isso é feito automaticamente +```bash +git submodule update --init --recursive +``` -* [GNU Arm Embedded Toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) - > É necessário que a pasta `bin` dessa instalação esteja no `PATH` +Agora, crie uma pasta `build/` na raiz do projeto (se ainda não existir) e entre nela: -* uncrustify - > Linux: `sudo apt install uncrustify` - > - > Windows: Baixe o .zip no [SourceForge](https://sourceforge.net/projects/uncrustify/files/). Adicione o local do executável na variável de ambiente `PATH`. +```bash +mkdir -p build +cd build +``` -* [Visual Studio Code](https://code.visualstudio.com/) - * [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - * [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) - * [Cortex-Debug](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug) +Dentro dela, configure o ambiente com CMake: -* [STM32 Cube Programmer](https://www.st.com/en/development-tools/stm32cubeprog.html) ou [J-Link](https://www.segger.com/downloads/jlink/) - > É necessário que o executável também esteja no `PATH` +```bash +cmake .. +``` -## Preparando +Depois, compile o projeto: -### Projeto +```bash +make -j +``` -Primeiro é necessário criar um projeto do Cube na pasta `cube/` com o nome desejado, -que deve ter as seguintes opções de projeto: +> O parâmetro `-j` ativa a compilação paralela, usando mais núcleos do seu processador para acelerar o processo. -Project: +### Limpar arquivos -* Application Structure: *Basic* -* [x] Do not generate the main() -* Toolchain / IDE: *Makefile* +```bash +make clear # Código do usuário +make clear_cube # Bibliotecas Cube +make clear_all # Tudo +``` -Code Generator: +### Manual -* STM32Cube Firmware Library Package: *Copy all used libraries into the project folder* -* Generated files: - * *Generate peripheral initialization as a pair of .c/.h files per peripheral* - * *Delete previously generated files when not re-generated* +Para obter uma lista completa de comandos `make` disponíveis (definidos no CMake), use: -Um arquivo de exemplo se encontra em `cube/stm32_project_template.ioc` com todas as configurações necessárias. +```bash +make helpme +``` -Para projetos existentes, basta mover o arquivo `.ioc` para a pasta `cube/`. +## 🚀 Execução -### Compilação +Para gravar o firmware principal no microcontrolador, você pode usar um dos seguintes comandos (requer a ferramenta correspondente instalada): -O arquivo `CMakeLists.txt` deve ser editado de acordo com o projeto. +### Gravando via [STM32CubeProgrammer](https://www.st.com/en/development-tools/stm32cubeprog.html) -Para isso é necessário mudar o nome do projeto, o qual deve ter o mesmo do arquivo do Cube (por exemplo, `stm32_project_template.ioc`), porém sem a extensão `.ioc`. +> [!IMPORTANT] +> O executável `STM32_Programmer_CLI` precisa estar no `PATH` do seu sistema para este comando funcionar. -```c -# Cube file name without .ioc extension -project(stm32_project_template C ASM) +```bash +make flash ``` -> Os argumentos `C` e `ASM` estão relacionados ao tipo de linguagem que o projeto utiliza (C e Assembly). +### Gravando via J-Link -Também é necessário alterar as seguintes configurações: +> [!IMPORTANT] +> O `JLinkExe` precisa estar no `PATH` ou a variável de ambiente `JLINK_CMD` precisa ser definida com o caminho para o executável. -```c -# Device Configuration -set(DEVICE_CORTEX F3) -set(DEVICE_FAMILY STM32F3xx) -set(DEVICE_TYPE STM32F303xx) -set(DEVICE_DEF STM32F303xE) -set(DEVICE STM32F303RE) +```bash +make jflash ``` -Basta pegar o nome completo do microcontrolador e colocar nessas configurações, seguindo o padrão, fazendo as substituições que forem precisas por x. +Se o projeto ainda não foi compilado, esses comandos irão compilá-lo automaticamente antes de gravar. -> Em caso de dúvida, veja o nome do arquivo .ld gerado na pasta cube, ele contém o nome completo do microcontrolador. +## 🧪 Testes -## Gerando arquivos +Cada teste deve ser um arquivo independente na pasta `test/` com sua própria função `main()`. -Com as configurações realizadas corretamente, você deve se direcionar para a pasta `build`. Estando lá, basta rodar o seguinte comando: +Para compilar um teste específico, use `make `. Por exemplo, para compilar o teste `test/test_gpio.c`: ```bash -cmake .. +make test_gpio -j ``` -Esse comando é de extrema importância, pois nenhum dos outros comandos de compilação funcionarão sem ele ter sido rodado antes. - -> Todos os comandos que envolvam `make` devem ser rodados dentro da pasta `build`, após o comando `cmake ..` ter sido feito. - -Basicamente, ele configura o ambiente do CMake e gera os arquivos do cube, caso a pasta `cube` esteja vazia. Todavia, caso você queira apenas gerar os arquivos do cube, também é possível rodar o comando +Para gravar um teste específico, use `make flash_` ou `make jflash_`: ```bash -make cube +make flash_test_gpio ``` -## Compilando - -Para compilar os arquivos, após ter rodado `cmake ..`, ainda dentro da pasta `build`, rode: +ou ```bash -make +make jflash_test_gpio ``` -O comando `make` apenas compilará o código principal, não compilando nenhum teste. Para compilar um teste, cujo arquivo se chama **nome_do_teste.c**, rode: +Para compilar todos os testes definidos no projeto, use `make test_all`: ```bash -make nome_do_teste +make test_all -j ``` -## Limpando Arquivos compilados +## 🐛 Debug -Se acontecer algum erro, pode ser necessário limpar os arquivos já compilados. Para isso, dentro da pasta `build`, faça: +1. **Configure o build para Debug:** + Execute o CMake com a variável `BUILD_TYPE` definida como `Debug` (inclui símbolos de debug, sem otimizações) ou `RelWithDebInfo` (inclui símbolos, com otimizações). -```bash -make clean -``` + ```bash + # Dentro da pasta build/ + cmake .. -DBUILD_TYPE=Debug + ``` + + ou + + ```bash + cmake .. -DBUILD_TYPE=RelWithDebInfo + ``` + +2. **Compile o projeto:** + + ```bash + make -j + ``` + +3. **Gere configurações de debug (Opcional, para VS Code):** + Se estiver usando o VS Code com a extensão Cortex-Debug, gere os arquivos de configuração `launch.json`: + + ```bash + make debug # Para o executável principal + ``` -Isso apaga todos os arquivos de compilação gerados, exceto aqueles que vêm das bibliotecas da ST geradas pelo Cube. Isso é feito para agilizar um novo build, já que raramente será necessário recompilar esses arquivos. Todavia, caso seja necessário, é possível limpá-los com o comando: + Para gerar configurações para um teste específico: + + ```bash + make debug_test_gpio + ``` + +4. **Inicie a Sessão de Debug:** + Use a extensão [Cortex-Debug](https://marketplace.visualstudio.com/items?marus25.Cortex-Debug) no VS Code com uma das configurações geradas no passo anterior, ou inicie manualmente um servidor GDB e conecte-se com `gdb-multiarch`. As configurações padrão usam um dos seguintes servidores GDB (instale o que for usar): + + * **[J-Link](https://www.segger.com/downloads/jlink/):** Pode ser necessário gravar o firmware antes com `make jflash` ou `make jflash_meu_teste`. + * **[OpenOCD](https://openocd.org/):** `sudo apt install openocd` (Ubuntu/Debian) + * **[ST-Util](https://github.com/stlink-org/stlink):** `sudo apt install stlink-tools` (Ubuntu/Debian) + +## 💄 Estilo de Código + +Para manter a consistência e a qualidade do código, usamos ferramentas de formatação e linting. + +### 🎨 Formatação + +Usamos o `clang-format` para padronizar a formatação do código C/C++. As regras de estilo estão definidas no arquivo `.clang-format` na raiz do projeto. + +Para formatar todo o código fonte (`src/`, `include/`, `test/`) de acordo com as regras, execute na pasta `build/`: ```bash -make clean_cube +make format ``` -Além disso, caso seja necessário limpar todos os arquivos de compilação, você pode rodar o comando: +### 🚨 Linter + +Usamos o `clang-tidy` para análise estática, ajudando a identificar possíveis bugs, aplicar boas práticas e garantir a aderência a padrões de codificação. As regras de linting estão definidas no arquivo `.clang-tidy` na raiz do projeto. + +O linter é executado durante a compilação quando a variável CMake `LINTER_MODE` está habilitada. Configure o CMake (dentro da pasta `build/`) com uma das seguintes opções: + +* **Habilitar Linter (apenas análise):** + ```bash + cmake .. -DLINTER_MODE=ON + ``` +* **Habilitar Linter e aplicar correções automáticas:** + ```bash + cmake .. -DLINTER_MODE=FIX + ``` +* **Desabilitar Linter (padrão):** + ```bash + cmake .. -DLINTER_MODE=OFF + ``` + +Após configurar o CMake, compile o projeto normalmente para rodar o linter (se habilitado): ```bash -make clean_all +make -j ``` -## Recompilando +## 📦 Submódulos -Caso você queira apagar os arquivos compilados e recompilá-los, é possível fazer isso com um comando só, rodando, dentro da pasta `build`, o comando: +Para adicionar uma biblioteca externa como um submódulo Git na pasta `lib/`: ```bash -make rebuild +git submodule add --name lib/ +# Exemplo: +# git submodule add --name lib_cmsis_dsp git@github.com:ARM-software/CMSIS-DSP.git lib/cmsis_dsp ``` -E, caso você queira apagar e recompilar todos os arquivos compilados, incluindo os do cube, rode o comando: +Para clonar um projeto que usa submódulos pela primeira vez, ou para atualizar os submódulos existentes: ```bash -make rebuild_all +git submodule update --init --recursive ``` -## Gravando +## 🐋 Docker -Para gravar os arquivos na placa, rode +É possível usar o Docker para criar um ambiente de desenvolvimento e compilação conteinerizado, garantindo consistência entre diferentes máquinas e facilitando a integração contínua (CI/CD). É necessário ter o [Docker](https://docs.docker.com/get-docker/) e o [Docker Compose](https://docs.docker.com/compose/install/) instalados. -```bash -make flash -``` +A configuração base do Docker para este template pode ser encontrada em https://github.com/ThundeRatz/stm32cubemx_docker. Adapte os arquivos em `.docker/` conforme necessário para o seu projeto. -Ou, caso use um gravador com J-Link: +### Compilar usando container + +Execute a compilação diretamente de fora do container: ```bash -make jflash +docker compose run build # Compila o projeto principal +docker compose run format # Formata o código +docker compose run lint # Roda o linter (requer LINTER_MODE=ON no build) ``` -Além disso, para gravar um teste, cujo nome do arquivo é **nome_do_teste.c**, deve-se rodar: +### Ambiente de desenvolvimento interativo + +Para entrar em um shell dentro do container e executar comandos manualmente: ```bash -make flash_nome_do_teste +docker compose run dev ``` -Ou, caso use um gravador com J-Link: +E estando dentro do container você pode usar os comandos normais ```bash -make jflash_nome_do_teste +mkdir -p build +cd build +cmake .. +make -j ``` -## Formatando +> [!TIP] +> Se você usa o Visual Studio Code, a extensão [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) permite que você abra o projeto diretamente *dentro* do container definido no `docker-compose.yml`, proporcionando uma experiência de desenvolvimento integrada. -Para garantir que o código está formatado, utilize o atalho `CTRL`+`S` para salvar e formatar o arquivo em que se está mexendo ou, para formatar todos os arquivos do repositório de uma vez, rode: +## 📝 Documentação + +Este template está configurado para gerar documentação do código fonte usando [Doxygen](https://www.doxygen.nl/). + +Para gerar a documentação (HTML e PDF, se LaTeX estiver instalado) na pasta `docs/`, execute o seguinte comando dentro da pasta `build/`: ```bash -make format +make docs ``` -## Submódulos +A configuração do Doxygen é controlada pelo arquivo `Doxyfile` na raiz do projeto. Edite-o para personalizar a geração da documentação. -### Adicionando um submódulo +## 🛠️ Ambiente de Desenvolvimento Windows (WSL) -Crie um diretório chamado `lib` e adicione o submódulo nele. +Se você está desenvolvendo em uma máquina Windows usando o [**Subsistema Windows para Linux (WSL)**](https://learn.microsoft.com/en-us/windows/wsl/), recomendamos o seguinte fluxo de trabalho para uma melhor experiência: -Exemplo: +1. **Instale as ferramentas de Build/Código no WSL:** + * `cmake`, `make`, `gcc-arm-none-eabi`, `git`, `clang-format`, `clang-tidy`, `doxygen`, etc. (usando o gerenciador de pacotes da sua distribuição Linux, como `apt`), conforme descrito na [seção de Dependências](#dependências) +2. **Instale as ferramentas de Hardware/Interface no Windows:** + * [STM32CubeMX](https://www.st.com/en/development-tools/stm32cubemx.html) + * [STM32CubeProgrammer](https://www.st.com/en/development-tools/stm32cubeprog.html) + * Drivers e Software do seu Debugger (e.g., [J-Link Software and Documentation Pack](https://www.segger.com/downloads/jlink/), Drivers ST-LINK) +3. **Adicione as Ferramentas Windows ao PATH:** + Facilita chamar `STM32_Programmer_CLI.exe` ou `JLinkGDBServerCL.exe` diretamente do terminal WSL. Como o WSL importa o PATH do Windows automaticamente, edite seu PATH para incluir os diretórios de instação das ferramentas. +4. **Fluxo de Trabalho Recomendado:** + * Use o terminal WSL para clonar, compilar (`cmake`, `make`), formatar (`make format`), etc. + * Execute o STM32CubeMX no Windows para configurar o hardware e gerar o código (o CMake pode detectá-lo via PATH). + * Use os comandos `make flash` ou `make jflash` no WSL (eles chamarão as ferramentas Windows via PATH). + * Para debug, execute o GDB Server apropriado (e.g., `JLinkGDBServerCL.exe`, `openocd.exe`, `st-util`) no **Windows** e conecte-se a ele a partir do `gdb-multiarch` no WSL ou via VS Code (veja nota abaixo). -```bash -mkdir lib -git submodule add --name STMSensors git@github.com:ThundeRatz/STMSensors.git lib/STMSensors -``` +> [!NOTE] +> **Rede WSL para Debug:** Ao rodar um GDB Server no Windows (porta `localhost:XXXX`), para que o GDB dentro do WSL consiga se conectar a ele, você pode precisar configurar o [**modo de rede espelhado (Mirrored mode networking)**](https://learn.microsoft.com/en-us/windows/wsl/networking#mirrored-mode-networking) no WSL (requer builds recentes do Windows 11). Isso faz com que o WSL compartilhe o mesmo endereço IP do Windows, facilitando a comunicação localhost. -### Inicializando um submódulo já existente +**Alternativas:** +* Você pode definir as variáveis de ambiente `JLINK_CMD` e `PROGRAMMER_CMD` no CMake ou no ambiente WSL para apontar explicitamente para os executáveis no Windows (`/mnt/c/...`), caso não queira adicioná-los ao PATH. +* É possível instalar e usar ferramentas como OpenOCD ou stlink-tools diretamente no WSL e tentar passar o dispositivo USB para o WSL usando `usbipd-win`. Consulte a [documentação oficial do WSL sobre USB](https://learn.microsoft.com/en-us/windows/wsl/connect-usb) para mais detalhes, mas essa abordagem pode ser menos estável que usar as ferramentas nativas do Windows. -Ao clonar um repositório que já tem submódulos, é necessário clonar os repositórios desse submódulo. Isso pode ser feito de duas formas, clonando junto com o repositório do projeto ou depois de já ter clonado. +## 👥 Diretrizes de Contribuição -Exemplo: +Para contribuir com este projeto (ou projetos derivados deste template), siga estas diretrizes: -Para se clonar junto, deve-se fazer: +### 💬 Mensagens de Commit Git -```bash -git clone --recurse-submodules git@github.com:ThundeRatz/STM32ProjectTemplate.git -``` +Para manter um histórico claro, consistente e compreensível globalmente, as mensagens de commit **devem obrigatoriamente ser escritas em Inglês**. Siga estas diretrizes ao escrever suas mensagens: -Para se clonar depois de já ter clonado o repositório do projeto: +1. **Use o Tempo Presente e Modo Imperativo (em Inglês):** + * Descreva o que o commit faz, como se estivesse dando uma ordem. + * Exemplo: Escreva `✨ Add user profile feature` (Adiciona funcionalidade de perfil de usuário) em vez de `Added user profile feature` (Adicionada funcionalidade...) ou `Adds user profile feature` (Adiciona funcionalidade...). -```bash -git submodule update --init -``` +2. **Comece com um Emoji Descritivo:** + * Um emoji no início da linha de assunto ajuda a identificar rapidamente o tipo de alteração. + * Exemplos comuns (Emoji `código`: Exemplo em Inglês - *Tradução/Contexto*): + * `🐛 Fix issue with timer interrupt` - *Corrige problema com interrupção do timer* + * `✨ Implement SPI communication module` - *Implementa módulo de comunicação SPI* + * `📝 Update README with setup instructions` - *Atualiza README com instruções de configuração* + * `🎨 Format code using clang-format` - *Formata código usando clang-format* + * `⚡ Optimize ADC reading loop` - *Otimiza loop de leitura do ADC* + * `♻️ Refactor GPIO initialization logic` - *Refatora lógica de inicialização do GPIO* + * `🔧 Adjust CMake toolchain file` - *Ajusta arquivo da toolchain CMake* + * `🧪 Add unit tests for calculation function` - *Adiciona testes unitários para função de cálculo* + * `⬆️ Update HAL library to version 1.8.0` - *Atualiza biblioteca HAL para versão 1.8.0* + * `⬇️ Downgrade external library due to bug` - *Reverte versão de biblioteca externa devido a bug* + * `🚑 Hotfix critical issue in motor control` - *Corrige problema crítico urgente no controle do motor* + * Para mais sugestões de emojis, veja: [Gitmoji](https://gitmoji.dev/) + +3. **Mantenha a Linha de Assunto Concisa:** + * A primeira linha (assunto) deve ser um resumo direto da mudança, idealmente com 50-72 caracteres. + * Se precisar de mais detalhes, deixe uma linha em branco após o assunto e escreva um corpo explicativo. + +Seguir estas convenções torna o histórico do Git mais fácil de navegar e entender para todos os contribuidores. -## Diretório de testes +### 🔀 GitHub Flow -O diretório `test` contém arquivos para testes de partes específicas do projeto, separando isso do código do projeto em si. Esses arquivos devem ser implementados de acordo com as necessidades dos desenvolvedores. +1. **Siga o [GitHub Flow](https://docs.github.com/pt/get-started/quickstart/github-flow):** + * Crie um branch a partir da `develop` para cada nova funcionalidade ou correção (`git checkout -b nome-da-feature`). + * Faça commits atômicos e descritivos no seu branch. + * Abra um Pull Request (PR) quando o trabalho estiver pronto para revisão. + * Discuta e revise o código no PR. Faça alterações conforme necessário. + * Após aprovação e passagem dos checks de CI, faça o merge do PR na `develop`. +2. **Mantenha a coesão do código e documentação:** Certifique-se de que o código novo se integra bem com o existente e que a documentação (comentários, README, Doxygen) é atualizada conforme necessário. +3. **Teste suas alterações:** Antes de submeter um Pull Request, compile e teste suas modificações localmente. Se houver testes automatizados, certifique-se de que eles passam. -Para compilar e gravar um teste, siga as instruções [na seção de compilação](#compilando) e [na seção para gravação](#gravando). +## 🙌 Agradecimentos -Cada arquivo de teste no diretório de testes funciona de forma independente, ou seja, cada um deve ter uma função `main()`, sendo cada um compilado, gravado e executado separadamente. +Este projeto não teria sido possível sem o suporte e colaboração da equipe **ThundeRatz** como um todo. +As decisões de arquitetura e organização foram fortemente baseadas nas boas práticas adotadas nos projetos da equipe, garantindo um código mais modular, eficiente e escalável. -## Debug +Também gostaríamos de reconhecer o projeto **[Micras](https://github.com/Team-Micras/MicrasFirmware)**, cujo desenvolvimento serviu de base para diversas decisões adotadas aqui. +As discussões técnicas e desafios enfrentados no Micras ajudaram a moldar a estrutura e as boas práticas deste template. -> Em breve diff --git a/cmake/config_validation.cmake b/cmake/config_validation.cmake index 390dc5b..cc2f002 100644 --- a/cmake/config_validation.cmake +++ b/cmake/config_validation.cmake @@ -1,71 +1,138 @@ -# Name: config_validation.cmake file -# ThundeRatz Robotics Team -# Brief: This file contains the existence checks of the declared variables -# 04/2023 - ############################################################################### -## Auxiliary Sets +## Existence checks ############################################################################### -# This variable is used by the stm32-cmake lib to find the STM32CubeMX files -# @see: https://github.com/ObKo/stm32-cmake#configuration -set(STM32_CUBE_${DEVICE_CORTEX}_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cube) - -# This set contains all the variables that must be defined by the user -# It is used to check if all of them are properly defined -set(USER_INPUT_VARIABLES - DEVICE_CORTEX - DEVICE_FAMILY - DEVICE_TYPE - DEVICE_DEF - DEVICE_FAMILY_COMPACT - DEVICE - BOARD_VERSION - TARGET_BOARD -) +# Check if CMake build type is correctly configured +if(NOT (BUILD_TYPE STREQUAL "Release" OR BUILD_TYPE STREQUAL "Debug" OR + BUILD_TYPE STREQUAL "RelWithDebInfo" OR BUILD_TYPE STREQUAL "MinSizeRel")) + set(BUILD_TYPE "RelWithDebInfo") +endif() -############################################################################### -## Existence checks -############################################################################### +set(CMAKE_BUILD_TYPE ${BUILD_TYPE}) +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") -## Check if STM32CubeMX variables are properly defined -if(DEFINED ENV{CUBE_PATH}) - message(STATUS "CUBE_PATH defined as $ENV{CUBE_PATH}") -else() - message(FATAL_ERROR "CUBE_PATH not defined") +# Check if host system is Linux +if(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "${CMAKE_HOST_SYSTEM_NAME} is not supported") endif() -if(CMAKE_HOST_WIN32) - set(JAVA_EXE "$ENV{CUBE_PATH}\\STM32CubeMX.exe") - set(CUBE_JAR "$ENV{CUBE_PATH}\\jre\\bin\\java.exe") - set(JLINK_EXE JLink.exe) +# Detect if running inside WSL +if(DEFINED ENV{WSL_DISTRO_NAME}) + message(STATUS "WSL detected") + set(CUBE_DEFAULT_PATH "/mnt/c/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX") + set(CUBE_PROGRAM "STM32CubeMX.exe") + set(PROGRAMMER_CMD "STM32_Programmer_CLI.exe") + set(JLINK_CMD "JLink.exe") + set(OPENOCD_CMD "openocd.exe") else() - set(JAVA_EXE $ENV{CUBE_PATH}/jre/bin/java) - set(CUBE_JAR $ENV{CUBE_PATH}/STM32CubeMX) - set(JLINK_EXE JLinkExe) + message(STATUS "Linux detected") + set(CUBE_DEFAULT_PATH "/usr/local/STMicroelectronics/STM32Cube/STM32CubeMX") + set(CUBE_PROGRAM "STM32CubeMX") + set(PROGRAMMER_CMD "STM32_Programmer_CLI") + set(JLINK_CMD "JLinkExe") + set(OPENOCD_CMD "openocd") endif() -# Check if necessary variables are defined: -foreach(VARIABLE ${USER_INPUT_VARIABLES}) - if(NOT DEFINED ${VARIABLE}) - message(FATAL_ERROR "${VARIABLE} not defined") +# Set STM32CubeMX command +if(DEFINED ENV{CUBE_CMD}) + set(CUBE_CMD $ENV{CUBE_CMD}) + message(STATUS "Using STM32CubeMX from environment: ${CUBE_CMD}") +else() + message(STATUS "CUBE_CMD not defined, trying to run from PATH") + find_program(CUBE_CMD ${CUBE_PROGRAM}) + + if(CUBE_CMD) + message(STATUS "STM32CubeMX found at: ${CUBE_CMD}") + else() + message(STATUS "${CUBE_PROGRAM} not found on PATH, trying default path") + set(CUBE_CMD "${CUBE_DEFAULT_PATH}/${CUBE_PROGRAM}") + + if(NOT EXISTS ${CUBE_CMD}) + message(FATAL_ERROR + "STM32CubeMX program not found at expected path: ${CUBE_CMD}\n" + "Define the CUBE_CMD environment variable or add the binary folder to the PATH" + ) + endif() endif() -endforeach() -message(STATUS "All necessary variables defined!") +endif() + +if(CUBE_CMD MATCHES "\.exe$" ) + set(CUBE_SOURCE_DIR "\\\\wsl.localhost/$ENV{WSL_DISTRO_NAME}${CMAKE_CURRENT_SOURCE_DIR}/cube") +else() + set(CUBE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cube") +endif() + +# Set STM32 Programmer command +if(DEFINED ENV{PROGRAMMER_CMD}) + set(PROGRAMMER_CMD $ENV{PROGRAMMER_CMD}) +endif() + +# Set J-Link command +if(DEFINED ENV{JLINK_CMD}) + set(JLINK_CMD $ENV{JLINK_CMD}) +endif() + +# Set OpenOCD command +if(DEFINED ENV{OPENOCD_CMD}) + set(OPENOCD_CMD $ENV{OPENOCD_CMD}) +endif() + +# Check if OpenOCD variables are properly defined +if (DEFINED ENV{OPENOCD_SCRIPTS_PATH}) + set(OPENOCD_SCRIPTS_PATH $ENV{OPENOCD_SCRIPTS_PATH}) + message(STATUS "OPENOCD_SCRIPTS_PATH defined as $ENV{OPENOCD_SCRIPTS_PATH}") +else() + set(OPENOCD_SCRIPTS_PATH "/usr/share/openocd/scripts") + message(STATUS "OPENOCD_SCRIPTS_PATH not defined. Using default path ${OPENOCD_SCRIPTS_PATH}") +endif() + +# Check if STM32CubeMX project is correctly configured +set(CUBE_CMAKE_TOOLCHAIN_CONFIG "ProjectManager.TargetToolchain=CMake") +set(IOC_FILE "cube/${PROJECT_RELEASE}.ioc") +file(READ ${IOC_FILE} IOC_CONTENTS) +string(FIND ${IOC_CONTENTS} ${CUBE_CMAKE_TOOLCHAIN_CONFIG} CUBE_CMAKE_TOOLCHAIN_CONFIG_POS) + +if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${IOC_FILE}") + message(FATAL_ERROR "CubeMX ${IOC_FILE} project file not found") +elseif(CUBE_CMAKE_TOOLCHAIN_CONFIG_POS EQUAL -1) + message(FATAL_ERROR "CMake toolchain not selected in CubeMX project") +else() + message(STATUS "CMake toolchain selected in CubeMX project") +endif() + +# Set DEVICE variable based on cube configuration +string(REGEX MATCH "ProjectManager\.DeviceId=[^\n]+" DEVICE_LINE ${IOC_CONTENTS}) +string(SUBSTRING ${DEVICE_LINE} 24 11 DEVICE) +string(TOLOWER ${DEVICE} LOWERCASE_DEVICE) +string(SUBSTRING ${LOWERCASE_DEVICE} 0 7 TARGET_CFG) +message(STATUS "Device is ${DEVICE}") # Check cube directory for files # If it's empty, generate the files -# It's important to do it before find_package(CMSIS) -file(GLOB_RECURSE CUBE_SOURCES_CHECK "${CMAKE_CURRENT_SOURCE_DIR}/cube/Src/*.c") -list(LENGTH CUBE_SOURCES_CHECK CUBE_LENGHT) -if(CUBE_LENGHT EQUAL 0) - message(STATUS "Cube directory is empty. Generating cube files...") +file(GLOB_RECURSE CUBE_SOURCES_CHECK "${CMAKE_CURRENT_SOURCE_DIR}/cube/**/*.c") +list(LENGTH CUBE_SOURCES_CHECK CUBE_LENGTH) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/.cube - "config load ${CMAKE_CURRENT_SOURCE_DIR}/cube/${PROJECT_RELEASE}.ioc\n" +if(CUBE_LENGTH EQUAL 0) + message(STATUS "Cube directory is empty. Generating cube files...") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cube_script.txt" + "config load ${CUBE_SOURCE_DIR}/${PROJECT_RELEASE}.ioc\n" "project generate\n" "exit\n" ) - execute_process(COMMAND ${JAVA_EXE} -jar ${CUBE_JAR} -q ${CMAKE_CURRENT_BINARY_DIR}/.cube) + execute_process(COMMAND ${CUBE_CMD} -q ${CMAKE_CURRENT_BINARY_DIR}/cube_script.txt) +endif() + +# Check linter configuration +if(LINTER_MODE STREQUAL "ON") + set(CMAKE_CXX_CLANG_TIDY "clang-tidy") + add_compile_options(-fms-extensions) + message(STATUS "Enabling clang-tidy, hex files will not be generated") +elseif(LINTER_MODE STREQUAL "FIX") + set(CMAKE_CXX_CLANG_TIDY "clang-tidy;--fix") + add_compile_options(-fms-extensions) + message(STATUS "Enabling clang-tidy with fix, hex files will not be generated") +else() + set(LINTER_MODE "OFF") + message(STATUS "Linter is disabled") endif() diff --git a/cmake/targets.cmake b/cmake/targets.cmake index 0a29039..f82521b 100644 --- a/cmake/targets.cmake +++ b/cmake/targets.cmake @@ -1,122 +1,132 @@ -# Name: targets.cmake -# ThundeRatz Robotics Team -# Brief: This file contains auxiliary custom targets declarations -# 04/2023 - ############################################################################### ## Auxiliary Targets ############################################################################### add_custom_target(helpme - COMMAND cat ${CMAKE_CURRENT_BINARY_DIR}/.helpme + COMMAND cat ${CMAKE_CURRENT_BINARY_DIR}/helpme ) add_custom_target(cube COMMAND echo "Generating cube files..." - COMMAND echo "config load ${CMAKE_CURRENT_SOURCE_DIR}/cube/${PROJECT_RELEASE}.ioc" > ${CMAKE_CURRENT_BINARY_DIR}/.cube - COMMAND echo "project generate" >> ${CMAKE_CURRENT_BINARY_DIR}/.cube - COMMAND echo "exit" >> ${CMAKE_CURRENT_BINARY_DIR}/.cube + COMMAND echo "config load ${CUBE_SOURCE_DIR}/${PROJECT_RELEASE}.ioc" > ${CMAKE_CURRENT_BINARY_DIR}/cube_script.txt + COMMAND echo "project generate" >> ${CMAKE_CURRENT_BINARY_DIR}/cube_script.txt + COMMAND echo "exit" >> ${CMAKE_CURRENT_BINARY_DIR}/cube_script.txt - COMMAND ${JAVA_EXE} -jar ${CUBE_JAR} -q ${CMAKE_CURRENT_BINARY_DIR}/.cube + COMMAND ${CUBE_CMD} -q ${CMAKE_CURRENT_BINARY_DIR}/cube_script.txt ) add_custom_target(info - STM32_Programmer_CLI -c port=SWD + COMMAND ${PROGRAMMER_CMD} -c port=SWD ) add_custom_target(reset - COMMAND echo "Reseting device" - COMMAND STM32_Programmer_CLI -c port=SWD -rst + COMMAND echo "Resetting device" + COMMAND ${PROGRAMMER_CMD} -c port=SWD -rst ) -add_custom_target(clean_all +add_custom_target(clear COMMAND echo "Cleaning all build files..." COMMAND rm -rf ${CMAKE_CURRENT_BINARY_DIR}/* ) -add_custom_target(clean_cube +add_custom_target(clear_cube COMMAND echo "Cleaning cube files..." COMMAND mv ${CMAKE_CURRENT_SOURCE_DIR}/cube/*.ioc . - COMMAND rm -rf ${CMAKE_CURRENT_SOURCE_DIR}/cube/* + COMMAND rm -rf ${CMAKE_CURRENT_SOURCE_DIR}/cube + COMMAND mkdir ${CMAKE_CURRENT_SOURCE_DIR}/cube COMMAND mv *.ioc ${CMAKE_CURRENT_SOURCE_DIR}/cube/ ) +add_custom_target(clear_all + COMMAND ${CMAKE_MAKE_PROGRAM} clear_cube + COMMAND echo "Cleaning all build files..." + COMMAND rm -rf ${CMAKE_CURRENT_BINARY_DIR}/* +) + add_custom_target(rebuild - COMMAND ${CMAKE_MAKE_PROGRAM} clean_all + COMMAND ${CMAKE_MAKE_PROGRAM} clear COMMAND cmake .. COMMAND ${CMAKE_MAKE_PROGRAM} ) add_custom_target(rebuild_all - COMMAND ${CMAKE_MAKE_PROGRAM} clean_cube - COMMAND ${CMAKE_MAKE_PROGRAM} clean_all + COMMAND ${CMAKE_MAKE_PROGRAM} clear_all COMMAND cmake .. COMMAND ${CMAKE_MAKE_PROGRAM} ) -function(targets_generate_format_target) - set(FILES_LIST "") +add_custom_target(docs + COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && doxygen Doxyfile + COMMAND yes Q | make -C ${CMAKE_CURRENT_SOURCE_DIR}/docs/latex || true + COMMAND mv ${CMAKE_CURRENT_SOURCE_DIR}/docs/latex/refman.pdf ${CMAKE_CURRENT_SOURCE_DIR}/docs/ + COMMAND rm -rf ${CMAKE_CURRENT_SOURCE_DIR}/docs/latex +) + +function(generate_test_all_target) + foreach(FILE ${ARGV}) + get_filename_component(TEST_NAME ${FILE} NAME_WLE) + list(APPEND TEST_TARGETS ${TEST_NAME}) + endforeach() + + add_custom_target(test_all + COMMAND ${CMAKE_MAKE_PROGRAM} ${TEST_TARGETS} + ) +endfunction() + +function(generate_format_target) foreach(FILE ${ARGV}) list(APPEND FILES_LIST ${${FILE}}) endforeach() + add_custom_target(format - COMMAND uncrustify -c ${CMAKE_CURRENT_SOURCE_DIR}/uncrustify.cfg --replace --no-backup ${FILES_LIST} + COMMAND clang-format -style=file -i ${FILES_LIST} --verbose ) endfunction() # Flash via st-link or jlink -function(targets_generate_flash_target TARGET) +function(generate_flash_target TARGET) if("${TARGET}" STREQUAL "${PROJECT_NAME}") set(TARGET_SUFFIX "") else() - set(TARGET_SUFFIX _${TARGET}) + set(TARGET_SUFFIX "_${TARGET}") endif() add_custom_target(flash${TARGET_SUFFIX} COMMAND echo "Flashing..." - COMMAND STM32_Programmer_CLI -c port=SWD -w ${TARGET}.hex -v -rst + COMMAND ${PROGRAMMER_CMD} -c port=SWD -w ${TARGET}.hex -v -rst ) add_dependencies(flash${TARGET_SUFFIX} ${TARGET}) - set(input_file ${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/jlink.in) - configure_file(${input_file} ${CMAKE_CURRENT_BINARY_DIR}/jlinkflash/.jlink-flash${TARGET_SUFFIX}) + set(input_file "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/jlink.in") + configure_file(${input_file} "${CMAKE_CURRENT_BINARY_DIR}/jlinkflash/.jlink-flash${TARGET_SUFFIX}") add_custom_target(jflash${TARGET_SUFFIX} COMMAND echo "Flashing ${PROJECT_NAME}.hex with J-Link" - COMMAND ${JLINK_EXE} ${CMAKE_CURRENT_BINARY_DIR}/.jlink-flash${TARGET_SUFFIX} - COMMAND ${JLINK_EXE} ${CMAKE_CURRENT_BINARY_DIR}/jlinkflash/.jlink-flash${TARGET_SUFFIX} + COMMAND ${JLINK_CMD} ${CMAKE_CURRENT_BINARY_DIR}/jlinkflash/.jlink-flash${TARGET_SUFFIX} ) add_dependencies(jflash${TARGET_SUFFIX} ${TARGET}) endfunction() -function(targets_generate_vsfiles_target TARGET) +function(generate_debug_target TARGET) if("${TARGET}" STREQUAL "${PROJECT_NAME}") set(TARGET_SUFFIX "") else() - set(TARGET_SUFFIX _${TARGET}) + set(TARGET_SUFFIX "_${TARGET}") endif() set(DEBUG_FILE_NAME ${TARGET}) - set(input_file ${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/launch.json.in) - set(ouput_save_file ${CMAKE_CURRENT_BINARY_DIR}/vsfiles/.vsfiles${TARGET_SUFFIX}) + set(input_file "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/launch.json.in") + set(output_save_file "${CMAKE_CURRENT_BINARY_DIR}/vsfiles/.vsfiles${TARGET_SUFFIX}") + configure_file(${input_file} ${output_save_file}) - configure_file(${input_file} ${ouput_save_file}) - - add_custom_target(debug_files${TARGET_SUFFIX} + add_custom_target(debug${TARGET_SUFFIX} COMMAND echo "Configuring VS Code files for ${TARGET}" - COMMAND cat ${ouput_save_file} > ${LAUNCH_JSON_PATH} + COMMAND cat ${output_save_file} > ${LAUNCH_JSON_PATH} ) - add_dependencies(debug_files${TARGET_SUFFIX} ${TARGET}) -endfunction() - -function(targets_generate_helpme_target) - set(input_file ${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/helpme.in) - set(ouput_save_file ${CMAKE_CURRENT_BINARY_DIR}/.helpme) - - configure_file(${input_file} ${ouput_save_file}) + add_dependencies(debug${TARGET_SUFFIX} ${TARGET}) endfunction() diff --git a/cmake/templates/helpme.in b/cmake/templates/helpme.in index 7dbce56..9ffeb7b 100644 --- a/cmake/templates/helpme.in +++ b/cmake/templates/helpme.in @@ -4,23 +4,40 @@ and modify the file if necessary Options: + all: build main project target, can also be called using only make helpme: show this help cube: generate cube files info: show information about the connected uC (microcontroller) + [test_name]: compile the project with the test file as executable + test_all: compile all test files and generate tests executables flash: load the compiled files of the main program into the microcontroller via st-link flash_[test_name]: load the compiled files of a test into the microcontroller via st-link jflash: load the compiled files of the main program into the microcontroller via j-link jflash_[test_name]: load the compiled files of a test into the microcontroller via j-link + debug generate the VS Code files for debugging the main program + debug_[test_name]: generate the VS Code files for debugging a test format: format .c/.h files - clean: clean the compiled files - clean_all: delete all files in the /build folder - clean_cube: clean the files generated by Cube + clear: delete all files in the /build folder + clear_cube: clean the files generated by Cube + clear_all: delete all files in the /build folder and the files generated by Cube reset: reset the microcontroller rebuild: recompile the files in the /build folder rebuild_all: recompile the files in the /build folder and the files generated by Cube + docs: generate the Doxygen documentation -Current configurations: - DEVICE_FAMILY = ${DEVICE_FAMILY} - DEVICE_TYPE = ${DEVICE_TYPE} - DEVICE = ${DEVICE} - DEVICE_DEF = ${DEVICE_DEF} +Project Variables: + When running the cmake command, you can set the following variables + by adding `-D{VARIABLE}={VALUE}` after `cmake ..` in the terminal: + BUILD_TYPE: Set the project build type + Possible values: Debug, Release, RelWithDebInfo, MinSizeRel (default: RelWithDebInfo) + LINTER_MODE: Set clang-tidy linter mode + Possible values: ON, OFF, FIX (default: OFF) + +Current configuration: + PROJECT NAME = ${CMAKE_PROJECT_NAME} + IOC FILE = ${PROJECT_RELEASE}.ioc + DEVICE = ${DEVICE} + BUILD TYPE = ${BUILD_TYPE} + LINTER MODE = ${LINTER_MODE} + +--------------------------------------------------------------------------- diff --git a/cmake/templates/launch.json.in b/cmake/templates/launch.json.in index dfd9a6b..1bc3193 100644 --- a/cmake/templates/launch.json.in +++ b/cmake/templates/launch.json.in @@ -2,26 +2,40 @@ "version": "0.2.0", "configurations": [ { + "name": "Cortex Debug (OpenOCD)", "type": "cortex-debug", "request": "launch", - "servertype": "stutil", + "servertype": "external", "cwd": "${CMAKE_CURRENT_SOURCE_DIR}", - "gdbPath": "arm-none-eabi-gdb", - "executable": "build/${DEBUG_FILE_NAME}.elf", - "name": "Cortex Debug (ST-Util)", - "device": "${DEVICE}", - "v1": false + "executable": "${CMAKE_CURRENT_BINARY_DIR}/${DEBUG_FILE_NAME}.elf", + "gdbPath": "gdb-multiarch", + "runToEntryPoint": "main", + "preLaunchTask": "Launch OpenOCD", + "gdbTarget": "localhost:3333", }, { + "name": "Cortex Debug (J-Link)", "type": "cortex-debug", "request": "launch", "servertype": "jlink", "cwd": "${CMAKE_CURRENT_SOURCE_DIR}", - "gdbPath": "arm-none-eabi-gdb", - "executable": "build/${DEBUG_FILE_NAME}.elf", - "name": "Cortex Debug (J-Link)", + "executable": "${CMAKE_CURRENT_BINARY_DIR}/${DEBUG_FILE_NAME}.elf", + "gdbPath": "gdb-multiarch", + "runToEntryPoint": "main", "device": "${DEVICE}", "interface": "swd", - } + }, + { + "name": "Cortex Debug (ST-Util)", + "type": "cortex-debug", + "request": "launch", + "servertype": "stutil", + "cwd": "${CMAKE_CURRENT_SOURCE_DIR}", + "executable": "${CMAKE_CURRENT_BINARY_DIR}/${DEBUG_FILE_NAME}.elf", + "gdbPath": "gdb-multiarch", + "runToEntryPoint": "main", + "device": "${DEVICE}", + "v1": false + }, ] } diff --git a/cmake/templates/tasks.json.in b/cmake/templates/tasks.json.in new file mode 100644 index 0000000..e08f9c5 --- /dev/null +++ b/cmake/templates/tasks.json.in @@ -0,0 +1,26 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Launch OpenOCD", + "command": "${OPENOCD_CMD} -f ${OPENOCD_SCRIPTS_PATH}/interface/stlink.cfg -f ${OPENOCD_SCRIPTS_PATH}/target/${TARGET_CFG}x.cfg", + "type": "shell", + "problemMatcher": { + "pattern": [ + { + "regexp": "", + "file": 1, + "location": 2, + "message": 3 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": "Open On-Chip Debugger", + "endsPattern": "Listening on port" + } + }, + "isBackground": true + } + ] +} diff --git a/cmake/utilities.cmake b/cmake/utilities.cmake new file mode 100644 index 0000000..41ec529 --- /dev/null +++ b/cmake/utilities.cmake @@ -0,0 +1,67 @@ +############################################################################### +## Utilities Functions +############################################################################### + +# This function adds a target with name '${TARGET}_always_display_size'. The new +# target builds a TARGET and then calls the program defined in CMAKE_SIZE to +# display the size of the final ELF. +function(print_size_of_target TARGET) + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${CMAKE_SIZE} "$" + COMMENT "Target Sizes: " + ) +endfunction() + +# This function calls the objcopy program defined in CMAKE_OBJCOPY to generate +# file with object format specified in OBJCOPY_BFD_OUTPUT. +# The generated file has the name of the target output but with extension +# corresponding to the OUTPUT_EXTENSION argument value. +# The generated file will be placed in the same directory as the target output file. +function(_generate_file TARGET OUTPUT_EXTENSION OBJCOPY_BFD_OUTPUT) + # If linter is enabled, do not generate files + if(LINTER_MODE STREQUAL "ON" OR LINTER_MODE STREQUAL "FIX") + return() + endif() + + set(OUTPUT_FILE_NAME "${TARGET}.${OUTPUT_EXTENSION}") + + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O ${OBJCOPY_BFD_OUTPUT} "$" ${OUTPUT_FILE_NAME} + BYPRODUCTS ${OUTPUT_FILE_NAME} + COMMENT "Generating ${OBJCOPY_BFD_OUTPUT} file ${OUTPUT_FILE_NAME}" + ) +endfunction() + +# This function adds post-build generation of the binary file from the target ELF. +# The generated file will be placed in the same directory as the ELF file. +function(generate_binary_file TARGET) + _generate_file(${TARGET} "bin" "binary") +endfunction() + +# This function adds post-build generation of the Motorola S-record file from the target ELF. +# The generated file will be placed in the same directory as the ELF file. +function(generate_srec_file TARGET) + _generate_file(${TARGET} "srec" "srec") +endfunction() + +# This function adds post-build generation of the Intel hex file from the target ELF. +# The generated file will be placed in the same directory as the ELF file. +function(generate_hex_file TARGET) + _generate_file(${TARGET} "hex" "ihex") +endfunction() + +function(generate_helpme_text) + set(input_file "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/helpme.in") + set(output_save_file "${CMAKE_CURRENT_BINARY_DIR}/helpme") + configure_file(${input_file} ${output_save_file}) +endfunction() + +function(generate_vscode_tasks_json) + set(input_file "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/tasks.json.in") + set(output_save_file "${CMAKE_CURRENT_SOURCE_DIR}/.vscode/tasks.json") + configure_file(${input_file} ${output_save_file}) +endfunction() diff --git a/cmake/workspace.cmake b/cmake/workspace.cmake deleted file mode 100644 index 6577724..0000000 --- a/cmake/workspace.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# Name: workspace.cmake -# ThundeRatz Robotics Team -# Brief: CMake file to generate VS Code files and link githooks -# 04/2023 - -############################################################################### -## VS Code files -############################################################################### - -message(STATUS "Configuring VS Code files") -configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/launch.json.in ${LAUNCH_JSON_PATH} -) - -############################################################################### -## Link Githooks -############################################################################### - -message(STATUS "Linking githooks") -execute_process( - COMMAND git config core.hooksPath ${CMAKE_CURRENT_SOURCE_DIR}/.githooks -) diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..3f79278 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,38 @@ +services: + base: + build: + dockerfile: .docker/Dockerfile + target: base + + build: + command: /project/.docker/scripts/build.sh + build: + dockerfile: .docker/Dockerfile + target: build + + lint: + command: /project/.docker/scripts/build.sh -DLINTER_MODE=ON + build: + dockerfile: .docker/Dockerfile + target: build + + check-format: + command: /project/.docker/scripts/check_format.sh + build: + dockerfile: .docker/Dockerfile + target: build + + dev: + command: bash + build: + dockerfile: .docker/Dockerfile + target: base + privileged: True + environment: + - DISPLAY=${DISPLAY} + - QT_X11_NO_MITSHM=1 + - NVIDIA_DRIVER_CAPABILITIES=all + volumes: + - .:/project:rw + - /tmp/.X11-unix:/tmp/.X11-unix:rw + - ${XAUTHORITY:-$HOME/.Xauthority}:/root/.Xauthority diff --git a/config/target.hpp b/config/target.hpp new file mode 100644 index 0000000..8076be0 --- /dev/null +++ b/config/target.hpp @@ -0,0 +1,14 @@ +#ifndef TARGET_HPP +#define TARGET_HPP + +#include "gpio.hpp" +#include + +const hal::Gpio::Config led_config = { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast, + // performance-no-int-to-ptr) + .port = LED_GPIO_Port, + .pin = LED_Pin, +}; + +#endif // TARGET_HPP diff --git a/cube/stm32_project_template.ioc b/cube/stm32_project_template.ioc index b4efc92..53325e0 100644 --- a/cube/stm32_project_template.ioc +++ b/cube/stm32_project_template.ioc @@ -1,97 +1,47 @@ #MicroXplorer Configuration settings - do not modify -CAD.formats= -CAD.pinconfig= +CAD.formats=[] +CAD.pinconfig=Dual CAD.provider= File.Version=6 -KeepUserPlacement=true -Mcu.CPN=STM32F303RET6 -Mcu.Family=STM32F3 +GPIO.groupedBy=Group By Peripherals +KeepUserPlacement=false +Mcu.CPN=STM32F103C8T6 +Mcu.Family=STM32F1 Mcu.IP0=NVIC Mcu.IP1=RCC Mcu.IP2=SYS -Mcu.IP3=USART1 -Mcu.IP4=USART2 -Mcu.IPNb=5 -Mcu.Name=STM32F303R(D-E)Tx -Mcu.Package=LQFP64 -Mcu.Pin0=PC13 -Mcu.Pin1=PC14-OSC32_IN -Mcu.Pin10=PA13 -Mcu.Pin11=PA14 -Mcu.Pin12=PB3 -Mcu.Pin13=VP_SYS_VS_Systick -Mcu.Pin2=PC15-OSC32_OUT -Mcu.Pin3=PF0-OSC_IN -Mcu.Pin4=PF1-OSC_OUT -Mcu.Pin5=PA2 -Mcu.Pin6=PA3 -Mcu.Pin7=PA5 -Mcu.Pin8=PA9 -Mcu.Pin9=PA10 -Mcu.PinsNb=14 +Mcu.IPNb=3 +Mcu.Name=STM32F103C(8-B)Tx +Mcu.Package=LQFP48 +Mcu.Pin0=PC13-TAMPER-RTC +Mcu.Pin1=PA13 +Mcu.Pin2=PA14 +Mcu.Pin3=VP_SYS_VS_Systick +Mcu.PinsNb=4 Mcu.ThirdPartyNb=0 Mcu.UserConstants= -Mcu.UserName=STM32F303RETx -MxCube.Version=6.9.0 -MxDb.Version=DB.6.0.90 -NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false -NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false +Mcu.UserName=STM32F103C8Tx +MxCube.Version=6.13.0 +MxDb.Version=DB.6.0.130 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.ForceEnableDMAVector=true -NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false -NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false -NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false -NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false -NVIC.PriorityGroup=NVIC_PRIORITYGROUP_0 -NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false -NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:true\:true\:true\:false -NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:false\:true\:false\:false -PA10.Locked=true -PA10.Mode=Asynchronous -PA10.Signal=USART1_RX -PA13.GPIOParameters=GPIO_Label -PA13.GPIO_Label=TMS -PA13.Locked=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO -PA14.GPIOParameters=GPIO_Label -PA14.GPIO_Label=TCK -PA14.Locked=true PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA2.Mode=Asynchronous -PA2.Signal=USART2_TX -PA3.Mode=Asynchronous -PA3.Signal=USART2_RX -PA5.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode -PA5.GPIO_Label=LD2 [Green Led] -PA5.GPIO_Mode=GPIO_MODE_OUTPUT_PP -PA5.GPIO_PuPd=GPIO_NOPULL -PA5.GPIO_Speed=GPIO_SPEED_FREQ_LOW -PA5.Locked=true -PA5.Signal=GPIO_Output -PA9.Locked=true -PA9.Mode=Asynchronous -PA9.Signal=USART1_TX -PB3.GPIOParameters=GPIO_Label -PB3.GPIO_Label=SWO -PB3.Locked=true -PB3.Signal=SYS_JTDO-TRACESWO -PC13.GPIOParameters=GPIO_Label,GPIO_ModeDefaultEXTI -PC13.GPIO_Label=B1 [Blue PushButton] -PC13.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING -PC13.Locked=true -PC13.Signal=GPXTI13 -PC14-OSC32_IN.Locked=true -PC14-OSC32_IN.Mode=LSE-External-Oscillator -PC14-OSC32_IN.Signal=RCC_OSC32_IN -PC15-OSC32_OUT.Locked=true -PC15-OSC32_OUT.Mode=LSE-External-Oscillator -PC15-OSC32_OUT.Signal=RCC_OSC32_OUT -PF0-OSC_IN.Locked=true -PF0-OSC_IN.Mode=HSE-External-Clock-Source -PF0-OSC_IN.Signal=RCC_OSC_IN -PF1-OSC_OUT.Locked=true -PF1-OSC_OUT.Signal=RCC_OSC_OUT +PC13-TAMPER-RTC.GPIOParameters=GPIO_Label +PC13-TAMPER-RTC.GPIO_Label=LED +PC13-TAMPER-RTC.Locked=true +PC13-TAMPER-RTC.Signal=GPIO_Output PinOutPanel.RotationAngle=0 ProjectManager.AskForMigrate=true ProjectManager.BackupPrevious=false @@ -101,8 +51,8 @@ ProjectManager.CoupleFile=true ProjectManager.CustomerFirmwarePackage= ProjectManager.DefaultFWLocation=true ProjectManager.DeletePrevious=true -ProjectManager.DeviceId=STM32F303RETx -ProjectManager.FirmwarePackage=STM32Cube FW_F3 V1.11.4 +ProjectManager.DeviceId=STM32F103C8Tx +ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.6 ProjectManager.FreePins=false ProjectManager.HalAssertFull=false ProjectManager.HeapSize=0x200 @@ -118,68 +68,31 @@ ProjectManager.ProjectName=stm32_project_template ProjectManager.ProjectStructure= ProjectManager.RegisterCallBack= ProjectManager.StackSize=0x400 -ProjectManager.TargetToolchain=Makefile +ProjectManager.TargetToolchain=CMake ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART2_UART_Init-USART2-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true -RCC.ADC12outputFreq_Value=72000000 -RCC.ADC34outputFreq_Value=72000000 -RCC.AHBFreq_Value=72000000 +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true +RCC.ADCFreqValue=32000000 +RCC.AHBFreq_Value=64000000 RCC.APB1CLKDivider=RCC_HCLK_DIV2 -RCC.APB1Freq_Value=36000000 -RCC.APB1TimFreq_Value=72000000 -RCC.APB2Freq_Value=72000000 -RCC.APB2TimFreq_Value=72000000 -RCC.CortexFreq_Value=72000000 -RCC.FCLKCortexFreq_Value=72000000 +RCC.APB1Freq_Value=32000000 +RCC.APB1TimFreq_Value=64000000 +RCC.APB2Freq_Value=64000000 +RCC.APB2TimFreq_Value=64000000 +RCC.FCLKCortexFreq_Value=64000000 RCC.FamilyName=M -RCC.HCLKFreq_Value=72000000 -RCC.HSE_VALUE=8000000 -RCC.HSI_VALUE=8000000 -RCC.I2C1Freq_Value=8000000 -RCC.I2C2Freq_Value=8000000 -RCC.I2C3Freq_Value=8000000 -RCC.I2SClocksFreq_Value=72000000 -RCC.IPParameters=ADC12outputFreq_Value,ADC34outputFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,I2SClocksFreq_Value,LSI_VALUE,MCOFreq_Value,PLLCLKFreq_Value,PLLM,PLLMCOFreq_Value,PLLMUL,PLLN,PLLP,PLLQ,RCC_PLLsource_Clock_Source_FROM_HSE,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSourceVirtual,TIM15Freq_Value,TIM16Freq_Value,TIM17Freq_Value,TIM1Freq_Value,TIM20Freq_Value,TIM2Freq_Value,TIM3Freq_Value,TIM8Freq_Value,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOOutput2Freq_Value -RCC.LSI_VALUE=40000 -RCC.MCOFreq_Value=72000000 -RCC.PLLCLKFreq_Value=72000000 -RCC.PLLM=8 -RCC.PLLMCOFreq_Value=72000000 -RCC.PLLMUL=RCC_PLL_MUL9 -RCC.PLLN=336 -RCC.PLLP=RCC_PLLP_DIV4 -RCC.PLLQ=7 -RCC.RCC_PLLsource_Clock_Source_FROM_HSE=RCC_HSE_PREDIV_DIV2 -RCC.RTCFreq_Value=40000 -RCC.RTCHSEDivFreq_Value=250000 -RCC.SYSCLKFreq_VALUE=72000000 -RCC.SYSCLKSourceVirtual=RCC_SYSCLKSOURCE_PLLCLK -RCC.TIM15Freq_Value=72000000 -RCC.TIM16Freq_Value=72000000 -RCC.TIM17Freq_Value=72000000 -RCC.TIM1Freq_Value=72000000 -RCC.TIM20Freq_Value=72000000 -RCC.TIM2Freq_Value=72000000 -RCC.TIM3Freq_Value=72000000 -RCC.TIM8Freq_Value=72000000 -RCC.UART4Freq_Value=36000000 -RCC.UART5Freq_Value=36000000 -RCC.USART1Freq_Value=72000000 -RCC.USART2Freq_Value=36000000 -RCC.USART3Freq_Value=36000000 -RCC.USBFreq_Value=72000000 -RCC.VCOOutput2Freq_Value=8000000 -SH.GPXTI13.0=GPIO_EXTI13 -SH.GPXTI13.ConfNb=1 -USART1.BaudRate=115200 -USART1.IPParameters=VirtualMode-Asynchronous,BaudRate -USART1.VirtualMode-Asynchronous=VM_ASYNC -USART2.BaudRate=115200 -USART2.IPParameters=VirtualMode-Asynchronous,BaudRate -USART2.VirtualMode-Asynchronous=VM_ASYNC +RCC.HCLKFreq_Value=64000000 +RCC.IPParameters=ADCFreqValue,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value +RCC.MCOFreq_Value=64000000 +RCC.PLLCLKFreq_Value=64000000 +RCC.PLLMCOFreq_Value=32000000 +RCC.PLLMUL=RCC_PLL_MUL16 +RCC.SYSCLKFreq_VALUE=64000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.TimSysFreq_Value=64000000 +RCC.USBFreq_Value=64000000 VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick board=custom diff --git a/inc/mcu.h b/inc/mcu.h deleted file mode 100644 index 3d09bf9..0000000 --- a/inc/mcu.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file mcu.h - * - * @brief MCU related - */ - -#ifndef __MCU_H__ -#define __MCU_H__ - -#include - -/***************************************** - * Public Function Prototypes - *****************************************/ - -/** - * @brief Initializes MCU and some peripherals. - */ -void mcu_init(void); - -/** - * @brief Initializes System Clock. - * @note Defined by cube. - */ -void SystemClock_Config(void); - -/** - * @brief Put the MCU to sleep. - * - * @param ms Sleep time in milliseconds - */ -void mcu_sleep(uint32_t ms); - -/** - * @brief Toggles LED. - */ -void led_toggle(void); - -#endif // __MCU_H__ diff --git a/include/gpio.hpp b/include/gpio.hpp new file mode 100644 index 0000000..5999e6b --- /dev/null +++ b/include/gpio.hpp @@ -0,0 +1,75 @@ +/** + * @file gpio.hpp + * + * @brief HAL GPIO class header + * + * @author Thunderatz Development Team + */ + +#ifndef HAL_GPIO_HPP +#define HAL_GPIO_HPP + +#include +#include + +namespace hal { +/** + * @brief Class for controlling GPIO pins on STM32 microcontrollers + */ +class Gpio { +public: + /** + * @brief Configuration structure for GPIO pin + */ + struct Config { + GPIO_TypeDef* port{}; + uint16_t pin{}; + GPIO_PinState active_state = GPIO_PIN_SET; + }; + + /** + * @brief Constructor for the Gpio class + * + * @param config Configuration for the GPIO pin + */ + explicit Gpio(const Config& config); + + /** + * @brief Read the current state of the GPIO pin + * + * @return bool The current state of the GPIO pin (true for high, false for + * low) + */ + bool read() const; + + /** + * @brief Write a new state to the GPIO pin + * + * @param pin_state The state to be written (true for high, false for low) + */ + void write(bool state); + + /** + * @brief Toggle the state of the GPIO pin + */ + void toggle(); + +private: + /** + * @brief The port of the GPIO + */ + GPIO_TypeDef* port; + + /** + * @brief The pin number of the GPIO + */ + uint16_t pin; + + /** + * @brief The active state of the GPIO + */ + GPIO_PinState active_state; +}; +} // namespace hal + +#endif // HAL_GPIO_HPP diff --git a/include/mcu.hpp b/include/mcu.hpp new file mode 100644 index 0000000..ae88ab2 --- /dev/null +++ b/include/mcu.hpp @@ -0,0 +1,42 @@ +/** + * @file mcu.hpp + * + * @brief MCU related + * + * @author Thunderatz Development Team + */ + +#ifndef MCU_HPP +#define MCU_HPP + +#include + +/***************************************** + * Public Function Prototypes + *****************************************/ + +extern "C" { +/** + * @brief Initializes System Clock. + * @note Defined by cube. + */ +void SystemClock_Config(void); +} + +namespace hal { +class mcu { +public: + /** + * @brief Initializes MCU and some peripherals. + */ + static void init(); + + /** + * @brief Put the MCU to sleep. + * + * @param ms Sleep time in milliseconds + */ + static void sleep(uint32_t ms); +}; +} // namespace hal +#endif // MCU_HPP diff --git a/lib/stm32-cmake b/lib/stm32-cmake deleted file mode 160000 index e8c282e..0000000 --- a/lib/stm32-cmake +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e8c282e982310d9eab3af82fc01f2762c094359b diff --git a/src/gpio.cpp b/src/gpio.cpp new file mode 100644 index 0000000..11b2e6b --- /dev/null +++ b/src/gpio.cpp @@ -0,0 +1,31 @@ +/** + * @file gpio.cpp + * + * @brief HAL GPIO class source + * + * @author Thunderatz Development Team + */ + +#include "gpio.hpp" + +namespace hal { +Gpio::Gpio(const Config& config) : port{config.port}, pin{config.pin}, active_state{config.active_state} { } + +bool Gpio::read() const { + return HAL_GPIO_ReadPin(this->port, this->pin) == this->active_state; +} + +void Gpio::write(bool state) { + GPIO_PinState pin_state = this->active_state; + + if (!state) { + pin_state = (this->active_state == GPIO_PIN_SET) ? GPIO_PIN_RESET : GPIO_PIN_SET; + } + + HAL_GPIO_WritePin(this->port, this->pin, pin_state); +} + +void Gpio::toggle() { + HAL_GPIO_TogglePin(this->port, this->pin); +} +} // namespace hal diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 90f8109..0000000 --- a/src/main.c +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @file main.c - * - * @brief Main function - */ - -#include "mcu.h" - -/***************************************** - * Private Constant Definitions - *****************************************/ - -#define LED_TOGGLE_DELAY_MS 1500 - -/***************************************** - * Main Function - *****************************************/ - -int main(void) { - mcu_init(); - - for (;;) { - led_toggle(); - mcu_sleep(LED_TOGGLE_DELAY_MS); - } -} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..d98fb44 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,31 @@ +/** + * @file main.cpp + * + * @brief Main function + * + * @author Thunderatz Development Team + */ + +#include "mcu.hpp" +#include "target.hpp" + +/***************************************** + * Private Constant Definitions + *****************************************/ + +static constexpr uint16_t led_toggle_delay_ms = 1500; + +/***************************************** + * Main Function + *****************************************/ + +int main() { + hal::mcu::init(); + + hal::Gpio led{led_config}; + + for (;;) { + led.toggle(); + hal::mcu::sleep(led_toggle_delay_ms); + } +} diff --git a/src/mcu.c b/src/mcu.cpp similarity index 53% rename from src/mcu.c rename to src/mcu.cpp index 12b6877..122aa46 100644 --- a/src/mcu.c +++ b/src/mcu.cpp @@ -1,21 +1,20 @@ /** - * @file mcu.c + * @file mcu.cpp * * @brief MCU related + * + * @author Thunderatz Development Team */ -#include - -#include "mcu.h" - -#include "gpio.h" -#include "main.h" +#include "mcu.hpp" +#include /***************************************** * Public Function Body Definitions *****************************************/ -void mcu_init(void) { +namespace hal { +void mcu::init() { HAL_Init(); SystemClock_Config(); @@ -23,10 +22,7 @@ void mcu_init(void) { MX_GPIO_Init(); } -void mcu_sleep(uint32_t ms) { +void mcu::sleep(uint32_t ms) { HAL_Delay(ms); } - -void led_toggle(void) { - HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); -} +} // namespace hal diff --git a/tests/bin/test_main.c b/tests/bin/test_main.c deleted file mode 100644 index 4cc9e4b..0000000 --- a/tests/bin/test_main.c +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @file test_main.c - * - * @brief Main function for tests. - */ - -#include -#include "tests_core.h" - -int main(void) { - test_core_init(); - - for (;;) { - } -} diff --git a/tests/inc/test_core.h b/tests/inc/test_core.h deleted file mode 100644 index 058dc8b..0000000 --- a/tests/inc/test_core.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file test_core.h - * - * @brief Core functions to the test - * - * @date 04/2021 - * - * @copyright MIT License - * - */ - -#ifndef __TEST_CORE_H__ -#define __TEST_CORE_H__ - -/***************************************** - * Public Functions Prototypes - *****************************************/ - -/** - * @brief Initialize test core - * - */ -void test_core_init(void); - -#endif // __TEST_CORE_H__ diff --git a/tests/src/test_core.c b/tests/src/test_core.c deleted file mode 100644 index 3387397..0000000 --- a/tests/src/test_core.c +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @file test_core.c - * - * @brief Core functions to the test - * - * @date 04/2021 - * - * @copyright MIT License - * - */ - -#include "test_core.h" -#include "mcu.h" - -/***************************************** - * Public Functions Bodies Definitions - *****************************************/ - -void test_core_init(void) { - mcu_init(); -} diff --git a/tests/src/test_gpio.cpp b/tests/src/test_gpio.cpp new file mode 100644 index 0000000..3b2da16 --- /dev/null +++ b/tests/src/test_gpio.cpp @@ -0,0 +1,21 @@ +/** + * @file test_gpio.cpp + * + * @brief Test for GPIO HAL implementation + * + * @author Thunderatz Development Team + */ + +#include "mcu.hpp" +#include "target.hpp" + +int main() { + hal::mcu::init(); + + hal::Gpio led{led_config}; + + for (;;) { + led.toggle(); + hal::mcu::sleep(500); + } +} diff --git a/tests/src/test_main.cpp b/tests/src/test_main.cpp new file mode 100644 index 0000000..1fe76ba --- /dev/null +++ b/tests/src/test_main.cpp @@ -0,0 +1,15 @@ +/** + * @file test_main.cpp + * + * @brief Main function for tests. + * + * @author Thunderatz Development Team + */ + +#include "mcu.hpp" + +int main() { + hal::mcu::init(); + + for (;;) { } +} diff --git a/uncrustify.cfg b/uncrustify.cfg deleted file mode 100644 index 26fd455..0000000 --- a/uncrustify.cfg +++ /dev/null @@ -1,2132 +0,0 @@ -# Uncrustify-0.66.1_f - -# -# General options -# - -# The type of line endings. Default=Auto. -newlines = auto # auto/lf/crlf/cr - -# The original size of tabs in the input. Default=8. -input_tab_size = 4 # unsigned number - -# The size of tabs in the output (only used if align_with_tabs=true). Default=8. -output_tab_size = 4 # unsigned number - -# The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn). -string_escape_char = 92 # unsigned number - -# Alternate string escape char for Pawn. Only works right before the quote char. -string_escape_char2 = 0 # unsigned number - -# Replace tab characters found in string literals with the escape sequence \t instead. -string_replace_tab_chars = false # false/true - -# Allow interpreting '>=' and '>>=' as part of a template in 'void f(list>=val);'. -# If True, 'assert(x<0 && y>=3)' will be broken. Default=False -# Improvements to template detection may make this option obsolete. -tok_split_gte = false # false/true - -# Override the default ' *INDENT-OFF*' in comments for disabling processing of part of the file. -disable_processing_cmt = "FORMAT_OFF" # string - -# Override the default ' *INDENT-ON*' in comments for enabling processing of part of the file. -enable_processing_cmt = "FORMAT_ON" # string - -# Enable parsing of digraphs. Default=False. -enable_digraphs = false # false/true - -# Control what to do with the UTF-8 BOM (recommend 'remove'). -utf8_bom = ignore # ignore/add/remove/force - -# If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8. -utf8_byte = false # false/true - -# Force the output encoding to UTF-8. -utf8_force = false # false/true - -# -# Spacing options -# - -# Add or remove space around arithmetic operator '+', '-', '/', '*', etc -# also '>>>' '<<' '>>' '%' '|'. -sp_arith = add # ignore/add/remove/force - -# Add or remove space around arithmetic operator '+' and '-'. Overrides sp_arith -sp_arith_additive = ignore # ignore/add/remove/force - -# Add or remove space around assignment operator '=', '+=', etc. -sp_assign = force # ignore/add/remove/force - -# Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign. -sp_cpp_lambda_assign = ignore # ignore/add/remove/force - -# Add or remove space after the capture specification in C++11 lambda. -sp_cpp_lambda_paren = ignore # ignore/add/remove/force - -# Add or remove space around assignment operator '=' in a prototype. -sp_assign_default = force # ignore/add/remove/force - -# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign. -sp_before_assign = ignore # ignore/add/remove/force - -# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign. -sp_after_assign = ignore # ignore/add/remove/force - -# Add or remove space in 'NS_ENUM ('. -sp_enum_paren = ignore # ignore/add/remove/force - -# Add or remove space around assignment '=' in enum. -sp_enum_assign = force # ignore/add/remove/force - -# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign. -sp_enum_before_assign = ignore # ignore/add/remove/force - -# Add or remove space after assignment '=' in enum. Overrides sp_enum_assign. -sp_enum_after_assign = ignore # ignore/add/remove/force - -# Add or remove space around assignment ':' in enum. -sp_enum_colon = ignore # ignore/add/remove/force - -# Add or remove space around preprocessor '##' concatenation operator. Default=Add. -sp_pp_concat = remove # ignore/add/remove/force - -# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. -sp_pp_stringify = remove # ignore/add/remove/force - -# Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'. -sp_before_pp_stringify = ignore # ignore/add/remove/force - -# Add or remove space around boolean operators '&&' and '||'. -sp_bool = force # ignore/add/remove/force - -# Add or remove space around compare operator '<', '>', '==', etc. -sp_compare = force # ignore/add/remove/force - -# Add or remove space inside '(' and ')'. -sp_inside_paren = remove # ignore/add/remove/force - -# Add or remove space between nested parens: '((' vs ') )'. -sp_paren_paren = remove # ignore/add/remove/force - -# Add or remove space between back-to-back parens: ')(' vs ') ('. -sp_cparen_oparen = ignore # ignore/add/remove/force - -# Whether to balance spaces inside nested parens. -sp_balance_nested_parens = false # false/true - -# Add or remove space between ')' and '{'. -sp_paren_brace = force # ignore/add/remove/force - -# Add or remove space before pointer star '*'. -sp_before_ptr_star = remove # ignore/add/remove/force - -# Add or remove space before pointer star '*' that isn't followed by a variable name -# If set to 'ignore', sp_before_ptr_star is used instead. -sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force - -# Add or remove space between pointer stars '*'. -sp_between_ptr_star = remove # ignore/add/remove/force - -# Add or remove space after pointer star '*', if followed by a word. -sp_after_ptr_star = add # ignore/add/remove/force - -# Add or remove space after pointer star '*', if followed by a qualifier. -sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force - -# Add or remove space after a pointer star '*', if followed by a func proto/def. -sp_after_ptr_star_func = add # ignore/add/remove/force - -# Add or remove space after a pointer star '*', if followed by an open paren (function types). -sp_ptr_star_paren = ignore # ignore/add/remove/force - -# Add or remove space before a pointer star '*', if followed by a func proto/def. -sp_before_ptr_star_func = remove # ignore/add/remove/force - -# Add or remove space before a reference sign '&'. -sp_before_byref = remove # ignore/add/remove/force - -# Add or remove space before a reference sign '&' that isn't followed by a variable name. -# If set to 'ignore', sp_before_byref is used instead. -sp_before_unnamed_byref = ignore # ignore/add/remove/force - -# Add or remove space after reference sign '&', if followed by a word. -sp_after_byref = add # ignore/add/remove/force - -# Add or remove space after a reference sign '&', if followed by a func proto/def. -sp_after_byref_func = force # ignore/add/remove/force - -# Add or remove space before a reference sign '&', if followed by a func proto/def. -sp_before_byref_func = remove # ignore/add/remove/force - -# Add or remove space between type and word. Default=Force. -sp_after_type = force # ignore/add/remove/force - -# Add or remove space before the paren in the D constructs 'template Foo(' and 'class Foo('. -sp_before_template_paren = ignore # ignore/add/remove/force - -# Add or remove space in 'template <' vs 'template<'. -# If set to ignore, sp_before_angle is used. -sp_template_angle = force # ignore/add/remove/force - -# Add or remove space before '<>'. -sp_before_angle = remove # ignore/add/remove/force - -# Add or remove space inside '<' and '>'. -sp_inside_angle = remove # ignore/add/remove/force - -# Add or remove space between '<>' and ':'. -sp_angle_colon = ignore # ignore/add/remove/force - -# Add or remove space after '<>'. -sp_after_angle = force # ignore/add/remove/force - -# Add or remove space between '<>' and '(' as found in 'new List(foo);'. -sp_angle_paren = remove # ignore/add/remove/force - -# Add or remove space between '<>' and '()' as found in 'new List();'. -sp_angle_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space between '<>' and a word as in 'List m;' or 'template static ...'. -sp_angle_word = force # ignore/add/remove/force - -# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add. -sp_angle_shift = remove # ignore/add/remove/force - -# Permit removal of the space between '>>' in 'foo >' (C++11 only). Default=False. -# sp_angle_shift cannot remove the space without this option. -sp_permit_cpp11_shift = true # false/true - -# Add or remove space before '(' of 'if', 'for', 'switch', 'while', etc. -sp_before_sparen = force # ignore/add/remove/force - -# Add or remove space inside if-condition '(' and ')'. -sp_inside_sparen = remove # ignore/add/remove/force - -# Add or remove space before if-condition ')'. Overrides sp_inside_sparen. -sp_inside_sparen_close = ignore # ignore/add/remove/force - -# Add or remove space after if-condition '('. Overrides sp_inside_sparen. -sp_inside_sparen_open = ignore # ignore/add/remove/force - -# Add or remove space after ')' of 'if', 'for', 'switch', and 'while', etc. -sp_after_sparen = ignore # ignore/add/remove/force - -# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while', etc. -sp_sparen_brace = ignore # ignore/add/remove/force - -# Add or remove space between 'invariant' and '(' in the D language. -sp_invariant_paren = ignore # ignore/add/remove/force - -# Add or remove space after the ')' in 'invariant (C) c' in the D language. -sp_after_invariant_paren = ignore # ignore/add/remove/force - -# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. -sp_special_semi = remove # ignore/add/remove/force - -# Add or remove space before ';'. Default=Remove. -sp_before_semi = remove # ignore/add/remove/force - -# Add or remove space before ';' in non-empty 'for' statements. -sp_before_semi_for = remove # ignore/add/remove/force - -# Add or remove space before a semicolon of an empty part of a for statement. -sp_before_semi_for_empty = remove # ignore/add/remove/force - -# Add or remove space after ';', except when followed by a comment. Default=Add. -sp_after_semi = force # ignore/add/remove/force - -# Add or remove space after ';' in non-empty 'for' statements. Default=Force. -sp_after_semi_for = force # ignore/add/remove/force - -# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; ). -sp_after_semi_for_empty = remove # ignore/add/remove/force - -# Add or remove space before '[' (except '[]'). -sp_before_square = remove # ignore/add/remove/force - -# Add or remove space before '[]'. -sp_before_squares = remove # ignore/add/remove/force - -# Add or remove space inside a non-empty '[' and ']'. -sp_inside_square = remove # ignore/add/remove/force - -# Add or remove space after ',', 'a,b' vs 'a, b'. -sp_after_comma = force # ignore/add/remove/force - -# Add or remove space before ','. Default=Remove. -sp_before_comma = remove # ignore/add/remove/force - -# Add or remove space between ',' and ']' in multidimensional array type 'int[,,]'. Only for C#. -sp_after_mdatype_commas = ignore # ignore/add/remove/force - -# Add or remove space between '[' and ',' in multidimensional array type 'int[,,]'. Only for C#. -sp_before_mdatype_commas = ignore # ignore/add/remove/force - -# Add or remove space between ',' in multidimensional array type 'int[,,]'. Only for C#. -sp_between_mdatype_commas = ignore # ignore/add/remove/force - -# Add or remove space between an open paren and comma: '(,' vs '( ,'. Default=Force. -sp_paren_comma = force # ignore/add/remove/force - -# Add or remove space before the variadic '...' when preceded by a non-punctuator. -sp_before_ellipsis = ignore # ignore/add/remove/force - -# Add or remove space after class ':'. -sp_after_class_colon = force # ignore/add/remove/force - -# Add or remove space before class ':'. -sp_before_class_colon = force # ignore/add/remove/force - -# Add or remove space after class constructor ':'. -sp_after_constr_colon = ignore # ignore/add/remove/force - -# Add or remove space before class constructor ':'. -sp_before_constr_colon = ignore # ignore/add/remove/force - -# Add or remove space before case ':'. Default=Remove. -sp_before_case_colon = remove # ignore/add/remove/force - -# Add or remove space between 'operator' and operator sign. -sp_after_operator = force # ignore/add/remove/force - -# Add or remove space between the operator symbol and the open paren, as in 'operator ++('. -sp_after_operator_sym = remove # ignore/add/remove/force - -# Overrides sp_after_operator_sym when the operator has no arguments, as in 'operator *()'. -sp_after_operator_sym_empty = ignore # ignore/add/remove/force - -# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a'. -sp_after_cast = force # ignore/add/remove/force - -# Add or remove spaces inside cast parens. -sp_inside_paren_cast = remove # ignore/add/remove/force - -# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)'. -sp_cpp_cast_paren = remove # ignore/add/remove/force - -# Add or remove space between 'sizeof' and '('. -sp_sizeof_paren = remove # ignore/add/remove/force - -# Add or remove space after the tag keyword (Pawn). -sp_after_tag = ignore # ignore/add/remove/force - -# Add or remove space inside enum '{' and '}'. -sp_inside_braces_enum = ignore # ignore/add/remove/force - -# Add or remove space inside struct/union '{' and '}'. -sp_inside_braces_struct = ignore # ignore/add/remove/force - -# Add or remove space after open brace in an unnamed temporary direct-list-initialization. -sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force - -# Add or remove space before close brace in an unnamed temporary direct-list-initialization. -sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force - -# Add or remove space inside an unnamed temporary direct-list-initialization. -sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force - -# Add or remove space inside '{' and '}'. -sp_inside_braces = ignore # ignore/add/remove/force - -# Add or remove space inside '{}'. -sp_inside_braces_empty = force # ignore/add/remove/force - -# Add or remove space between return type and function name -# A minimum of 1 is forced except for pointer return types. -sp_type_func = force # ignore/add/remove/force - -# Add or remove space between type and open brace of an unnamed temporary direct-list-initialization. -sp_type_brace_init_lst = ignore # ignore/add/remove/force - -# Add or remove space between function name and '(' on function declaration. -sp_func_proto_paren = remove # ignore/add/remove/force - -# Add or remove space between function name and '()' on function declaration without parameters. -sp_func_proto_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space between function name and '(' on function definition. -sp_func_def_paren = remove # ignore/add/remove/force - -# Add or remove space between function name and '()' on function definition without parameters. -sp_func_def_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space inside empty function '()'. -sp_inside_fparens = remove # ignore/add/remove/force - -# Add or remove space inside function '(' and ')'. -sp_inside_fparen = remove # ignore/add/remove/force - -# Add or remove space inside the first parens in the function type: 'void (*x)(...)'. -sp_inside_tparen = ignore # ignore/add/remove/force - -# Add or remove between the parens in the function type: 'void (*x)(...)'. -sp_after_tparen_close = ignore # ignore/add/remove/force - -# Add or remove space between ']' and '(' when part of a function call. -sp_square_fparen = remove # ignore/add/remove/force - -# Add or remove space between ')' and '{' of function. -sp_fparen_brace = force # ignore/add/remove/force - -# Java: Add or remove space between ')' and '{{' of double brace initializer. -sp_fparen_dbrace = ignore # ignore/add/remove/force - -# Add or remove space between function name and '(' on function calls. -sp_func_call_paren = remove # ignore/add/remove/force - -# Add or remove space between function name and '()' on function calls without parameters. -# If set to 'ignore' (the default), sp_func_call_paren is used. -sp_func_call_paren_empty = remove # ignore/add/remove/force - -# Add or remove space between the user function name and '(' on function calls -# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file. -sp_func_call_user_paren = ignore # ignore/add/remove/force - -# Add or remove space between a constructor/destructor and the open paren. -sp_func_class_paren = remove # ignore/add/remove/force - -# Add or remove space between a constructor without parameters or destructor and '()'. -sp_func_class_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space between 'return' and '('. -sp_return_paren = force # ignore/add/remove/force - -# Add or remove space between '__attribute__' and '('. -sp_attribute_paren = remove # ignore/add/remove/force - -# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. -sp_defined_paren = remove # ignore/add/remove/force - -# Add or remove space between 'throw' and '(' in 'throw (something)'. -sp_throw_paren = force # ignore/add/remove/force - -# Add or remove space between 'throw' and anything other than '(' as in '@throw [...];'. -sp_after_throw = ignore # ignore/add/remove/force - -# Add or remove space between 'catch' and '(' in 'catch (something) { }' -# If set to ignore, sp_before_sparen is used. -sp_catch_paren = force # ignore/add/remove/force - -# Add or remove space between 'version' and '(' in 'version (something) { }' (D language) -# If set to ignore, sp_before_sparen is used. -sp_version_paren = ignore # ignore/add/remove/force - -# Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language) -# If set to ignore, sp_before_sparen is used. -sp_scope_paren = ignore # ignore/add/remove/force - -# Add or remove space between 'super' and '(' in 'super (something)'. Default=Remove. -sp_super_paren = remove # ignore/add/remove/force - -# Add or remove space between 'this' and '(' in 'this (something)'. Default=Remove. -sp_this_paren = remove # ignore/add/remove/force - -# Add or remove space between macro and value. -sp_macro = force # ignore/add/remove/force - -# Add or remove space between macro function ')' and value. -sp_macro_func = force # ignore/add/remove/force - -# Add or remove space between 'else' and '{' if on the same line. -sp_else_brace = force # ignore/add/remove/force - -# Add or remove space between '}' and 'else' if on the same line. -sp_brace_else = force # ignore/add/remove/force - -# Add or remove space between '}' and the name of a typedef on the same line. -sp_brace_typedef = force # ignore/add/remove/force - -# Add or remove space between 'catch' and '{' if on the same line. -sp_catch_brace = force # ignore/add/remove/force - -# Add or remove space between '}' and 'catch' if on the same line. -sp_brace_catch = force # ignore/add/remove/force - -# Add or remove space between 'finally' and '{' if on the same line. -sp_finally_brace = force # ignore/add/remove/force - -# Add or remove space between '}' and 'finally' if on the same line. -sp_brace_finally = force # ignore/add/remove/force - -# Add or remove space between 'try' and '{' if on the same line. -sp_try_brace = force # ignore/add/remove/force - -# Add or remove space between get/set and '{' if on the same line. -sp_getset_brace = force # ignore/add/remove/force - -# Add or remove space between a variable and '{' for C++ uniform initialization. Default=Add. -sp_word_brace = add # ignore/add/remove/force - -# Add or remove space between a variable and '{' for a namespace. Default=Add. -sp_word_brace_ns = add # ignore/add/remove/force - -# Add or remove space before the '::' operator. -sp_before_dc = remove # ignore/add/remove/force - -# Add or remove space after the '::' operator. -sp_after_dc = remove # ignore/add/remove/force - -# Add or remove around the D named array initializer ':' operator. -sp_d_array_colon = ignore # ignore/add/remove/force - -# Add or remove space after the '!' (not) operator. Default=Remove. -sp_not = remove # ignore/add/remove/force - -# Add or remove space after the '~' (invert) operator. Default=Remove. -sp_inv = remove # ignore/add/remove/force - -# Add or remove space after the '&' (address-of) operator. Default=Remove -# This does not affect the spacing after a '&' that is part of a type. -sp_addr = remove # ignore/add/remove/force - -# Add or remove space around the '.' or '->' operators. Default=Remove. -sp_member = remove # ignore/add/remove/force - -# Add or remove space after the '*' (dereference) operator. Default=Remove -# This does not affect the spacing after a '*' that is part of a type. -sp_deref = remove # ignore/add/remove/force - -# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove. -sp_sign = remove # ignore/add/remove/force - -# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove. -sp_incdec = remove # ignore/add/remove/force - -# Add or remove space before a backslash-newline at the end of a line. Default=Add. -sp_before_nl_cont = force # ignore/add/remove/force - -# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'. -sp_after_oc_scope = ignore # ignore/add/remove/force - -# Add or remove space after the colon in message specs -# '-(int) f:(int) x;' vs '-(int) f: (int) x;'. -sp_after_oc_colon = ignore # ignore/add/remove/force - -# Add or remove space before the colon in message specs -# '-(int) f: (int) x;' vs '-(int) f : (int) x;'. -sp_before_oc_colon = ignore # ignore/add/remove/force - -# Add or remove space after the colon in immutable dictionary expression -# 'NSDictionary *test = @{@"foo" :@"bar"};'. -sp_after_oc_dict_colon = ignore # ignore/add/remove/force - -# Add or remove space before the colon in immutable dictionary expression -# 'NSDictionary *test = @{@"foo" :@"bar"};'. -sp_before_oc_dict_colon = ignore # ignore/add/remove/force - -# Add or remove space after the colon in message specs -# '[object setValue:1];' vs '[object setValue: 1];'. -sp_after_send_oc_colon = ignore # ignore/add/remove/force - -# Add or remove space before the colon in message specs -# '[object setValue:1];' vs '[object setValue :1];'. -sp_before_send_oc_colon = ignore # ignore/add/remove/force - -# Add or remove space after the (type) in message specs -# '-(int)f: (int) x;' vs '-(int)f: (int)x;'. -sp_after_oc_type = ignore # ignore/add/remove/force - -# Add or remove space after the first (type) in message specs -# '-(int) f:(int)x;' vs '-(int)f:(int)x;'. -sp_after_oc_return_type = ignore # ignore/add/remove/force - -# Add or remove space between '@selector' and '(' -# '@selector(msgName)' vs '@selector (msgName)' -# Also applies to @protocol() constructs. -sp_after_oc_at_sel = ignore # ignore/add/remove/force - -# Add or remove space between '@selector(x)' and the following word -# '@selector(foo) a:' vs '@selector(foo)a:'. -sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force - -# Add or remove space inside '@selector' parens -# '@selector(foo)' vs '@selector( foo )' -# Also applies to @protocol() constructs. -sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force - -# Add or remove space before a block pointer caret -# '^int (int arg){...}' vs. ' ^int (int arg){...}'. -sp_before_oc_block_caret = ignore # ignore/add/remove/force - -# Add or remove space after a block pointer caret -# '^int (int arg){...}' vs. '^ int (int arg){...}'. -sp_after_oc_block_caret = ignore # ignore/add/remove/force - -# Add or remove space between the receiver and selector in a message. -# '[receiver selector ...]'. -sp_after_oc_msg_receiver = ignore # ignore/add/remove/force - -# Add or remove space after @property. -sp_after_oc_property = ignore # ignore/add/remove/force - -# Add or remove space around the ':' in 'b ? t : f'. -sp_cond_colon = ignore # ignore/add/remove/force - -# Add or remove space before the ':' in 'b ? t : f'. Overrides sp_cond_colon. -sp_cond_colon_before = ignore # ignore/add/remove/force - -# Add or remove space after the ':' in 'b ? t : f'. Overrides sp_cond_colon. -sp_cond_colon_after = ignore # ignore/add/remove/force - -# Add or remove space around the '?' in 'b ? t : f'. -sp_cond_question = force # ignore/add/remove/force - -# Add or remove space before the '?' in 'b ? t : f'. Overrides sp_cond_question. -sp_cond_question_before = ignore # ignore/add/remove/force - -# Add or remove space after the '?' in 'b ? t : f'. Overrides sp_cond_question. -sp_cond_question_after = ignore # ignore/add/remove/force - -# In the abbreviated ternary form (a ?: b), add/remove space between ? and :.'. Overrides all other sp_cond_* options. -sp_cond_ternary_short = ignore # ignore/add/remove/force - -# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here. -sp_case_label = force # ignore/add/remove/force - -# Control the space around the D '..' operator. -sp_range = ignore # ignore/add/remove/force - -# Control the spacing after ':' in 'for (TYPE VAR : EXPR)'. Only JAVA. -sp_after_for_colon = ignore # ignore/add/remove/force - -# Control the spacing before ':' in 'for (TYPE VAR : EXPR)'. Only JAVA. -sp_before_for_colon = ignore # ignore/add/remove/force - -# Control the spacing in 'extern (C)' (D). -sp_extern_paren = ignore # ignore/add/remove/force - -# Control the space after the opening of a C++ comment '// A' vs '//A'. -sp_cmt_cpp_start = force # ignore/add/remove/force - -# True: If space is added with sp_cmt_cpp_start, do it after doxygen sequences like '///', '///<', '//!' and '//!<'. -sp_cmt_cpp_doxygen = true # false/true - -# True: If space is added with sp_cmt_cpp_start, do it after Qt translator or meta-data comments like '//:', '//=', and '//~'. -sp_cmt_cpp_qttr = false # false/true - -# Controls the spaces between #else or #endif and a trailing comment. -sp_endif_cmt = force # ignore/add/remove/force - -# Controls the spaces after 'new', 'delete' and 'delete[]'. -sp_after_new = force # ignore/add/remove/force - -# Controls the spaces between new and '(' in 'new()'. -sp_between_new_paren = ignore # ignore/add/remove/force - -# Controls the spaces between ')' and 'type' in 'new(foo) BAR'. -sp_after_newop_paren = ignore # ignore/add/remove/force - -# Controls the spaces inside paren of the new operator: 'new(foo) BAR'. -sp_inside_newop_paren = ignore # ignore/add/remove/force - -# Controls the space after open paren of the new operator: 'new(foo) BAR'. -# Overrides sp_inside_newop_paren. -sp_inside_newop_paren_open = ignore # ignore/add/remove/force - -# Controls the space before close paren of the new operator: 'new(foo) BAR'. -# Overrides sp_inside_newop_paren. -sp_inside_newop_paren_close = ignore # ignore/add/remove/force - -# Controls the spaces before a trailing or embedded comment. -sp_before_tr_emb_cmt = force # ignore/add/remove/force - -# Number of spaces before a trailing or embedded comment. -sp_num_before_tr_emb_cmt = 2 # unsigned number - -# Control space between a Java annotation and the open paren. -sp_annotation_paren = ignore # ignore/add/remove/force - -# If True, vbrace tokens are dropped to the previous token and skipped. -sp_skip_vbrace_tokens = false # false/true - -# If True, a is inserted after #define. -force_tab_after_define = false # false/true - -# -# Indenting -# - -# The number of columns to indent per level. -# Usually 2, 3, 4, or 8. Default=8. -indent_columns = 4 # unsigned number - -# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents. -# For FreeBSD, this is set to 4. Negative value is absolute and not increased for each '(' level. -indent_continue = 0 # number - -# The continuation indent for func_*_param if they are true. -# If non-zero, this overrides the indent. -indent_param = 0 # unsigned number - -# How to use tabs when indenting code -# 0=spaces only -# 1=indent with tabs to brace level, align with spaces (default) -# 2=indent and align with tabs, using spaces when not on a tabstop -indent_with_tabs = 0 # unsigned number - -# Comments that are not a brace level are indented with tabs on a tabstop. -# Requires indent_with_tabs=2. If false, will use spaces. -indent_cmt_with_tabs = false # false/true - -# Whether to indent strings broken by '\' so that they line up. -indent_align_string = false # false/true - -# The number of spaces to indent multi-line XML strings. -# Requires indent_align_string=True. -indent_xml_string = 0 # unsigned number - -# Spaces to indent '{' from level. -indent_brace = 0 # unsigned number - -# Whether braces are indented to the body level. -indent_braces = false # false/true - -# Disabled indenting function braces if indent_braces is True. -indent_braces_no_func = false # false/true - -# Disabled indenting class braces if indent_braces is True. -indent_braces_no_class = false # false/true - -# Disabled indenting struct braces if indent_braces is True. -indent_braces_no_struct = false # false/true - -# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. -indent_brace_parent = false # false/true - -# Indent based on the paren open instead of the brace open in '({\n', default is to indent by brace. -indent_paren_open_brace = false # false/true - -# indent a C# delegate by another level, default is to not indent by another level. -indent_cs_delegate_brace = false # false/true - -# Whether the 'namespace' body is indented. -indent_namespace = false # false/true - -# Only indent one namespace and no sub-namespaces. -# Requires indent_namespace=True. -indent_namespace_single_indent = false # false/true - -# The number of spaces to indent a namespace block. -indent_namespace_level = 0 # unsigned number - -# If the body of the namespace is longer than this number, it won't be indented. -# Requires indent_namespace=True. Default=0 (no limit) -indent_namespace_limit = 0 # unsigned number - -# Whether the 'extern "C"' body is indented. -indent_extern = false # false/true - -# Whether the 'class' body is indented. -indent_class = true # false/true - -# Whether to indent the stuff after a leading base class colon. -indent_class_colon = false # false/true - -# Indent based on a class colon instead of the stuff after the colon. -# Requires indent_class_colon=True. Default=False. -indent_class_on_colon = false # false/true - -# Whether to indent the stuff after a leading class initializer colon. -indent_constr_colon = false # false/true - -# Virtual indent from the ':' for member initializers. Default=2. -indent_ctor_init_leading = 2 # unsigned number - -# Additional indent for constructor initializer list. -# Negative values decrease indent down to the first column. Default=0. -indent_ctor_init = 0 # number - -# False=treat 'else\nif' as 'else if' for indenting purposes -# True=indent the 'if' one level. -indent_else_if = false # false/true - -# Amount to indent variable declarations after a open brace. neg=relative, pos=absolute. -indent_var_def_blk = 0 # number - -# Indent continued variable declarations instead of aligning. -indent_var_def_cont = false # false/true - -# Indent continued shift expressions ('<<' and '>>') instead of aligning. -# Turn align_left_shift off when enabling this. -indent_shift = false # false/true - -# True: force indentation of function definition to start in column 1 -# False: use the default behavior. -indent_func_def_force_col1 = false # false/true - -# True: indent continued function call parameters one indent level -# False: align parameters under the open paren. -indent_func_call_param = false # false/true - -# Same as indent_func_call_param, but for function defs. -indent_func_def_param = false # false/true - -# Same as indent_func_call_param, but for function protos. -indent_func_proto_param = false # false/true - -# Same as indent_func_call_param, but for class declarations. -indent_func_class_param = false # false/true - -# Same as indent_func_call_param, but for class variable constructors. -indent_func_ctor_var_param = false # false/true - -# Same as indent_func_call_param, but for templates. -indent_template_param = false # false/true - -# Double the indent for indent_func_xxx_param options. -# Use both values of the options indent_columns and indent_param. -indent_func_param_double = false # false/true - -# Indentation column for standalone 'const' function decl/proto qualifier. -indent_func_const = 0 # unsigned number - -# Indentation column for standalone 'throw' function decl/proto qualifier. -indent_func_throw = 0 # unsigned number - -# The number of spaces to indent a continued '->' or '.' -# Usually set to 0, 1, or indent_columns. -indent_member = 4 # unsigned number - -# Spaces to indent single line ('//') comments on lines before code. -indent_sing_line_comments = 0 # unsigned number - -# If set, will indent trailing single line ('//') comments relative -# to the code instead of trying to keep the same absolute column. -indent_relative_single_line_comments = false # false/true - -# Spaces to indent 'case' from 'switch' -# Usually 0 or indent_columns. -indent_switch_case = 4 # unsigned number - -# Whether to indent preproccesor statements inside of switch statements. -indent_switch_pp = true # false/true - -# Spaces to shift the 'case' line, without affecting any other lines -# Usually 0. -indent_case_shift = 0 # unsigned number - -# Spaces to indent '{' from 'case'. -# By default, the brace will appear under the 'c' in case. -# Usually set to 0 or indent_columns. -# negative value are OK. -indent_case_brace = 0 # number - -# Whether to indent comments found in first column. -indent_col1_comment = false # false/true - -# How to indent goto labels -# >0: absolute column where 1 is the leftmost column -# <=0: subtract from brace indent -# Default=1 -indent_label = 1 # number - -# Same as indent_label, but for access specifiers that are followed by a colon. Default=1 -indent_access_spec = 1 # number - -# Indent the code after an access specifier by one level. -# If set, this option forces 'indent_access_spec=0'. -indent_access_spec_body = true # false/true - -# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended). -indent_paren_nl = false # false/true - -# Controls the indent of a close paren after a newline. -# 0: Indent to body level -# 1: Align under the open paren -# 2: Indent to the brace level -indent_paren_close = 0 # unsigned number - -# Controls the indent of the open paren of a function definition, if on it's own line.If True, indents the open paren -indent_paren_after_func_def = false # false/true - -# Controls the indent of the open paren of a function declaration, if on it's own line.If True, indents the open paren -indent_paren_after_func_decl = false # false/true - -# Controls the indent of the open paren of a function call, if on it's own line.If True, indents the open paren -indent_paren_after_func_call = false # false/true - -# Controls the indent of a comma when inside a paren.If True, aligns under the open paren. -indent_comma_paren = false # false/true - -# Controls the indent of a BOOL operator when inside a paren.If True, aligns under the open paren. -indent_bool_paren = false # false/true - -# If 'indent_bool_paren' is True, controls the indent of the first expression. If True, aligns the first expression to the following ones. -indent_first_bool_expr = true # false/true - -# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended). -indent_square_nl = false # false/true - -# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies. -indent_preserve_sql = false # false/true - -# Align continued statements at the '='. Default=True -# If False or the '=' is followed by a newline, the next line is indent one tab. -indent_align_assign = true # false/true - -# Indent OC blocks at brace level instead of usual rules. -indent_oc_block = false # false/true - -# Indent OC blocks in a message relative to the parameter name. -# 0=use indent_oc_block rules, 1+=spaces to indent -indent_oc_block_msg = 0 # unsigned number - -# Minimum indent for subsequent parameters -indent_oc_msg_colon = 0 # unsigned number - -# If True, prioritize aligning with initial colon (and stripping spaces from lines, if necessary). -# Default=True. -indent_oc_msg_prioritize_first_colon = true # false/true - -# If indent_oc_block_msg and this option are on, blocks will be indented the way that Xcode does by default (from keyword if the parameter is on its own line; otherwise, from the previous indentation level). -indent_oc_block_msg_xcode_style = false # false/true - -# If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is relative to a msg keyword. -indent_oc_block_msg_from_keyword = false # false/true - -# If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is relative to a msg colon. -indent_oc_block_msg_from_colon = false # false/true - -# If indent_oc_block_msg and this option are on, blocks will be indented from where the block caret is. -indent_oc_block_msg_from_caret = false # false/true - -# If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is. -indent_oc_block_msg_from_brace = false # false/true - -# When identing after virtual brace open and newline add further spaces to reach this min. indent. -indent_min_vbrace_open = 0 # unsigned number - -# True: When identing after virtual brace open and newline add further spaces after regular indent to reach next tabstop. -indent_vbrace_open_on_tabstop = false # false/true - -# If True, a brace followed by another token (not a newline) will indent all contained lines to match the token.Default=True. -indent_token_after_brace = true # false/true - -# If True, cpp lambda body will be indentedDefault=False. -indent_cpp_lambda_body = true # false/true - -# indent (or not) an using block if no braces are used. Only for C#.Default=True. -indent_using_block = true # false/true - -# indent the continuation of ternary operator. -# 0: (Default) off -# 1: When the `if_false` is a continuation, indent it under `if_false` -# 2: When the `:` is a continuation, indent it under `?` -indent_ternary_operator = 0 # unsigned number - -# If true, ignore indent and align for asm blocks as they have their own indentation. -indent_ignore_asm_block = false # false/true - -# -# Newline adding and removing options -# - -# Whether to collapse empty blocks between '{' and '}'. -nl_collapse_empty_body = false # false/true - -# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };'. -nl_assign_leave_one_liners = true # false/true - -# Don't split one-line braced statements inside a class xx { } body. -nl_class_leave_one_liners = true # false/true - -# Don't split one-line enums: 'enum foo { BAR = 15 };' -nl_enum_leave_one_liners = false # false/true - -# Don't split one-line get or set functions. -nl_getset_leave_one_liners = false # false/true - -# Don't split one-line function definitions - 'int foo() { return 0; }'. -nl_func_leave_one_liners = false # false/true - -# Don't split one-line C++11 lambdas - '[]() { return 0; }'. -nl_cpp_lambda_leave_one_liners = false # false/true - -# Don't split one-line if/else statements - 'if(a) b++;'. -nl_if_leave_one_liners = false # false/true - -# Don't split one-line while statements - 'while(a) b++;'. -nl_while_leave_one_liners = false # false/true - -# Don't split one-line OC messages. -nl_oc_msg_leave_one_liner = false # false/true - -# Add or remove newline between Objective-C block signature and '{'. -nl_oc_block_brace = ignore # ignore/add/remove/force - -# Add or remove newlines at the start of the file. -nl_start_of_file = ignore # ignore/add/remove/force - -# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force'. -nl_start_of_file_min = 0 # unsigned number - -# Add or remove newline at the end of the file. -nl_end_of_file = force # ignore/add/remove/force - -# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force'). -nl_end_of_file_min = 1 # unsigned number - -# Add or remove newline between '=' and '{'. -nl_assign_brace = remove # ignore/add/remove/force - -# Add or remove newline between '=' and '[' (D only). -nl_assign_square = ignore # ignore/add/remove/force - -# Add or remove newline after '= [' (D only). Will also affect the newline before the ']'. -nl_after_square_assign = ignore # ignore/add/remove/force - -# The number of blank lines after a block of variable definitions at the top of a function body -# 0 = No change (default). -nl_func_var_def_blk = 0 # unsigned number - -# The number of newlines before a block of typedefs -# 0 = No change (default) -# is overridden by the option 'nl_after_access_spec'. -nl_typedef_blk_start = 0 # unsigned number - -# The number of newlines after a block of typedefs -# 0 = No change (default). -nl_typedef_blk_end = 0 # unsigned number - -# The maximum consecutive newlines within a block of typedefs -# 0 = No change (default). -nl_typedef_blk_in = 0 # unsigned number - -# The number of newlines before a block of variable definitions not at the top of a function body -# 0 = No change (default) -# is overridden by the option 'nl_after_access_spec'. -nl_var_def_blk_start = 0 # unsigned number - -# The number of newlines after a block of variable definitions not at the top of a function body -# 0 = No change (default). -nl_var_def_blk_end = 0 # unsigned number - -# The maximum consecutive newlines within a block of variable definitions -# 0 = No change (default). -nl_var_def_blk_in = 0 # unsigned number - -# Add or remove newline between a function call's ')' and '{', as in: -# list_for_each(item, &list) { }. -nl_fcall_brace = force # ignore/add/remove/force - -# Add or remove newline between 'enum' and '{'. -nl_enum_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'enum' and 'class'. -nl_enum_class = ignore # ignore/add/remove/force - -# Add or remove newline between 'enum class' and the identifier. -nl_enum_class_identifier = ignore # ignore/add/remove/force - -# Add or remove newline between 'enum class' type and ':'. -nl_enum_identifier_colon = ignore # ignore/add/remove/force - -# Add or remove newline between 'enum class identifier :' and 'type' and/or 'type'. -nl_enum_colon_type = ignore # ignore/add/remove/force - -# Add or remove newline between 'struct and '{'. -nl_struct_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'union' and '{'. -nl_union_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'if' and '{'. -nl_if_brace = remove # ignore/add/remove/force - -# Add or remove newline between '}' and 'else'. -nl_brace_else = remove # ignore/add/remove/force - -# Add or remove newline between 'else if' and '{' -# If set to ignore, nl_if_brace is used instead. -nl_elseif_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'else' and '{'. -nl_else_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'else' and 'if'. -nl_else_if = remove # ignore/add/remove/force - -# Add or remove newline before 'if'/'else if' closing parenthesis. -nl_before_if_closing_paren = ignore # ignore/add/remove/force - -# Add or remove newline between '}' and 'finally'. -nl_brace_finally = remove # ignore/add/remove/force - -# Add or remove newline between 'finally' and '{'. -nl_finally_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'try' and '{'. -nl_try_brace = remove # ignore/add/remove/force - -# Add or remove newline between get/set and '{'. -nl_getset_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'for' and '{'. -nl_for_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'catch' and '{'. -nl_catch_brace = remove # ignore/add/remove/force - -# Add or remove newline between '}' and 'catch'. -nl_brace_catch = remove # ignore/add/remove/force - -# Add or remove newline between '}' and ']'. -nl_brace_square = ignore # ignore/add/remove/force - -# Add or remove newline between '}' and ')' in a function invocation. -nl_brace_fparen = ignore # ignore/add/remove/force - -# Add or remove newline between 'while' and '{'. -nl_while_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'scope (x)' and '{' (D). -nl_scope_brace = ignore # ignore/add/remove/force - -# Add or remove newline between 'unittest' and '{' (D). -nl_unittest_brace = ignore # ignore/add/remove/force - -# Add or remove newline between 'version (x)' and '{' (D). -nl_version_brace = ignore # ignore/add/remove/force - -# Add or remove newline between 'using' and '{'. -nl_using_brace = remove # ignore/add/remove/force - -# Add or remove newline between two open or close braces. -# Due to general newline/brace handling, REMOVE may not work. -nl_brace_brace = ignore # ignore/add/remove/force - -# Add or remove newline between 'do' and '{'. -nl_do_brace = remove # ignore/add/remove/force - -# Add or remove newline between '}' and 'while' of 'do' statement. -nl_brace_while = remove # ignore/add/remove/force - -# Add or remove newline between 'switch' and '{'. -nl_switch_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'synchronized' and '{'. -nl_synchronized_brace = ignore # ignore/add/remove/force - -# Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc. -# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and nl_catch_brace. -nl_multi_line_cond = false # false/true - -# Force a newline in a define after the macro name for multi-line defines. -nl_multi_line_define = false # false/true - -# Whether to put a newline before 'case' statement, not after the first 'case'. -nl_before_case = true # false/true - -# Add or remove newline between ')' and 'throw'. -nl_before_throw = ignore # ignore/add/remove/force - -# Whether to put a newline after 'case' statement. -nl_after_case = true # false/true - -# Add or remove a newline between a case ':' and '{'. Overrides nl_after_case. -nl_case_colon_brace = remove # ignore/add/remove/force - -# Newline between namespace and {. -nl_namespace_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'template<>' and whatever follows. -nl_template_class = add # ignore/add/remove/force - -# Add or remove newline between 'class' and '{'. -nl_class_brace = remove # ignore/add/remove/force - -# Add or remove newline before/after each ',' in the base class list, -# (tied to pos_class_comma). -nl_class_init_args = ignore # ignore/add/remove/force - -# Add or remove newline after each ',' in the constructor member initialization. -# Related to nl_constr_colon, pos_constr_colon and pos_constr_comma. -nl_constr_init_args = ignore # ignore/add/remove/force - -# Add or remove newline before first element, after comma, and after last element in enum. -nl_enum_own_lines = ignore # ignore/add/remove/force - -# Add or remove newline between return type and function name in a function definition. -nl_func_type_name = remove # ignore/add/remove/force - -# Add or remove newline between return type and function name inside a class {} -# Uses nl_func_type_name or nl_func_proto_type_name if set to ignore. -nl_func_type_name_class = remove # ignore/add/remove/force - -# Add or remove newline between class specification and '::' in 'void A::f() { }' -# Only appears in separate member implementation (does not appear with in-line implmementation). -nl_func_class_scope = ignore # ignore/add/remove/force - -# Add or remove newline between function scope and name -# Controls the newline after '::' in 'void A::f() { }'. -nl_func_scope_name = remove # ignore/add/remove/force - -# Add or remove newline between return type and function name in a prototype. -nl_func_proto_type_name = remove # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the declaration. -nl_func_paren = remove # ignore/add/remove/force - -# Overrides nl_func_paren for functions with no parameters. -nl_func_paren_empty = ignore # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the definition. -nl_func_def_paren = remove # ignore/add/remove/force - -# Overrides nl_func_def_paren for functions with no parameters. -nl_func_def_paren_empty = ignore # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the call -nl_func_call_paren = ignore # ignore/add/remove/force - -# Overrides nl_func_call_paren for functions with no parameters. -nl_func_call_paren_empty = ignore # ignore/add/remove/force - -# Add or remove newline after '(' in a function declaration. -nl_func_decl_start = remove # ignore/add/remove/force - -# Add or remove newline after '(' in a function definition. -nl_func_def_start = remove # ignore/add/remove/force - -# Overrides nl_func_decl_start when there is only one parameter. -nl_func_decl_start_single = ignore # ignore/add/remove/force - -# Overrides nl_func_def_start when there is only one parameter. -nl_func_def_start_single = ignore # ignore/add/remove/force - -# Whether to add newline after '(' in a function declaration if '(' and ')' are in different lines. -nl_func_decl_start_multi_line = false # false/true - -# Whether to add newline after '(' in a function definition if '(' and ')' are in different lines. -nl_func_def_start_multi_line = false # false/true - -# Add or remove newline after each ',' in a function declaration. -nl_func_decl_args = remove # ignore/add/remove/force - -# Add or remove newline after each ',' in a function definition. -nl_func_def_args = remove # ignore/add/remove/force - -# Whether to add newline after each ',' in a function declaration if '(' and ')' are in different lines. -nl_func_decl_args_multi_line = false # false/true - -# Whether to add newline after each ',' in a function definition if '(' and ')' are in different lines. -nl_func_def_args_multi_line = false # false/true - -# Add or remove newline before the ')' in a function declaration. -nl_func_decl_end = remove # ignore/add/remove/force - -# Add or remove newline before the ')' in a function definition. -nl_func_def_end = remove # ignore/add/remove/force - -# Overrides nl_func_decl_end when there is only one parameter. -nl_func_decl_end_single = ignore # ignore/add/remove/force - -# Overrides nl_func_def_end when there is only one parameter. -nl_func_def_end_single = ignore # ignore/add/remove/force - -# Whether to add newline before ')' in a function declaration if '(' and ')' are in different lines. -nl_func_decl_end_multi_line = false # false/true - -# Whether to add newline before ')' in a function definition if '(' and ')' are in different lines. -nl_func_def_end_multi_line = false # false/true - -# Add or remove newline between '()' in a function declaration. -nl_func_decl_empty = remove # ignore/add/remove/force - -# Add or remove newline between '()' in a function definition. -nl_func_def_empty = remove # ignore/add/remove/force - -# Add or remove newline between '()' in a function call. -nl_func_call_empty = ignore # ignore/add/remove/force - -# Whether to add newline after '(' in a function call if '(' and ')' are in different lines. -nl_func_call_start_multi_line = false # false/true - -# Whether to add newline after each ',' in a function call if '(' and ')' are in different lines. -nl_func_call_args_multi_line = false # false/true - -# Whether to add newline before ')' in a function call if '(' and ')' are in different lines. -nl_func_call_end_multi_line = false # false/true - -# Whether to put each OC message parameter on a separate line -# See nl_oc_msg_leave_one_liner. -nl_oc_msg_args = false # false/true - -# Add or remove newline between function signature and '{'. -nl_fdef_brace = remove # ignore/add/remove/force - -# Add or remove newline between C++11 lambda signature and '{'. -nl_cpp_ldef_brace = remove # ignore/add/remove/force - -# Add or remove a newline between the return keyword and return expression. -nl_return_expr = remove # ignore/add/remove/force - -# Whether to put a newline after semicolons, except in 'for' statements. -nl_after_semicolon = true # false/true - -# Java: Control the newline between the ')' and '{{' of the double brace initializer. -nl_paren_dbrace_open = ignore # ignore/add/remove/force - -# Whether to put a newline after the type in an unnamed temporary direct-list-initialization. -nl_type_brace_init_lst = ignore # ignore/add/remove/force - -# Whether to put a newline after open brace in an unnamed temporary direct-list-initialization. -nl_type_brace_init_lst_open = ignore # ignore/add/remove/force - -# Whether to put a newline before close brace in an unnamed temporary direct-list-initialization. -nl_type_brace_init_lst_close = ignore # ignore/add/remove/force - -# Whether to put a newline after brace open. -# This also adds a newline before the matching brace close. -nl_after_brace_open = true # false/true - -# If nl_after_brace_open and nl_after_brace_open_cmt are True, a newline is -# placed between the open brace and a trailing single-line comment. -nl_after_brace_open_cmt = true # false/true - -# Whether to put a newline after a virtual brace open with a non-empty body. -# These occur in un-braced if/while/do/for statement bodies. -nl_after_vbrace_open = false # false/true - -# Whether to put a newline after a virtual brace open with an empty body. -# These occur in un-braced if/while/do/for statement bodies. -nl_after_vbrace_open_empty = false # false/true - -# Whether to put a newline after a brace close. -# Does not apply if followed by a necessary ';'. -nl_after_brace_close = false # false/true - -# Whether to put a newline after a virtual brace close. -# Would add a newline before return in: 'if (foo) a++; return;'. -nl_after_vbrace_close = false # false/true - -# Control the newline between the close brace and 'b' in: 'struct { int a; } b;' -# Affects enums, unions and structures. If set to ignore, uses nl_after_brace_close. -nl_brace_struct_var = ignore # ignore/add/remove/force - -# Whether to alter newlines in '#define' macros. -nl_define_macro = false # false/true - -# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and '#endif'. Does not affect top-level #ifdefs. -nl_squeeze_ifdef = false # false/true - -# Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. -nl_squeeze_ifdef_top_level = false # false/true - -# Add or remove blank line before 'if'. -nl_before_if = force # ignore/add/remove/force - -# Add or remove blank line after 'if' statement. -# Add/Force work only if the next token is not a closing brace. -nl_after_if = force # ignore/add/remove/force - -# Add or remove blank line before 'for'. -nl_before_for = force # ignore/add/remove/force - -# Add or remove blank line after 'for' statement. -nl_after_for = force # ignore/add/remove/force - -# Add or remove blank line before 'while'. -nl_before_while = force # ignore/add/remove/force - -# Add or remove blank line after 'while' statement. -nl_after_while = force # ignore/add/remove/force - -# Add or remove blank line before 'switch'. -nl_before_switch = force # ignore/add/remove/force - -# Add or remove blank line after 'switch' statement. -nl_after_switch = force # ignore/add/remove/force - -# Add or remove blank line before 'synchronized'. -nl_before_synchronized = ignore # ignore/add/remove/force - -# Add or remove blank line after 'synchronized' statement. -nl_after_synchronized = ignore # ignore/add/remove/force - -# Add or remove blank line before 'do'. -nl_before_do = force # ignore/add/remove/force - -# Add or remove blank line after 'do/while' statement. -nl_after_do = force # ignore/add/remove/force - -# Whether to double-space commented-entries in struct/union/enum. -nl_ds_struct_enum_cmt = false # false/true - -# force nl before } of a struct/union/enum -# (lower priority than 'eat_blanks_before_close_brace'). -nl_ds_struct_enum_close_brace = false # false/true - -# Add or remove blank line before 'func_class_def'. -nl_before_func_class_def = 0 # unsigned number - -# Add or remove blank line before 'func_class_proto'. -nl_before_func_class_proto = 0 # unsigned number - -# Add or remove a newline before/after a class colon, -# (tied to pos_class_colon). -nl_class_colon = force # ignore/add/remove/force - -# Add or remove a newline around a class constructor colon. -# Related to nl_constr_init_args, pos_constr_colon and pos_constr_comma. -nl_constr_colon = ignore # ignore/add/remove/force - -# Change simple unbraced if statements into a one-liner -# 'if(b)\n i++;' => 'if(b) i++;'. -nl_create_if_one_liner = false # false/true - -# Change simple unbraced for statements into a one-liner -# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);'. -nl_create_for_one_liner = false # false/true - -# Change simple unbraced while statements into a one-liner -# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);'. -nl_create_while_one_liner = false # false/true - -# Change a one-liner if statement into simple unbraced if -# 'if(b) i++;' => 'if(b)\n i++;'. -nl_split_if_one_liner = false # false/true - -# Change a one-liner for statement into simple unbraced for -# 'for (i=0;<5;i++) foo(i);' => 'for (i=0;<5;i++)\n foo(i);'. -nl_split_for_one_liner = true # false/true - -# Change a one-liner while statement into simple unbraced while -# 'while (i<5) foo(i++);' => 'while (i<5)\n foo(i++);'. -nl_split_while_one_liner = true # false/true - -# -# Blank line options -# - -# The maximum consecutive newlines (3 = 2 blank lines). -nl_max = 2 # unsigned number - -# The maximum consecutive newlines in function. -nl_max_blank_in_func = 0 # unsigned number - -# The number of newlines after a function prototype, if followed by another function prototype. -nl_after_func_proto = 2 # unsigned number - -# The number of newlines after a function prototype, if not followed by another function prototype. -nl_after_func_proto_group = 0 # unsigned number - -# The number of newlines after a function class prototype, if followed by another function class prototype. -nl_after_func_class_proto = 0 # unsigned number - -# The number of newlines after a function class prototype, if not followed by another function class prototype. -nl_after_func_class_proto_group = 0 # unsigned number - -# The number of newlines before a multi-line function def body. -nl_before_func_body_def = 0 # unsigned number - -# The number of newlines before a multi-line function prototype body. -nl_before_func_body_proto = 0 # unsigned number - -# The number of newlines after '}' of a multi-line function body. -nl_after_func_body = 2 # unsigned number - -# The number of newlines after '}' of a multi-line function body in a class declaration. -nl_after_func_body_class = 2 # unsigned number - -# The number of newlines after '}' of a single line function body. -nl_after_func_body_one_liner = 2 # unsigned number - -# The minimum number of newlines before a multi-line comment. -# Doesn't apply if after a brace open or another multi-line comment. -nl_before_block_comment = 2 # unsigned number - -# The minimum number of newlines before a single-line C comment. -# Doesn't apply if after a brace open or other single-line C comments. -nl_before_c_comment = 2 # unsigned number - -# The minimum number of newlines before a CPP comment. -# Doesn't apply if after a brace open or other CPP comments. -nl_before_cpp_comment = 2 # unsigned number - -# Whether to force a newline after a multi-line comment. -nl_after_multiline_comment = false # false/true - -# Whether to force a newline after a label's colon. -nl_after_label_colon = false # false/true - -# The number of newlines after '}' or ';' of a struct/enum/union definition. -nl_after_struct = 2 # unsigned number - -# The number of newlines before a class definition. -nl_before_class = 0 # unsigned number - -# The number of newlines after '}' or ';' of a class definition. -nl_after_class = 2 # unsigned number - -# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. -# Will not change the newline count if after a brace open. -# 0 = No change. -nl_before_access_spec = 2 # unsigned number - -# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:' or 'slots:' label. -# 0 = No change. -# Overrides 'nl_typedef_blk_start' and 'nl_var_def_blk_start'. -nl_after_access_spec = 1 # unsigned number - -# The number of newlines between a function def and the function comment. -# 0 = No change. -nl_comment_func_def = 0 # unsigned number - -# The number of newlines after a try-catch-finally block that isn't followed by a brace close. -# 0 = No change. -nl_after_try_catch_finally = 2 # unsigned number - -# The number of newlines before and after a property, indexer or event decl. -# 0 = No change. -nl_around_cs_property = 0 # unsigned number - -# The number of newlines between the get/set/add/remove handlers in C#. -# 0 = No change. -nl_between_get_set = 0 # unsigned number - -# Add or remove newline between C# property and the '{'. -nl_property_brace = ignore # ignore/add/remove/force - -# Whether to remove blank lines after '{'. -eat_blanks_after_open_brace = true # false/true - -# Whether to remove blank lines before '}'. -eat_blanks_before_close_brace = true # false/true - -# How aggressively to remove extra newlines not in preproc. -# 0: No change -# 1: Remove most newlines not handled by other config -# 2: Remove all newlines and reformat completely by config -nl_remove_extra_newlines = 0 # unsigned number - -# Whether to put a blank line before 'return' statements, unless after an open brace. -nl_before_return = false # false/true - -# Whether to put a blank line after 'return' statements, unless followed by a close brace. -nl_after_return = false # false/true - -# Whether to put a newline after a Java annotation statement. -# Only affects annotations that are after a newline. -nl_after_annotation = ignore # ignore/add/remove/force - -# Controls the newline between two annotations. -nl_between_annotation = ignore # ignore/add/remove/force - -# -# Positioning options -# - -# The position of arithmetic operators in wrapped expressions. -pos_arith = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of assignment in wrapped expressions. -# Do not affect '=' followed by '{'. -pos_assign = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of boolean operators in wrapped expressions. -pos_bool = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of comparison operators in wrapped expressions. -pos_compare = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of conditional (b ? t : f) operators in wrapped expressions. -pos_conditional = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of the comma in wrapped expressions. -pos_comma = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of the comma in enum entries. -pos_enum_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of the comma in the base class list if there are more than one line, -# (tied to nl_class_init_args). -pos_class_comma = lead_force # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of the comma in the constructor initialization list. -# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. -pos_constr_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of trailing/leading class colon, between class and base class list -# (tied to nl_class_colon). -pos_class_colon = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# The position of colons between constructor and member initialization, -# (tied to nl_constr_colon). -# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. -pos_constr_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force - -# -# Line Splitting options -# - -# Try to limit code width to N number of columns -code_width = 120 # unsigned number - -# Whether to fully split long 'for' statements at semi-colons. -ls_for_split_full = true # false/true - -# Whether to fully split long function protos/calls at commas. -ls_func_split_full = false # false/true - -# Whether to split lines as close to code_width as possible and ignore some groupings. -ls_code_width = false # false/true - -# -# Code alignment (not left column spaces/tabs) -# - -# Whether to keep non-indenting tabs. -align_keep_tabs = false # false/true - -# Whether to use tabs for aligning. -align_with_tabs = false # false/true - -# Whether to bump out to the next tab when aligning. -align_on_tabstop = false # false/true - -# Whether to right-align numbers. -align_number_right = false # false/true - -# Whether to keep whitespace not required for alignment. -align_keep_extra_space = false # false/true - -# Align variable definitions in prototypes and functions. -align_func_params = true # false/true - -# The span for aligning parameter definitions in function on parameter name (0=don't align). -align_func_params_span = 0 # unsigned number - -# The threshold for aligning function parameter definitions (0=no limit). -align_func_params_thresh = 0 # unsigned number - -# The gap for aligning function parameter definitions. -align_func_params_gap = 0 # unsigned number - -# Align parameters in single-line functions that have the same name. -# The function names must already be aligned with each other. -align_same_func_call_params = false # false/true - -# The span for aligning variable definitions (0=don't align) -align_var_def_span = 0 # unsigned number - -# How to align the star in variable definitions. -# 0=Part of the type 'void * foo;' -# 1=Part of the variable 'void *foo;' -# 2=Dangling 'void *foo;' -align_var_def_star_style = 0 # unsigned number - -# How to align the '&' in variable definitions. -# 0=Part of the type -# 1=Part of the variable -# 2=Dangling -align_var_def_amp_style = 0 # unsigned number - -# The threshold for aligning variable definitions (0=no limit) -align_var_def_thresh = 0 # unsigned number - -# The gap for aligning variable definitions. -align_var_def_gap = 0 # unsigned number - -# Whether to align the colon in struct bit fields. -align_var_def_colon = false # false/true - -# align variable defs gap for bit colons. -align_var_def_colon_gap = 0 # unsigned number - -# Whether to align any attribute after the variable name. -align_var_def_attribute = true # false/true - -# Whether to align inline struct/enum/union variable definitions. -align_var_def_inline = false # false/true - -# The span for aligning on '=' in assignments (0=don't align) -align_assign_span = 0 # unsigned number - -# The threshold for aligning on '=' in assignments (0=no limit) -align_assign_thresh = 0 # unsigned number - -# The span for aligning on '=' in enums (0=don't align) -align_enum_equ_span = 0 # unsigned number - -# The threshold for aligning on '=' in enums (0=no limit) -align_enum_equ_thresh = 0 # unsigned number - -# The span for aligning class (0=don't align) -align_var_class_span = 0 # unsigned number - -# The threshold for aligning class member definitions (0=no limit). -align_var_class_thresh = 0 # unsigned number - -# The gap for aligning class member definitions. -align_var_class_gap = 0 # unsigned number - -# The span for aligning struct/union (0=don't align) -align_var_struct_span = 20 # unsigned number - -# The threshold for aligning struct/union member definitions (0=no limit) -align_var_struct_thresh = 0 # unsigned number - -# The gap for aligning struct/union member definitions. -align_var_struct_gap = 1 # unsigned number - -# The span for aligning struct initializer values (0=don't align) -align_struct_init_span = 0 # unsigned number - -# The minimum space between the type and the synonym of a typedef. -align_typedef_gap = 0 # unsigned number - -# The span for aligning single-line typedefs (0=don't align). -align_typedef_span = 0 # unsigned number - -# How to align typedef'd functions with other typedefs -# 0: Don't mix them at all -# 1: align the open paren with the types -# 2: align the function type name with the other type names -align_typedef_func = 0 # unsigned number - -# Controls the positioning of the '*' in typedefs. Just try it. -# 0: Align on typedef type, ignore '*' -# 1: The '*' is part of type name: typedef int *pint; -# 2: The '*' is part of the type, but dangling: typedef int *pint; -align_typedef_star_style = 0 # unsigned number - -# Controls the positioning of the '&' in typedefs. Just try it. -# 0: Align on typedef type, ignore '&' -# 1: The '&' is part of type name: typedef int &pint; -# 2: The '&' is part of the type, but dangling: typedef int &pint; -align_typedef_amp_style = 0 # unsigned number - -# The span for aligning comments that end lines (0=don't align) -align_right_cmt_span = 2 # unsigned number - -# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment. -align_right_cmt_mix = false # false/true - -# If a trailing comment is more than this number of columns away from the text it follows, -# it will qualify for being aligned. This has to be > 0 to do anything. -align_right_cmt_gap = 1 # unsigned number - -# Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore) -align_right_cmt_at_col = 0 # unsigned number - -# The span for aligning function prototypes (0=don't align). -align_func_proto_span = 0 # unsigned number - -# Minimum gap between the return type and the function name. -align_func_proto_gap = 0 # unsigned number - -# Align function protos on the 'operator' keyword instead of what follows. -align_on_operator = false # false/true - -# Whether to mix aligning prototype and variable declarations. -# If True, align_var_def_XXX options are used instead of align_func_proto_XXX options. -align_mix_var_proto = false # false/true - -# Align single-line functions with function prototypes, uses align_func_proto_span. -align_single_line_func = false # false/true - -# Aligning the open brace of single-line functions. -# Requires align_single_line_func=True, uses align_func_proto_span. -align_single_line_brace = false # false/true - -# Gap for align_single_line_brace. -align_single_line_brace_gap = 0 # unsigned number - -# The span for aligning ObjC msg spec (0=don't align) -align_oc_msg_spec_span = 0 # unsigned number - -# Whether to align macros wrapped with a backslash and a newline. -# This will not work right if the macro contains a multi-line comment. -align_nl_cont = true # false/true - -# # Align macro functions and variables together. -align_pp_define_together = false # false/true - -# The minimum space between label and value of a preprocessor define. -align_pp_define_gap = 0 # unsigned number - -# The span for aligning on '#define' bodies (0=don't align, other=number of lines including comments between blocks) -align_pp_define_span = 0 # unsigned number - -# Align lines that start with '<<' with previous '<<'. Default=True. -align_left_shift = false # false/true - -# Align text after asm volatile () colons. -align_asm_colon = false # false/true - -# Span for aligning parameters in an Obj-C message call on the ':' (0=don't align) -align_oc_msg_colon_span = 0 # unsigned number - -# If True, always align with the first parameter, even if it is too short. -align_oc_msg_colon_first = false # false/true - -# Aligning parameters in an Obj-C '+' or '-' declaration on the ':'. -align_oc_decl_colon = false # false/true - -# -# Comment modifications -# - -# Try to wrap comments at cmt_width columns -cmt_width = 0 # unsigned number - -# Set the comment reflow mode (Default=0) -# 0: no reflowing (apart from the line wrapping due to cmt_width) -# 1: no touching at all -# 2: full reflow -cmt_reflow_mode = 1 # unsigned number - -# Whether to convert all tabs to spaces in comments. Default is to leave tabs inside comments alone, unless used for indenting. -cmt_convert_tab_to_spaces = false # false/true - -# If False, disable all multi-line comment changes, including cmt_width. keyword substitution and leading chars. -# Default=True. -cmt_indent_multi = true # false/true - -# Whether to group c-comments that look like they are in a block. -cmt_c_group = false # false/true - -# Whether to put an empty '/*' on the first line of the combined c-comment. -cmt_c_nl_start = false # false/true - -# Whether to put a newline before the closing '*/' of the combined c-comment. -cmt_c_nl_end = false # false/true - -# Whether to group cpp-comments that look like they are in a block. -cmt_cpp_group = false # false/true - -# Whether to put an empty '/*' on the first line of the combined cpp-comment. -cmt_cpp_nl_start = false # false/true - -# Whether to put a newline before the closing '*/' of the combined cpp-comment. -cmt_cpp_nl_end = false # false/true - -# Whether to change cpp-comments into c-comments. -cmt_cpp_to_c = false # false/true - -# Whether to put a star on subsequent comment lines. -cmt_star_cont = true # false/true - -# The number of spaces to insert at the start of subsequent comment lines. -cmt_sp_before_star_cont = 0 # unsigned number - -# The number of spaces to insert after the star on subsequent comment lines. -cmt_sp_after_star_cont = 0 # number - -# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of -# the comment are the same length. Default=True. -cmt_multi_check_last = false # false/true - -# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of -# the comment are the same length AND if the length is bigger as the first_len minimum. Default=4 -cmt_multi_first_len_minimum = 4 # unsigned number - -# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment. -# Will substitute $(filename) with the current file's name. -cmt_insert_file_header = "" # string - -# The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment. -# Will substitute $(filename) with the current file's name. -cmt_insert_file_footer = "" # string - -# The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment. -# Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff. -# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... }. -cmt_insert_func_header = "" # string - -# The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment. -# Will substitute $(class) with the class name. -cmt_insert_class_header = "" # string - -# The filename that contains text to insert before a Obj-C message specification if the method isn't preceded with a C/C++ comment. -# Will substitute $(message) with the function name and $(javaparam) with the javadoc @param and @return stuff. -cmt_insert_oc_msg_header = "" # string - -# If a preprocessor is encountered when stepping backwards from a function name, then -# this option decides whether the comment should be inserted. -# Affects cmt_insert_oc_msg_header, cmt_insert_func_header and cmt_insert_class_header. -cmt_insert_before_preproc = false # false/true - -# If a function is declared inline to a class definition, then -# this option decides whether the comment should be inserted. -# Affects cmt_insert_func_header. -cmt_insert_before_inlines = true # false/true - -# If the function is a constructor/destructor, then -# this option decides whether the comment should be inserted. -# Affects cmt_insert_func_header. -cmt_insert_before_ctor_dtor = false # false/true - -# -# Code modifying options (non-whitespace) -# - -# Add or remove braces on single-line 'do' statement. -mod_full_brace_do = force # ignore/add/remove/force - -# Add or remove braces on single-line 'for' statement. -mod_full_brace_for = ignore # ignore/add/remove/force - -# Add or remove braces on single-line function definitions. (Pawn). -mod_full_brace_function = force # ignore/add/remove/force - -# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'. -mod_full_brace_if = force # ignore/add/remove/force - -# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if. -# If any must be braced, they are all braced. If all can be unbraced, then the braces are removed. -mod_full_brace_if_chain = false # false/true - -# Make all if/elseif/else statements with at least one 'else' or 'else if' fully braced. -# If mod_full_brace_if_chain is used together with this option, all if-else chains will get braces, -# and simple 'if' statements will lose them (if possible). -mod_full_brace_if_chain_only = false # false/true - -# Don't remove braces around statements that span N newlines -mod_full_brace_nl = 0 # unsigned number - -# Blocks removal of braces if the parenthesis of if/for/while/.. span multiple lines. -mod_full_brace_nl_block_rem_mlcond = false # false/true - -# Add or remove braces on single-line 'while' statement. -mod_full_brace_while = ignore # ignore/add/remove/force - -# Add or remove braces on single-line 'using ()' statement. -mod_full_brace_using = force # ignore/add/remove/force - -# Add or remove unnecessary paren on 'return' statement. -mod_paren_on_return = ignore # ignore/add/remove/force - -# Whether to change optional semicolons to real semicolons. -mod_pawn_semicolon = false # false/true - -# Add parens on 'while' and 'if' statement around bools. -mod_full_paren_if_bool = true # false/true - -# Whether to remove superfluous semicolons. -mod_remove_extra_semicolon = false # false/true - -# If a function body exceeds the specified number of newlines and doesn't have a comment after -# the close brace, a comment will be added. -mod_add_long_function_closebrace_comment = 0 # unsigned number - -# If a namespace body exceeds the specified number of newlines and doesn't have a comment after -# the close brace, a comment will be added. -mod_add_long_namespace_closebrace_comment = 0 # unsigned number - -# If a class body exceeds the specified number of newlines and doesn't have a comment after -# the close brace, a comment will be added. -mod_add_long_class_closebrace_comment = 0 # unsigned number - -# If a switch body exceeds the specified number of newlines and doesn't have a comment after -# the close brace, a comment will be added. -mod_add_long_switch_closebrace_comment = 0 # unsigned number - -# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after -# the #endif, a comment will be added. -mod_add_long_ifdef_endif_comment = 0 # unsigned number - -# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after -# the #else, a comment will be added. -mod_add_long_ifdef_else_comment = 0 # unsigned number - -# If True, will sort consecutive single-line 'import' statements [Java, D]. -mod_sort_import = false # false/true - -# If True, will sort consecutive single-line 'using' statements [C#]. -mod_sort_using = false # false/true - -# If True, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C] -# This is generally a bad idea, as it may break your code. -mod_sort_include = false # false/true - -# If True, it will move a 'break' that appears after a fully braced 'case' before the close brace. -mod_move_case_break = true # false/true - -# Will add or remove the braces around a fully braced case statement. -# Will only remove the braces if there are no variable declarations in the block. -mod_case_brace = ignore # ignore/add/remove/force - -# If True, it will remove a void 'return;' that appears as the last statement in a function. -mod_remove_empty_return = false # false/true - -# If True, it will organize the properties (Obj-C). -mod_sort_oc_properties = false # false/true - -# Determines weight of class property modifier (Obj-C). -mod_sort_oc_property_class_weight = 0 # number - -# Determines weight of atomic, nonatomic (Obj-C). -mod_sort_oc_property_thread_safe_weight = 0 # number - -# Determines weight of readwrite (Obj-C). -mod_sort_oc_property_readwrite_weight = 0 # number - -# Determines weight of reference type (retain, copy, assign, weak, strong) (Obj-C). -mod_sort_oc_property_reference_weight = 0 # number - -# Determines weight of getter type (getter=) (Obj-C). -mod_sort_oc_property_getter_weight = 0 # number - -# Determines weight of setter type (setter=) (Obj-C). -mod_sort_oc_property_setter_weight = 0 # number - -# Determines weight of nullability type (nullable, nonnull, null_unspecified, null_resettable) (Obj-C). -mod_sort_oc_property_nullability_weight = 0 # number - -# -# Preprocessor options -# - -# Control indent of preprocessors inside #if blocks at brace level 0 (file-level). -pp_indent = ignore # ignore/add/remove/force - -# Whether to indent #if/#else/#endif at the brace level (True) or from column 1 (False). -pp_indent_at_level = false # false/true - -# Specifies the number of columns to indent preprocessors per level at brace level 0 (file-level). -# If pp_indent_at_level=False, specifies the number of columns to indent preprocessors per level at brace level > 0 (function-level). -# Default=1. -pp_indent_count = 1 # unsigned number - -# Add or remove space after # based on pp_level of #if blocks. -pp_space = ignore # ignore/add/remove/force - -# Sets the number of spaces added with pp_space. -pp_space_count = 0 # unsigned number - -# The indent for #region and #endregion in C# and '#pragma region' in C/C++. -pp_indent_region = 0 # number - -# Whether to indent the code between #region and #endregion. -pp_region_indent_code = false # false/true - -# If pp_indent_at_level=True, sets the indent for #if, #else and #endif when not at file-level. -# 0: indent preprocessors using output_tab_size. -# >0: column at which all preprocessors will be indented. -pp_indent_if = 0 # number - -# Control whether to indent the code between #if, #else and #endif. -pp_if_indent_code = false # false/true - -# Whether to indent '#define' at the brace level (True) or from column 1 (false). -pp_define_at_level = false # false/true - -# Whether to ignore the '#define' body while formatting. -pp_ignore_define_body = false # false/true - -# Whether to indent case statements between #if, #else, and #endif. -# Only applies to the indent of the preprocesser that the case statements directly inside of. -pp_indent_case = true # false/true - -# Whether to indent whole function definitions between #if, #else, and #endif. -# Only applies to the indent of the preprocesser that the function definition is directly inside of. -pp_indent_func_def = true # false/true - -# Whether to indent extern C blocks between #if, #else, and #endif. -# Only applies to the indent of the preprocesser that the extern block is directly inside of. -pp_indent_extern = true # false/true - -# Whether to indent braces directly inside #if, #else, and #endif. -# Only applies to the indent of the preprocesser that the braces are directly inside of. -pp_indent_brace = true # false/true - -# -# Sort includes options -# - -# The regex for include category with priority 0. -include_category_0 = "" # string - -# The regex for include category with priority 1. -include_category_1 = "" # string - -# The regex for include category with priority 2. -include_category_2 = "" # string - -# -# Use or Do not Use options -# - -# True: indent_func_call_param will be used (default) -# False: indent_func_call_param will NOT be used. -use_indent_func_call_param = true # false/true - -# The value of the indentation for a continuation line is calculate differently if the line is: -# a declaration :your case with QString fileName ... -# an assignment :your case with pSettings = new QSettings( ... -# At the second case the option value might be used twice: -# at the assignment -# at the function call (if present) -# To prevent the double use of the option value, use this option with the value 'True'. -# True: indent_continue will be used only once -# False: indent_continue will be used every time (default). -use_indent_continue_only_once = false # false/true - -# SIGNAL/SLOT Qt macros have special formatting options. See options_for_QT.cpp for details. -# Default=True. -use_options_overriding_for_qt_macros = true # false/true - -# -# Warn levels - 1: error, 2: warning (default), 3: note -# - -# Warning is given if doing tab-to-\t replacement and we have found one in a C# verbatim string literal. -warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number - -# Meaning of the settings: -# Ignore - do not do any changes -# Add - makes sure there is 1 or more space/brace/newline/etc -# Force - makes sure there is exactly 1 space/brace/newline/etc, -# behaves like Add in some contexts -# Remove - removes space/brace/newline/etc -# -# -# - Token(s) can be treated as specific type(s) with the 'set' option: -# `set tokenType tokenString [tokenString...]` -# -# Example: -# `set BOOL __AND__ __OR__` -# -# tokenTypes are defined in src/token_enum.h, use them without the -# 'CT_' prefix: 'CT_BOOL' -> 'BOOL' -# -# -# - Token(s) can be treated as type(s) with the 'type' option. -# `type tokenString [tokenString...]` -# -# Example: -# `type int c_uint_8 Rectangle` -# -# This can also be achieved with `set TYPE int c_uint_8 Rectangle` -# -# -# To embed whitespace in tokenStrings use the '\' escape character, or quote -# the tokenStrings. These quotes are supported: "'` -# -# -# - Support for the auto detection of languages through the file ending can be -# added using the 'file_ext' command. -# `file_ext langType langString [langString..]` -# -# Example: -# `file_ext CPP .ch .cxx .cpp.in` -# -# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use -# them without the 'LANG_' prefix: 'LANG_CPP' -> 'CPP' -# -# -# - Custom macro-based indentation can be set up using 'macro-open', -# 'macro-else' and 'macro-close'. -# `(macro-open | macro-else | macro-close) tokenString` -# -# Example: -# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP` -# `macro-open BEGIN_MESSAGE_MAP` -# `macro-close END_MESSAGE_MAP` -# -## option(s) with 'not default' value: 204 -#