diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1fad350 --- /dev/null +++ b/.clang-format @@ -0,0 +1,193 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +SortIncludes: false +InsertBraces: true # Control statements must have curly brackets +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: AllDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: "^ IWYU pragma:" +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: "" +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: "^<(.*)>" + Priority: 0 + - Regex: '^"(.*)"' + Priority: 1 + - Regex: "(.*)" + Priority: 2 +IncludeIsMainRegex: "(Test)?$" +IncludeIsMainSourceRegex: "" +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: "" +MacroBlockEnd: "" +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: false +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Always +ShortNamespaceLines: 1 +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +--- + diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 24189a2..4f457d1 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -2,22 +2,12 @@ "version": 4, "configurations": [ { + /* + * Full configuration is provided by CMake plugin for vscode, + * that shall be installed by user + */ "name": "Win32", - "includePath": [ - "${workspaceFolder}\\dev\\VisualStudio\\", - "${workspaceFolder}\\lwmem\\src\\include\\" - ], - "defines": [ - "WIN32", - "_DEBUG", - "UNICODE", - "_UNICODE", - "LWMEM_DEV" - ], - "compilerPath": "c:\\msys64\\mingw64\\bin\\gcc.exe", - "cStandard": "gnu17", - "cppStandard": "gnu++14", - "intelliSenseMode": "windows-gcc-x86", + "intelliSenseMode": "${default}", "configurationProvider": "ms-vscode.cmake-tools" } ] diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..6a07920 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools", + "twxs.cmake", + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 8b95413..c76ad22 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,20 +1,16 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { + /* GDB must in be in the PATH environment */ "name": "(Windows) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}\\build\\LwLibPROJECT.exe", - "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", + "program": "${command:cmake.launchTargetPath}", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", - "environment": [], - "console": "integratedTerminal" + "environment": [] } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3b59a00 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "files.associations": { + "lwevt_types.h": "c", + "lwevt_type.h": "c", + "lwevt.h": "c", + "string.h": "c", + "lwevt_opt.h": "c" + }, + "esbonio.sphinx.confDir": "" +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 309d100..7a24c4a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,19 +1,11 @@ { - "version": "2.0.0", - - /* For this builds, you need - * - * - Ninja build system - * - MSYS2 compiler with ninja support - * - C/C++ extension for VSCode - * - CMake-Tools extension for VSCode - */ + "version": "2.1.0", "tasks": [ { "type": "cppbuild", "label": "Build project", "command": "cmake", - "args": ["--build", "\"build\""], + "args": ["--build", "${command:cmake.buildDirectory}", "-j", "8"], "options": { "cwd": "${workspaceFolder}" }, @@ -27,7 +19,7 @@ "type": "shell", "label": "Re-build project", "command": "cmake", - "args": ["--build", "\"build\"", "--clean-first", "-v"], + "args": ["--build", "${command:cmake.buildDirectory}", "--clean-first", "-v", "-j", "8"], "options": { "cwd": "${workspaceFolder}" }, @@ -37,7 +29,7 @@ "type": "shell", "label": "Clean project", "command": "cmake", - "args": ["--build", "\"build\"", "--target", "clean"], + "args": ["--build", "${command:cmake.buildDirectory}", "--target", "clean"], "options": { "cwd": "${workspaceFolder}" }, @@ -46,9 +38,48 @@ { "type": "shell", "label": "Run application", - "command": "${workspaceFolder}\\build\\LwLibPROJECT.exe", + "command": "${command:cmake.launchTargetPath}", "args": [], "problemMatcher": [], }, + { + "label": "Docs: Install python plugins from requirements.txt file", + "type": "shell", + "command": "python -m pip install -r requirements.txt", + "options": { + "cwd": "${workspaceFolder}/docs" + }, + "problemMatcher": [] + }, + { + "label": "Docs: Generate html", + "type": "shell", + "command": ".\\make html", + "options": { + "cwd": "${workspaceFolder}/docs" + }, + "problemMatcher": [] + }, + { + "label": "Docs: Clean build directory", + "type": "shell", + "command": ".\\make clean", + "options": { + "cwd": "${workspaceFolder}/docs" + }, + "problemMatcher": [] + }, + { + "label": "Build all WIN32 examples", + "type": "shell", + "command": "python", + "args": [ + "build_all_examples.py" + ], + "options": { + "cwd": "${workspaceFolder}/examples/win32" + }, + "problemMatcher": [] + } ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b34703f..4133354 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ ## Develop +## v2.1.0 + +- Split CMakeLists.txt files between library and executable +- Add C++ wrapper functions +- Change license year to 2022 +- Update code style with astyle +- Fix wrong length function usage +- Add `.clang-format` draft + ## v2.0.0 - Remove `len` parameter for regions definition. Affected functions: `lwmem_assignmem` and `lwmem_assignmem_ex` diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ed7aec..89ba41f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,28 +1,46 @@ -cmake_minimum_required(VERSION 3.0.0) -project(LwLibPROJECT VERSION 0.1.0) +cmake_minimum_required(VERSION 3.22) -include(CTest) -enable_testing() +# Setup project +project(LwLibPROJECT) -add_executable(${PROJECT_NAME} - lwmem/src/lwmem/lwmem.c - lwmem/src/system/lwmem_sys_win32.c - tests/lwmem_test.c - dev/VisualStudio/main.c +if(NOT PROJECT_IS_TOP_LEVEL) + add_subdirectory(lwmem) +else() + # Set as executable + add_executable(${PROJECT_NAME}) + + # Add key executable block + target_sources(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/dev/main.cpp + ${CMAKE_CURRENT_LIST_DIR}/tests/lwmem_test.c + + # win32 port + ${CMAKE_CURRENT_LIST_DIR}/lwmem/src/system/lwmem_sys_win32.c + ) + + # Add key include paths + target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/dev ) -target_include_directories(${PROJECT_NAME} PRIVATE - dev/VisualStudio - lwmem/src/include + # Compilation definition information + target_compile_definitions(${PROJECT_NAME} PUBLIC + WIN32 + _DEBUG + CONSOLE + LWMEM_DEV ) -target_compile_definitions(${PROJECT_NAME} PRIVATE - WIN32 - _DEBUG - CONSOLE - LWMEM_DEV + # Compiler options + target_compile_options(${PROJECT_NAME} PRIVATE + -Wall + -Wextra + -Wpedantic ) -set(CPACK_PROJECT_NAME ${PROJECT_NAME}) -set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) -include(CPack) + # Add subdir with lwmem and link to the project + add_subdirectory(lwmem) + target_link_libraries(${PROJECT_NAME} lwmem) + target_link_libraries(${PROJECT_NAME} lwmem_cpp) +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..f99154c --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,40 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "Win32-Debug", + "inherits": "default", + "toolchainFile": "${sourceDir}/cmake/i686-w64-mingw32-gcc.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "Win64-Debug", + "inherits": "default", + "toolchainFile": "${sourceDir}/cmake/x86_64-w64-mingw32-gcc.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + } + ], + "buildPresets": [ + { + "name": "Win32-Debug", + "configurePreset": "Win32-Debug" + }, + { + "name": "Win64-Debug", + "configurePreset": "Win64-Debug" + } + ] +} \ No newline at end of file diff --git a/LICENSE b/LICENSE index aa60317..3702ca4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Tilen MAJERLE +Copyright (c) 2023 Tilen MAJERLE 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/README.md b/README.md index 3feb20a..4b81873 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ * Supports automotive applications * Supports advanced free/realloc algorithms to optimize memory usage * Operating system ready, thread-safe API +* C++ wrapper functions * User friendly MIT license ## Contribute diff --git a/cmake/i686-w64-mingw32-gcc.cmake b/cmake/i686-w64-mingw32-gcc.cmake new file mode 100644 index 0000000..334d580 --- /dev/null +++ b/cmake/i686-w64-mingw32-gcc.cmake @@ -0,0 +1,7 @@ +set(CMAKE_SYSTEM_NAME Windows) + +# Some default GCC settings +set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) +set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) diff --git a/cmake/x86_64-w64-mingw32-gcc.cmake b/cmake/x86_64-w64-mingw32-gcc.cmake new file mode 100644 index 0000000..1d82433 --- /dev/null +++ b/cmake/x86_64-w64-mingw32-gcc.cmake @@ -0,0 +1,7 @@ +set(CMAKE_SYSTEM_NAME Windows) + +# Some default GCC settings +set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) +set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) diff --git a/dev/VisualStudio/main.c b/dev/VisualStudio/main.c deleted file mode 100644 index bd363c5..0000000 --- a/dev/VisualStudio/main.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include "lwmem/lwmem.h" -#include -#include - -extern void lwmem_test_run(void); -extern void lwmem_test_memory_structure(void); - -int -main(void) { - lwmem_test_memory_structure(); - //lwmem_test_run(); - return 0; -} diff --git a/dev/VisualStudio/lwmem_dev.sln b/dev/lwmem_dev.sln similarity index 100% rename from dev/VisualStudio/lwmem_dev.sln rename to dev/lwmem_dev.sln diff --git a/dev/VisualStudio/lwmem_dev.vcxproj b/dev/lwmem_dev.vcxproj similarity index 96% rename from dev/VisualStudio/lwmem_dev.vcxproj rename to dev/lwmem_dev.vcxproj index 694d66a..3567e76 100644 --- a/dev/VisualStudio/lwmem_dev.vcxproj +++ b/dev/lwmem_dev.vcxproj @@ -73,7 +73,7 @@ true - ..\..\lwmem\src\include;.;$(IncludePath) + ..\lwmem\src\include;.;$(IncludePath) true @@ -143,9 +143,9 @@ - - - + + + diff --git a/dev/VisualStudio/lwmem_dev.vcxproj.filters b/dev/lwmem_dev.vcxproj.filters similarity index 84% rename from dev/VisualStudio/lwmem_dev.vcxproj.filters rename to dev/lwmem_dev.vcxproj.filters index 46dbc3b..feefc4e 100644 --- a/dev/VisualStudio/lwmem_dev.vcxproj.filters +++ b/dev/lwmem_dev.vcxproj.filters @@ -16,13 +16,13 @@ Source Files - + Source Files\LWMEM - + Source Files\LWMEM - + Source Files\Tests diff --git a/dev/VisualStudio/lwmem_opts.h b/dev/lwmem_opts.h similarity index 98% rename from dev/VisualStudio/lwmem_opts.h rename to dev/lwmem_opts.h index a03fa48..9c9bce8 100644 --- a/dev/VisualStudio/lwmem_opts.h +++ b/dev/lwmem_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/dev/main.cpp b/dev/main.cpp new file mode 100644 index 0000000..62a4871 --- /dev/null +++ b/dev/main.cpp @@ -0,0 +1,24 @@ +#include "lwmem/lwmem.h" +#include "lwmem/lwmem.hpp" +#include +#include +#include + +extern "C" void lwmem_test_run(void); +extern "C" void lwmem_test_memory_structure(void); + +/* Setup manager */ +Lwmem::LwmemLight<1024> manager; + +int +main(void) { + lwmem_test_memory_structure(); + //lwmem_test_run(); + + /* Test C++ code */ + void* ret = manager.malloc(123); + std::cout << ret << std::endl; + manager.free(ret); + + return 0; +} diff --git a/docs/api-reference/lwmem_opt.rst b/docs/api-reference/lwmem_opt.rst index f789afb..3695cf7 100644 --- a/docs/api-reference/lwmem_opt.rst +++ b/docs/api-reference/lwmem_opt.rst @@ -9,4 +9,5 @@ When any of the settings shall be modified, it shall be done in dedicated applic .. note:: Check :ref:`getting_started` for guidelines on how to create and use configuration file. -.. doxygengroup:: LWMEM_OPT \ No newline at end of file +.. doxygengroup:: LWMEM_OPT + :inner: \ No newline at end of file diff --git a/docs/changelog/index.rst b/docs/changelog/index.rst new file mode 100644 index 0000000..51b89b4 --- /dev/null +++ b/docs/changelog/index.rst @@ -0,0 +1,6 @@ +.. _changelof: + +Changelog +========= + +.. literalinclude:: ../../CHANGELOG.md diff --git a/docs/conf.py b/docs/conf.py index 1ced558..032fb7c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,15 +23,25 @@ # -- Project information ----------------------------------------------------- project = 'LwMEM' -copyright = '2020, Tilen MAJERLE' +copyright = '2022, Tilen MAJERLE' author = 'Tilen MAJERLE' # Try to get branch at which this is running # and try to determine which version to display in sphinx -# Version is using git tag if on master or "latest-develop" if on develop branch +# Version is using git tag if on master/main or "latest-develop" if on develop branch version = '' git_branch = '' +def cmd_exec_print(t): + print("cmd > ", t, "\n", os.popen(t).read().strip(), "\n") + +# Print demo data here +cmd_exec_print('git branch') +cmd_exec_print('git describe') +cmd_exec_print('git describe --tags') +cmd_exec_print('git describe --tags --abbrev=0') +cmd_exec_print('git describe --tags --abbrev=1') + # Get current branch res = os.popen('git branch').read().strip() for line in res.split("\n"): @@ -41,17 +51,18 @@ # Decision for display version git_branch = git_branch.replace('(HEAD detached at ', '').replace(')', '') if git_branch.find('master') >= 0 or git_branch.find('main') >= 0: - version = os.popen('git describe --tags --abbrev=0').read().strip() - if version == '': - version = 'v0.0.0' -elif git_branch.find('develop') != -1 and not (git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0): + #version = os.popen('git describe --tags --abbrev=0').read().strip() + version = 'latest-stable' +elif git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0: + version = 'branch-' + git_branch +elif git_branch == 'develop' or git_branch == 'origin/develop': version = 'latest-develop' else: - version = 'branch-' + git_branch + version = os.popen('git describe --tags --abbrev=0').read().strip() # For debugging purpose only print("GIT BRANCH: " + git_branch) -print("GIT VERSION: " + version) +print("PROJ VERSION: " + version) # -- General configuration --------------------------------------------------- @@ -115,20 +126,19 @@ html_css_files = [ 'css/common.css', 'css/custom.css', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css', ] html_js_files = [ - 'https://kit.fontawesome.com/3102794088.js' + '' ] +# Master index file master_doc = 'index' -# -# Breathe configuration -# -# -# +# --- Breathe configuration ----------------------------------------------------- breathe_projects = { "lwmem": "_build/xml/" } breathe_default_project = "lwmem" -breathe_default_members = ('members', 'undoc-members') \ No newline at end of file +breathe_default_members = ('members', 'undoc-members') +breathe_show_enumvalue_initializer = True \ No newline at end of file diff --git a/docs/examples/index.rst b/docs/examples/index.rst index 6ef4a24..905872f 100644 --- a/docs/examples/index.rst +++ b/docs/examples/index.rst @@ -5,8 +5,8 @@ Examples and demos Various examples are provided for fast library evaluation on embedded systems. These are prepared and maintained for ``2`` platforms, but could be easily extended to more platforms: -* WIN32 examples, prepared as `Visual Studio Community `_ projects -* ARM Cortex-M examples for STM32, prepared as `STM32CubeIDE `_ GCC projects +* WIN32 examples, prepared as `CMake` projects, ready for `MSYS2 GCC compiler` +* ARM Cortex-M examples for STM32, prepared as `STM32CubeIDE `_ GCC projects. These are also supported in *Visual Studio Code* through *CMake* and *ninja* build system. `Dedicated tutorial `_ is available to get started in *VSCode*. .. warning:: Library is platform independent and can be used on any platform. @@ -20,8 +20,12 @@ Therefore it has been decided to support (for purpose of examples) ``2`` platfor WIN32 ***** -Examples for *WIN32* are prepared as `Visual Studio Community `_ projects. -You can directly open project in the IDE, compile & debug. +Examples for *WIN32* are CMake-ready and *VSCode*-ready. +It utilizes CMake-presets feature to let you select the example and compile it directly. + +* Make sure you have installed GCC compiler and is in env path (you can get it through MSYS2 packet manager) +* Install ninja and cmake and make them available in the path (you can get all through MSYS2 packet manager) +* Go to *examples win32* folder, open vscode there or run cmd: ``cmake --preset `` to configure cmake and later ``cmake --build --preset `` to compile the project STM32 ***** diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index c7055a9..ac1ea31 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -13,10 +13,10 @@ Download library Library is primarly hosted on `Github `_. -You can get it with: +You can get it by: * Downloading latest release from `releases area `_ on Github -* Cloning ``master`` branch for latest stable version +* Cloning ``main`` branch for latest stable version * Cloning ``develop`` branch for latest development Download from releases @@ -34,21 +34,21 @@ This is used when you do not have yet local copy on your machine. * Make sure ``git`` is installed. * Open console and navigate to path in the system to clone repository to. Use command ``cd your_path`` -* Clone repository with one of available ``3`` options +* Clone repository with one of available options below * Run ``git clone --recurse-submodules https://github.com/MaJerle/lwmem`` command to clone entire repository, including submodules * Run ``git clone --recurse-submodules --branch develop https://github.com/MaJerle/lwmem`` to clone `development` branch, including submodules - * Run ``git clone --recurse-submodules --branch master https://github.com/MaJerle/lwmem`` to clone `latest stable` branch, including submodules + * Run ``git clone --recurse-submodules --branch main https://github.com/MaJerle/lwmem`` to clone `latest stable` branch, including submodules * Navigate to ``examples`` directory and run favourite example Update cloned to latest version """"""""""""""""""""""""""""""" -* Open console and navigate to path in the system where your resources repository is. Use command ``cd your_path`` -* Run ``git pull origin master --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``master`` branch -* Run ``git pull origin develop --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``develop`` branch -* Run ``git submodule foreach git pull origin master`` to update & merge all submodules +* Open console and navigate to path in the system where your repository is located. Use command ``cd your_path`` +* Run ``git pull origin main`` command to get latest changes on ``main`` branch +* Run ``git pull origin develop`` command to get latest changes on ``develop`` branch +* Run ``git submodule update --init --remote`` to update submodules to latest version .. note:: This is preferred option to use when you want to evaluate library and run prepared examples. diff --git a/docs/index.rst b/docs/index.rst index 6c78805..3d67aae 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,6 +26,7 @@ Features * Supports automotive applications * Supports advanced free/realloc algorithms to optimize memory usage * Operating system ready, thread-safe API +* C++ wrapper functions * User friendly MIT license Requirements @@ -58,9 +59,31 @@ Table of contents .. toctree:: :maxdepth: 2 + :caption: Contents self get-started/index user-manual/index api-reference/index examples/index + changelog/index + +.. toctree:: + :maxdepth: 2 + :caption: Other projects + :hidden: + + LwBTN - Button manager + LwDTC - DateTimeCron + LwESP - ESP-AT library + LwEVT - Event manager + LwGPS - GPS NMEA parser + LwGSM - GSM-AT library + LwJSON - JSON parser + LwMEM - Memory manager + LwOW - OneWire with UART + LwPKT - Packet protocol + LwPRINTF - Printf + LwRB - Ring buffer + LwSHELL - Shell + LwUTIL - Utility functions diff --git a/docs/requirements.txt b/docs/requirements.txt index eb5e0fd..834b1bb 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,7 +2,7 @@ breathe>=4.9.1 colorama docutils==0.16 sphinx>=3.5.1 -sphinx_rtd_theme +sphinx_rtd_theme>=1.0.0 sphinx-tabs sphinxcontrib-svg2pdfconverter sphinx-sitemap diff --git a/docs/static/dark-light/checked.svg b/docs/static/dark-light/checked.svg new file mode 100644 index 0000000..a78af82 --- /dev/null +++ b/docs/static/dark-light/checked.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/static/dark-light/common-dark-light.css b/docs/static/dark-light/common-dark-light.css new file mode 100644 index 0000000..9a2dc1d --- /dev/null +++ b/docs/static/dark-light/common-dark-light.css @@ -0,0 +1,143 @@ +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:root { + --heading-color: red; + --duration: 0.5s; + --timing: ease; +} + +*, +::before, +::after { + box-sizing: border-box; +} + +body { + margin: 0; + transition: + color var(--duration) var(--timing), + background-color var(--duration) var(--timing); + font-family: sans-serif; + font-size: 12pt; + background-color: var(--background-color); + color: var(--text-color); + display: flex; + justify-content: center; +} + +main { + margin: 1rem; + max-width: 30rem; + position: relative; +} + +h1 { + color: var(--heading-color); + text-shadow: 0.1rem 0.1rem 0.1rem var(--shadow-color); + transition: text-shadow var(--duration) var(--timing); +} + +img { + max-width: 100%; + height: auto; + transition: filter var(--duration) var(--timing); +} + +p { + line-height: 1.5; + word-wrap: break-word; + overflow-wrap: break-word; + hyphens: auto; +} + +fieldset { + border: solid 0.1rem; + box-shadow: 0.1rem 0.1rem 0.1rem var(--shadow-color); + transition: box-shadow var(--duration) var(--timing); +} + +div { + padding: 0.5rem; +} + +aside { + position: absolute; + right: 0; + padding: 0.5rem; +} + +aside:nth-of-type(1) { + top: 0; +} + +aside:nth-of-type(2) { + top: 3rem; +} + +aside:nth-of-type(3) { + top: 7rem; +} + +aside:nth-of-type(4) { + top: 12rem; +} + +#content select, +#content button, +#content input[type="text"], +#content input[type="search"] { + width: 15rem; +} + +dark-mode-toggle { + --dark-mode-toggle-remember-icon-checked: url("checked.svg"); + --dark-mode-toggle-remember-icon-unchecked: url("unchecked.svg"); + --dark-mode-toggle-remember-font: 0.75rem "Helvetica"; + --dark-mode-toggle-legend-font: bold 0.85rem "Helvetica"; + --dark-mode-toggle-label-font: 0.85rem "Helvetica"; + --dark-mode-toggle-color: var(--text-color); + --dark-mode-toggle-background-color: none; + + margin-bottom: 1.5rem; +} + +#dark-mode-toggle-1 { + --dark-mode-toggle-dark-icon: url("sun.png"); + --dark-mode-toggle-light-icon: url("moon.png"); +} + +#dark-mode-toggle-2 { + --dark-mode-toggle-dark-icon: url("sun.svg"); + --dark-mode-toggle-light-icon: url("moon.svg"); + --dark-mode-toggle-icon-size: 2rem; + --dark-mode-toggle-icon-filter: invert(100%); +} + +#dark-mode-toggle-3, +#dark-mode-toggle-4 { + --dark-mode-toggle-dark-icon: url("moon.png"); + --dark-mode-toggle-light-icon: url("sun.png"); +} + +#dark-mode-toggle-3 { + --dark-mode-toggle-remember-filter: invert(100%); +} + +#dark-mode-toggle-4 { + --dark-mode-toggle-active-mode-background-color: var(--accent-color); + --dark-mode-toggle-remember-filter: invert(100%); +} diff --git a/docs/static/dark-light/dark-mode-toggle.mjs b/docs/static/dark-light/dark-mode-toggle.mjs new file mode 100644 index 0000000..da22262 --- /dev/null +++ b/docs/static/dark-light/dark-mode-toggle.mjs @@ -0,0 +1,329 @@ +/** + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @license © 2019 Google LLC. Licensed under the Apache License, Version 2.0. +const doc = document; +const store = localStorage; +const PREFERS_COLOR_SCHEME = 'prefers-color-scheme'; +const MEDIA = 'media'; +const LIGHT = 'light'; +const DARK = 'dark'; +const MQ_DARK = `(${PREFERS_COLOR_SCHEME}:${DARK})`; +const MQ_LIGHT = `(${PREFERS_COLOR_SCHEME}:${LIGHT})`; +const LINK_REL_STYLESHEET = 'link[rel=stylesheet]'; +const REMEMBER = 'remember'; +const LEGEND = 'legend'; +const TOGGLE = 'toggle'; +const SWITCH = 'switch'; +const APPEARANCE = 'appearance'; +const PERMANENT = 'permanent'; +const MODE = 'mode'; +const COLOR_SCHEME_CHANGE = 'colorschemechange'; +const PERMANENT_COLOR_SCHEME = 'permanentcolorscheme'; +const ALL = 'all'; +const NOT_ALL = 'not all'; +const NAME = 'dark-mode-toggle'; +const DEFAULT_URL = 'https://googlechromelabs.github.io/dark-mode-toggle/demo/'; + +// See https://html.spec.whatwg.org/multipage/common-dom-interfaces.html ↵ +// #reflecting-content-attributes-in-idl-attributes. +const installStringReflection = (obj, attrName, propName = attrName) => { + Object.defineProperty(obj, propName, { + enumerable: true, + get() { + const value = this.getAttribute(attrName); + return value === null ? '' : value; + }, + set(v) { + this.setAttribute(attrName, v); + }, + }); +}; + +const installBoolReflection = (obj, attrName, propName = attrName) => { + Object.defineProperty(obj, propName, { + enumerable: true, + get() { + return this.hasAttribute(attrName); + }, + set(v) { + if (v) { + this.setAttribute(attrName, ''); + } else { + this.removeAttribute(attrName); + } + }, + }); +}; + +const template = doc.createElement('template'); +// ⚠️ Note: this is a minified version of `src/template-contents.tpl`. +// Compress the CSS with https://cssminifier.com/, then paste it here. +// eslint-disable-next-line max-len +template.innerHTML = `
`; + +export class DarkModeToggle extends HTMLElement { + static get observedAttributes() { + return [MODE, APPEARANCE, PERMANENT, LEGEND, LIGHT, DARK, REMEMBER]; + } + + constructor() { + super(); + + installStringReflection(this, MODE); + installStringReflection(this, APPEARANCE); + installStringReflection(this, LEGEND); + installStringReflection(this, LIGHT); + installStringReflection(this, DARK); + installStringReflection(this, REMEMBER); + + installBoolReflection(this, PERMANENT); + + this._darkCSS = null; + this._lightCSS = null; + + doc.addEventListener(COLOR_SCHEME_CHANGE, (event) => { + this.mode = event.detail.colorScheme; + this._updateRadios(); + this._updateCheckbox(); + }); + + doc.addEventListener(PERMANENT_COLOR_SCHEME, (event) => { + this.permanent = event.detail.permanent; + this._permanentCheckbox.checked = this.permanent; + }); + + this._initializeDOM(); + } + + _initializeDOM() { + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.appendChild(template.content.cloneNode(true)); + + // We need to support `media="(prefers-color-scheme: dark)"` (with space) + // and `media="(prefers-color-scheme:dark)"` (without space) + this._darkCSS = doc.querySelectorAll(`${LINK_REL_STYLESHEET}[${MEDIA}*=${PREFERS_COLOR_SCHEME}][${MEDIA}*="${DARK}"]`); + this._lightCSS = doc.querySelectorAll(`${LINK_REL_STYLESHEET}[${MEDIA}*=${PREFERS_COLOR_SCHEME}][${MEDIA}*="${LIGHT}"]`); + + // Get DOM references. + this._lightRadio = shadowRoot.querySelector('[part=lightRadio]'); + this._lightLabel = shadowRoot.querySelector('[part=lightLabel]'); + this._darkRadio = shadowRoot.querySelector('[part=darkRadio]'); + this._darkLabel = shadowRoot.querySelector('[part=darkLabel]'); + this._darkCheckbox = shadowRoot.querySelector('[part=toggleCheckbox]'); + this._checkboxLabel = shadowRoot.querySelector('[part=toggleLabel]'); + this._legendLabel = shadowRoot.querySelector('legend'); + this._permanentAside = shadowRoot.querySelector('aside'); + this._permanentCheckbox = + shadowRoot.querySelector('[part=permanentCheckbox]'); + this._permanentLabel = shadowRoot.querySelector('[part=permanentLabel]'); + + // Does the browser support native `prefers-color-scheme`? + const hasNativePrefersColorScheme = + matchMedia(MQ_DARK).media !== NOT_ALL; + // Listen to `prefers-color-scheme` changes. + if (hasNativePrefersColorScheme) { + matchMedia(MQ_DARK).addListener(({matches}) => { + this.mode = matches ? DARK : LIGHT; + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + }); + } + // Set initial state, giving preference to a remembered value, then the + // native value (if supported), and eventually defaulting to a light + // experience. + const rememberedValue = store.getItem(NAME); + if (rememberedValue && [DARK, LIGHT].includes(rememberedValue)) { + this.mode = rememberedValue; + this._permanentCheckbox.checked = true; + this.permanent = true; + } else if (hasNativePrefersColorScheme) { + this.mode = matchMedia(MQ_LIGHT).matches ? LIGHT : DARK; + } + if (!this.mode) { + this.mode = LIGHT; + } + if (this.permanent && !rememberedValue) { + store.setItem(NAME, this.mode); + } + + // Default to toggle appearance. + if (!this.appearance) { + this.appearance = TOGGLE; + } + + // Update the appearance to either of toggle or switch. + this._updateAppearance(); + + // Update the radios + this._updateRadios(); + + // Make the checkbox reflect the state of the radios + this._updateCheckbox(); + + // Synchronize the behavior of the radio and the checkbox. + [this._lightRadio, this._darkRadio].forEach((input) => { + input.addEventListener('change', () => { + this.mode = this._lightRadio.checked ? LIGHT : DARK; + this._updateCheckbox(); + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + }); + }); + this._darkCheckbox.addEventListener('change', () => { + this.mode = this._darkCheckbox.checked ? DARK : LIGHT; + this._updateRadios(); + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + }); + + // Make remembering the last mode optional + this._permanentCheckbox.addEventListener('change', () => { + this.permanent = this._permanentCheckbox.checked; + this._dispatchEvent(PERMANENT_COLOR_SCHEME, { + permanent: this.permanent, + }); + }); + + // Finally update the mode and let the world know what's going on + this._updateMode(); + this._dispatchEvent(COLOR_SCHEME_CHANGE, {colorScheme: this.mode}); + this._dispatchEvent(PERMANENT_COLOR_SCHEME, { + permanent: this.permanent, + }); + } + + attributeChangedCallback(name, oldValue, newValue) { + if (name === MODE) { + if (![LIGHT, DARK].includes(newValue)) { + throw new RangeError(`Allowed values: "${LIGHT}" and "${DARK}".`); + } + // Only show the dialog programmatically on devices not capable of hover + // and only if there is a label + if (matchMedia('(hover:none)').matches && this.remember) { + this._showPermanentAside(); + } + if (this.permanent) { + store.setItem(NAME, this.mode); + } + this._updateRadios(); + this._updateCheckbox(); + this._updateMode(); + } else if (name === APPEARANCE) { + if (![TOGGLE, SWITCH].includes(newValue)) { + throw new RangeError(`Allowed values: "${TOGGLE}" and "${SWITCH}".`); + } + this._updateAppearance(); + } else if (name === PERMANENT) { + if (this.permanent) { + store.setItem(NAME, this.mode); + } else { + store.removeItem(NAME); + } + this._permanentCheckbox.checked = this.permanent; + } else if (name === LEGEND) { + this._legendLabel.textContent = newValue; + } else if (name === REMEMBER) { + this._permanentLabel.textContent = newValue; + } else if (name === LIGHT) { + this._lightLabel.textContent = newValue; + if (this.mode === LIGHT) { + this._checkboxLabel.textContent = newValue; + } + } else if (name === DARK) { + this._darkLabel.textContent = newValue; + if (this.mode === DARK) { + this._checkboxLabel.textContent = newValue; + } + } + } + + _dispatchEvent(type, value) { + this.dispatchEvent(new CustomEvent(type, { + bubbles: true, + composed: true, + detail: value, + })); + } + + _updateAppearance() { + // Hide or show the light-related affordances dependent on the appearance, + // which can be "switch" or "toggle". + const appearAsToggle = this.appearance === TOGGLE; + this._lightRadio.hidden = appearAsToggle; + this._lightLabel.hidden = appearAsToggle; + this._darkRadio.hidden = appearAsToggle; + this._darkLabel.hidden = appearAsToggle; + this._darkCheckbox.hidden = !appearAsToggle; + this._checkboxLabel.hidden = !appearAsToggle; + } + + _updateRadios() { + if (this.mode === LIGHT) { + this._lightRadio.checked = true; + } else { + this._darkRadio.checked = true; + } + } + + _updateCheckbox() { + if (this.mode === LIGHT) { + this._checkboxLabel.style.setProperty(`--${NAME}-checkbox-icon`, + `var(--${NAME}-light-icon,url("${DEFAULT_URL}moon.png"))`); + this._checkboxLabel.textContent = this.light; + if (!this.light) { + this._checkboxLabel.ariaLabel = DARK; + } + this._darkCheckbox.checked = false; + } else { + this._checkboxLabel.style.setProperty(`--${NAME}-checkbox-icon`, + `var(--${NAME}-dark-icon,url("${DEFAULT_URL}sun.png"))`); + this._checkboxLabel.textContent = this.dark; + if (!this.dark) { + this._checkboxLabel.ariaLabel = LIGHT; + } + this._darkCheckbox.checked = true; + } + } + + _updateMode() { + if (this.mode === LIGHT) { + this._lightCSS.forEach((link) => { + link.media = ALL; + link.disabled = false; + }); + this._darkCSS.forEach((link) => { + link.media = NOT_ALL; + link.disabled = true; + }); + } else { + this._darkCSS.forEach((link) => { + link.media = ALL; + link.disabled = false; + }); + this._lightCSS.forEach((link) => { + link.media = NOT_ALL; + link.disabled = true; + }); + } + } + + _showPermanentAside() { + this._permanentAside.style.visibility = 'visible'; + setTimeout(() => { + this._permanentAside.style.visibility = 'hidden'; + }, 3000); + } +} + +customElements.define(NAME, DarkModeToggle); \ No newline at end of file diff --git a/docs/static/dark-light/dark.css b/docs/static/dark-light/dark.css new file mode 100644 index 0000000..6ed8cfb --- /dev/null +++ b/docs/static/dark-light/dark.css @@ -0,0 +1,36 @@ +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:root { + color-scheme: dark; /* stylelint-disable-line property-no-unknown */ + + --background-color: rgb(15 15 15); + --text-color: rgb(240 240 240); + --shadow-color: rgb(240 240 240 / 50%); + --accent-color: rgb(0 0 240 / 50%); +} + +img { + filter: grayscale(50%); +} + +.icon { + filter: invert(100%); +} + +a { + color: yellow; +} diff --git a/docs/static/dark-light/light.css b/docs/static/dark-light/light.css new file mode 100644 index 0000000..f73cf7b --- /dev/null +++ b/docs/static/dark-light/light.css @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:root { + color-scheme: light; /* stylelint-disable-line property-no-unknown */ + + --background-color: rgb(240 240 240); + --text-color: rgb(15 15 15); + --shadow-color: rgb(15 15 15 / 50%); + --accent-color: rgb(240 0 0 / 50%); +} diff --git a/docs/static/dark-light/moon.png b/docs/static/dark-light/moon.png new file mode 100644 index 0000000..0ad57d9 Binary files /dev/null and b/docs/static/dark-light/moon.png differ diff --git a/docs/static/dark-light/moon.svg b/docs/static/dark-light/moon.svg new file mode 100644 index 0000000..fad89a4 --- /dev/null +++ b/docs/static/dark-light/moon.svg @@ -0,0 +1,7 @@ + + + + moon + + + diff --git a/docs/static/dark-light/sun.png b/docs/static/dark-light/sun.png new file mode 100644 index 0000000..40c9b36 Binary files /dev/null and b/docs/static/dark-light/sun.png differ diff --git a/docs/static/dark-light/sun.svg b/docs/static/dark-light/sun.svg new file mode 100644 index 0000000..0b18941 --- /dev/null +++ b/docs/static/dark-light/sun.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/docs/static/dark-light/unchecked.svg b/docs/static/dark-light/unchecked.svg new file mode 100644 index 0000000..6702330 --- /dev/null +++ b/docs/static/dark-light/unchecked.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/lib/FreeRTOS/CMSIS_RTOS_V2/cmsis_os.h b/examples/lib/FreeRTOS/CMSIS_RTOS_V2/cmsis_os.h index 3b885bb..7eb8d8b 100644 --- a/examples/lib/FreeRTOS/CMSIS_RTOS_V2/cmsis_os.h +++ b/examples/lib/FreeRTOS/CMSIS_RTOS_V2/cmsis_os.h @@ -1,5 +1,5 @@ /* -------------------------------------------------------------------------- - * Portions Copyright 2017 STMicroelectronics International N.V. All rights reserved. + * Portions Copyright � 2017 STMicroelectronics International N.V. All rights reserved. * Portions Copyright (c) 2013-2017 ARM Limited. All rights reserved. * -------------------------------------------------------------------------- * @@ -37,7 +37,7 @@ * Control functions for short timeouts in microsecond resolution: * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec * Removed: osSignalGet - * Version 2.0.0 + * Version 2.1.0 * OS objects creation without macros (dynamic creation and resource allocation): * - added: osXxxxNew functions which replace osXxxxCreate * - added: osXxxxAttr_t structures diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/c_cpp_properties.json b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..dd16d4c --- /dev/null +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "version": 4, + "configurations": [ + { + /* + * ms-vscode.cmake-tools plugin should be installed. + * + * It provides data for C/C++ plugin, + * such as include paths, browse paths, defines, etc. + */ + "name": "STM32", + "configurationProvider": "ms-vscode.cmake-tools", + "intelliSenseMode": "${default}" + } + ] +} diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/extensions.json b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/extensions.json new file mode 100644 index 0000000..6cb8e03 --- /dev/null +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools", + "marus25.cortex-debug", + "twxs.cmake", + "dan-c-underwood.arm", + "zixuanwang.linkerscript" + ] +} \ No newline at end of file diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/launch.json b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/launch.json new file mode 100644 index 0000000..cfa57fa --- /dev/null +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Microcontroller - ST-Link", + "cwd": "${workspaceFolder}", + "type": "cortex-debug", + "executable": "${command:cmake.launchTargetPath}", //or fixed file path: build/stm32h735g-dk-led.elf + "request": "launch", //Use "attach" to connect to target w/o elf download + "servertype": "stlink", + "device": "", //MCU used, ex. "STM32H735IG" + "interface": "swd", + "serialNumber": "", //Set ST-Link ID if you use multiple at the same time + "runToMain": true, + "svdFile": "path/to/file.svd", //Path to SVD file to see registers + "v1": false, + "showDevDebugOutput": "both", + + /* Will get automatically detected if STM32CubeIDE is installed to default directory + or it can be manually provided if necessary.. */ + //"serverpath": "c:\\ST\\STM32CubeIDE_1.7.0\\STM32CubeIDE\\plugins\\com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.win32_2.0.100.202109301221\\tools\\bin\\ST-LINK_gdbserver.exe", + //"armToolchainPath": "c:\\ST\\STM32CubeIDE_1.7.0\\STM32CubeIDE\\plugins\\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_2.1.0.202105311346\\tools\\bin", + //"stm32cubeprogrammer": "c:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin", + + /* If you use external loader, add additional arguments */ + //"serverArgs": ["--extload", "path/to/ext/loader.stldr"], + } + ] +} \ No newline at end of file diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/tasks.json b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/tasks.json new file mode 100644 index 0000000..448dbf0 --- /dev/null +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/.vscode/tasks.json @@ -0,0 +1,82 @@ +{ + "version": "2.1.0", + "tasks": [ + { + "type": "cppbuild", + "label": "Build project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "-j", "8"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "Re-build project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "--clean-first", "-v", "-j", "8"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + }, + { + "type": "shell", + "label": "Clean project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "--target", "clean"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "CubeProg: Flash project (SWD)", + "command": "STM32_Programmer_CLI", + "args": [ + "--connect", + "port=swd", + "--download", "${command:cmake.launchTargetPath}", + "-hardRst" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "CubeProg: Flash project with defined serial number (SWD) - you must set serial number first", + "command": "STM32_Programmer_CLI", + "args": [ + "--connect", + "port=swd", + "sn=", + "--download", "${command:cmake.launchTargetPath}", + "-hardRst" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "CubeProg: List all available communication interfaces", + "command": "STM32_Programmer_CLI", + "args": [ + "--list", + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + ] +} diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/CMakeLists.txt b/examples/stm32/lwmem_rtos_stm32l496_discovery/CMakeLists.txt new file mode 100644 index 0000000..7859dc6 --- /dev/null +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/CMakeLists.txt @@ -0,0 +1,227 @@ +cmake_minimum_required(VERSION 3.22) + +message("Entering ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") + +# +# Core project settings +# +set(PROJ_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +project(lwmem_stm32l496g_discovery_rtos) +enable_language(C CXX ASM) +message("Build type: " ${CMAKE_BUILD_TYPE}) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +# +# Core MCU flags, CPU, instruction set and FPU setup +# +set(CPU_PARAMETERS + -mthumb + # Other parameters + # -mcpu, -mfloat, -mfloat-abi, ... + -mcpu=cortex-m4 + -mfpu=fpv4-sp-d16 + -mfloat-abi=hard +) + +# Set linker script +set(linker_script_SRC ${PROJ_PATH}/STM32CubeIDE/Debug_STM32L496AG_FLASH.ld) +set(EXECUTABLE ${CMAKE_PROJECT_NAME}) + +# +# Source files +# +set(src_freertos_SRCS + ${PROJ_PATH}/../../lib/FreeRTOS/CMSIS_RTOS_V2/cmsis_os2.c + ${PROJ_PATH}/../../lib/FreeRTOS/croutine.c + ${PROJ_PATH}/../../lib/FreeRTOS/event_groups.c + ${PROJ_PATH}/../../lib/FreeRTOS/portable/MemMang/heap_4.c + ${PROJ_PATH}/../../lib/FreeRTOS/list.c + ${PROJ_PATH}/../../lib/FreeRTOS/portable/GCC/ARM_CM4F/port.c + ${PROJ_PATH}/../../lib/FreeRTOS/queue.c + ${PROJ_PATH}/../../lib/FreeRTOS/tasks.c + ${PROJ_PATH}/../../lib/FreeRTOS/timers.c) + +set(src_lwmem_SRCS + ${PROJ_PATH}/../../../lwmem/src/lwmem/lwmem.c + ${PROJ_PATH}/../../../lwmem/src/system/lwmem_sys_cmsis_os.c) + +set(src_stm32l4xx_hal_drivers_SRCS + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c) + +set(src_user_SRCS + ${PROJ_PATH}/src/main.c + ${PROJ_PATH}/src/stm32l4xx_it.c + ${PROJ_PATH}/src/syscalls.c + ${PROJ_PATH}/src/system_stm32l4xx.c) + +set(src_startup_SRCS + ${PROJ_PATH}/STM32CubeIDE/startup/startup_stm32l496xx.s) + +# +# Include directories +# +set(include_c_DIRS + ${PROJ_PATH}/inc + ${PROJ_PATH}/../../../lwmem/src/include + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Inc + ${PROJ_PATH}/../../lib/st/CMSIS/Device/ST/STM32L4xx/Include + ${PROJ_PATH}/../../lib/st/CMSIS/Include + ${PROJ_PATH}/../../lib/FreeRTOS/include + ${PROJ_PATH}/../../lib/FreeRTOS/CMSIS_RTOS_V2 + ${PROJ_PATH}/../../lib/FreeRTOS/portable/GCC/ARM_CM4F +) +set(include_cxx_DIRS + +) +set(include_asm_DIRS + +) + +# +# Symbols definition +# +set(symbols_c_SYMB + "__weak=__attribute__((weak))" + "__packed=__attribute__((__packed__))" + "USE_FULL_LL_DRIVER" + "STM32L496xx" +) +set(symbols_cxx_SYMB + "STM32F10X_MD" + "USE_STDPERIPH_DRIVER" +) +set(symbols_asm_SYMB + +) + +# +# Link directories setup +# Must be before executable is added +# +set(link_DIRS + +) +link_directories(${EXECUTABLE} ${link_DIRS}) + +# +# Executable files +# +add_executable(${EXECUTABLE} + ${src_freertos_SRCS} + ${src_lwmem_SRCS} + ${src_stm32l4xx_hal_drivers_SRCS} + ${src_user_SRCS} + ${src_startup_SRCS}) + +# +# Add linked libraries for linker +# +set(link_LIBS + +) +target_link_libraries(${EXECUTABLE} ${link_LIBS}) + +# +# Project symbols +# +target_compile_definitions(${EXECUTABLE} PRIVATE + # Language specific only + $<$: ${symbols_c_SYMB}> + $<$: ${symbols_cxx_SYMB}> + $<$: ${symbols_asm_SYMB}> + + # Configuration specific + $<$: + DEBUG + > + $<$: > +) + +# +# Add include paths for each of the compiler +# +target_include_directories(${EXECUTABLE} PRIVATE + # Language specific only + $<$: ${include_c_DIRS}> + $<$: ${include_cxx_DIRS}> + $<$: ${include_asm_DIRS}> + + # Configuration specific + $<$: > + $<$: > +) + +# Compiler and linker options +target_compile_options(${EXECUTABLE} PRIVATE + ${CPU_PARAMETERS} + -Wall + -Wextra + -Wpedantic + -Wno-unused-parameter + $<$: + + > + $<$: + #-Wno-volatile + #-Wold-style-cast + #-Wuseless-cast + #-Wsuggest-override + > + $<$: + -x assembler-with-cpp + -MMD + -MP + > + $<$: + -Og -g3 -ggdb + > + $<$: + -Og -g0 + > +) + +# Setup linker parameters +target_link_options(${EXECUTABLE} PRIVATE + -T${linker_script_SRC} + ${CPU_PARAMETERS} + -Wl,-Map=${CMAKE_PROJECT_NAME}.map + -u _printf_float # STDIO float formatting support (remove if not used) + --specs=nosys.specs + -Wl,--start-group + -lc + -lm + -lstdc++ + -lsupc++ + -Wl,--end-group + -Wl,--print-memory-usage +) + +# Execute post-build to print size +add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_SIZE} $ +) + +# Convert output to hex and binary +add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O ihex $ ${EXECUTABLE}.hex +) + +# Convert to bin file -> add conditional check? +add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O binary $ ${EXECUTABLE}.bin +) + +message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/CMakePresets.json b/examples/stm32/lwmem_rtos_stm32l496_discovery/CMakePresets.json new file mode 100644 index 0000000..788b377 --- /dev/null +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/CMakePresets.json @@ -0,0 +1,43 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "Debug", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "RelWithDebInfo", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "Release", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "MinSizeRel", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel" + } + } + ] +} \ No newline at end of file diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/cmake/gcc-arm-none-eabi.cmake b/examples/stm32/lwmem_rtos_stm32l496_discovery/cmake/gcc-arm-none-eabi.cmake new file mode 100644 index 0000000..3577ff8 --- /dev/null +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/cmake/gcc-arm-none-eabi.cmake @@ -0,0 +1,20 @@ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +# Some default GCC settings +# arm-none-eabi- must be part of path environment +set(TOOLCHAIN_PREFIX arm-none-eabi-) +set(FLAGS "-fdata-sections -ffunction-sections --specs=nano.specs -Wl,--gc-sections") +set(CPP_FLAGS "-fno-rtti -fno-exceptions -fno-threadsafe-statics") + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc ${FLAGS}) +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++ ${FLAGS} ${CPP_FLAGS}) +set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) +set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) + +set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/lwmem_opts.h b/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/lwmem_opts.h index 0f929f3..27f8119 100644 --- a/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/lwmem_opts.h +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/lwmem_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/main.h b/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/main.h index 4bff3ec..e3fd5d3 100644 --- a/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/main.h +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/inc/main.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/stm32/lwmem_rtos_stm32l496_discovery/src/main.c b/examples/stm32/lwmem_rtos_stm32l496_discovery/src/main.c index e36eb21..0a68844 100644 --- a/examples/stm32/lwmem_rtos_stm32l496_discovery/src/main.c +++ b/examples/stm32/lwmem_rtos_stm32l496_discovery/src/main.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/stm32/lwmem_stm32l496_discovery/.vscode/c_cpp_properties.json b/examples/stm32/lwmem_stm32l496_discovery/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..dd16d4c --- /dev/null +++ b/examples/stm32/lwmem_stm32l496_discovery/.vscode/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "version": 4, + "configurations": [ + { + /* + * ms-vscode.cmake-tools plugin should be installed. + * + * It provides data for C/C++ plugin, + * such as include paths, browse paths, defines, etc. + */ + "name": "STM32", + "configurationProvider": "ms-vscode.cmake-tools", + "intelliSenseMode": "${default}" + } + ] +} diff --git a/examples/stm32/lwmem_stm32l496_discovery/.vscode/extensions.json b/examples/stm32/lwmem_stm32l496_discovery/.vscode/extensions.json new file mode 100644 index 0000000..6cb8e03 --- /dev/null +++ b/examples/stm32/lwmem_stm32l496_discovery/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools", + "marus25.cortex-debug", + "twxs.cmake", + "dan-c-underwood.arm", + "zixuanwang.linkerscript" + ] +} \ No newline at end of file diff --git a/examples/stm32/lwmem_stm32l496_discovery/.vscode/launch.json b/examples/stm32/lwmem_stm32l496_discovery/.vscode/launch.json new file mode 100644 index 0000000..cfa57fa --- /dev/null +++ b/examples/stm32/lwmem_stm32l496_discovery/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Microcontroller - ST-Link", + "cwd": "${workspaceFolder}", + "type": "cortex-debug", + "executable": "${command:cmake.launchTargetPath}", //or fixed file path: build/stm32h735g-dk-led.elf + "request": "launch", //Use "attach" to connect to target w/o elf download + "servertype": "stlink", + "device": "", //MCU used, ex. "STM32H735IG" + "interface": "swd", + "serialNumber": "", //Set ST-Link ID if you use multiple at the same time + "runToMain": true, + "svdFile": "path/to/file.svd", //Path to SVD file to see registers + "v1": false, + "showDevDebugOutput": "both", + + /* Will get automatically detected if STM32CubeIDE is installed to default directory + or it can be manually provided if necessary.. */ + //"serverpath": "c:\\ST\\STM32CubeIDE_1.7.0\\STM32CubeIDE\\plugins\\com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.win32_2.0.100.202109301221\\tools\\bin\\ST-LINK_gdbserver.exe", + //"armToolchainPath": "c:\\ST\\STM32CubeIDE_1.7.0\\STM32CubeIDE\\plugins\\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_2.1.0.202105311346\\tools\\bin", + //"stm32cubeprogrammer": "c:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin", + + /* If you use external loader, add additional arguments */ + //"serverArgs": ["--extload", "path/to/ext/loader.stldr"], + } + ] +} \ No newline at end of file diff --git a/examples/stm32/lwmem_stm32l496_discovery/.vscode/tasks.json b/examples/stm32/lwmem_stm32l496_discovery/.vscode/tasks.json new file mode 100644 index 0000000..448dbf0 --- /dev/null +++ b/examples/stm32/lwmem_stm32l496_discovery/.vscode/tasks.json @@ -0,0 +1,82 @@ +{ + "version": "2.1.0", + "tasks": [ + { + "type": "cppbuild", + "label": "Build project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "-j", "8"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "Re-build project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "--clean-first", "-v", "-j", "8"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + }, + { + "type": "shell", + "label": "Clean project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "--target", "clean"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "CubeProg: Flash project (SWD)", + "command": "STM32_Programmer_CLI", + "args": [ + "--connect", + "port=swd", + "--download", "${command:cmake.launchTargetPath}", + "-hardRst" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "CubeProg: Flash project with defined serial number (SWD) - you must set serial number first", + "command": "STM32_Programmer_CLI", + "args": [ + "--connect", + "port=swd", + "sn=", + "--download", "${command:cmake.launchTargetPath}", + "-hardRst" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "CubeProg: List all available communication interfaces", + "command": "STM32_Programmer_CLI", + "args": [ + "--list", + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + ] +} diff --git a/examples/stm32/lwmem_stm32l496_discovery/CMakeLists.txt b/examples/stm32/lwmem_stm32l496_discovery/CMakeLists.txt new file mode 100644 index 0000000..553edb4 --- /dev/null +++ b/examples/stm32/lwmem_stm32l496_discovery/CMakeLists.txt @@ -0,0 +1,211 @@ +cmake_minimum_required(VERSION 3.22) + +message("Entering ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") + +# +# Core project settings +# +set(PROJ_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +project(lwmem_stm32l496g_discovery) +enable_language(C CXX ASM) +message("Build type: " ${CMAKE_BUILD_TYPE}) + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +# +# Core MCU flags, CPU, instruction set and FPU setup +# +set(CPU_PARAMETERS + -mthumb + # Other parameters + # -mcpu, -mfloat, -mfloat-abi, ... + -mcpu=cortex-m4 + -mfpu=fpv4-sp-d16 + -mfloat-abi=hard +) + +# Set linker script +set(linker_script_SRC ${PROJ_PATH}/STM32CubeIDE/Debug_STM32L496AG_FLASH.ld) +set(EXECUTABLE ${CMAKE_PROJECT_NAME}) + +# +# Source files +# +set(src_lwmem_SRCS + ${PROJ_PATH}/../../../lwmem/src/lwmem/lwmem.c) + +set(src_stm32l4xx_hal_drivers_SRCS + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c) + +set(src_user_SRCS + ${PROJ_PATH}/src/main.c + ${PROJ_PATH}/src/stm32l4xx_it.c + ${PROJ_PATH}/src/syscalls.c + ${PROJ_PATH}/src/system_stm32l4xx.c) + +set(src_startup_SRCS + ${PROJ_PATH}/STM32CubeIDE/startup/startup_stm32l496xx.s) + +# +# Include directories +# +set(include_c_DIRS + ${PROJ_PATH}/inc + ${PROJ_PATH}/../../../lwmem/src/include + ${PROJ_PATH}/../../lib/st/STM32L4xx_HAL_Driver/Inc + ${PROJ_PATH}/../../lib/st/CMSIS/Device/ST/STM32L4xx/Include + ${PROJ_PATH}/../../lib/st/CMSIS/Include +) +set(include_cxx_DIRS + +) +set(include_asm_DIRS + +) + +# +# Symbols definition +# +set(symbols_c_SYMB + "__weak=__attribute__((weak))" + "__packed=__attribute__((__packed__))" + "USE_FULL_LL_DRIVER" + "STM32L496xx" +) +set(symbols_cxx_SYMB + "STM32F10X_MD" + "USE_STDPERIPH_DRIVER" +) +set(symbols_asm_SYMB + +) + +# +# Link directories setup +# Must be before executable is added +# +set(link_DIRS + +) +link_directories(${EXECUTABLE} ${link_DIRS}) + +# +# Executable files +# +add_executable(${EXECUTABLE} + ${src_lwmem_SRCS} + ${src_stm32l4xx_hal_drivers_SRCS} + ${src_user_SRCS} + ${src_startup_SRCS}) + +# +# Add linked libraries for linker +# +set(link_LIBS + +) +target_link_libraries(${EXECUTABLE} ${link_LIBS}) + +# +# Project symbols +# +target_compile_definitions(${EXECUTABLE} PRIVATE + # Language specific only + $<$: ${symbols_c_SYMB}> + $<$: ${symbols_cxx_SYMB}> + $<$: ${symbols_asm_SYMB}> + + # Configuration specific + $<$: + DEBUG + > + $<$: > +) + +# +# Add include paths for each of the compiler +# +target_include_directories(${EXECUTABLE} PRIVATE + # Language specific only + $<$: ${include_c_DIRS}> + $<$: ${include_cxx_DIRS}> + $<$: ${include_asm_DIRS}> + + # Configuration specific + $<$: > + $<$: > +) + +# Compiler and linker options +target_compile_options(${EXECUTABLE} PRIVATE + ${CPU_PARAMETERS} + -Wall + -Wextra + -Wpedantic + -Wno-unused-parameter + $<$: + + > + $<$: + #-Wno-volatile + #-Wold-style-cast + #-Wuseless-cast + #-Wsuggest-override + > + $<$: + -x assembler-with-cpp + -MMD + -MP + > + $<$: + -Og -g3 -ggdb + > + $<$: + -Og -g0 + > +) + +# Setup linker parameters +target_link_options(${EXECUTABLE} PRIVATE + -T${linker_script_SRC} + ${CPU_PARAMETERS} + -Wl,-Map=${CMAKE_PROJECT_NAME}.map + -u _printf_float # STDIO float formatting support (remove if not used) + --specs=nosys.specs + -Wl,--start-group + -lc + -lm + -lstdc++ + -lsupc++ + -Wl,--end-group + -Wl,--print-memory-usage +) + +# Execute post-build to print size +add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_SIZE} $ +) + +# Convert output to hex and binary +add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O ihex $ ${EXECUTABLE}.hex +) + +# Convert to bin file -> add conditional check? +add_custom_command(TARGET ${EXECUTABLE} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O binary $ ${EXECUTABLE}.bin +) + +message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") diff --git a/examples/stm32/lwmem_stm32l496_discovery/CMakePresets.json b/examples/stm32/lwmem_stm32l496_discovery/CMakePresets.json new file mode 100644 index 0000000..788b377 --- /dev/null +++ b/examples/stm32/lwmem_stm32l496_discovery/CMakePresets.json @@ -0,0 +1,43 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "Debug", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "RelWithDebInfo", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "Release", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "MinSizeRel", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel" + } + } + ] +} \ No newline at end of file diff --git a/examples/stm32/lwmem_stm32l496_discovery/cmake/gcc-arm-none-eabi.cmake b/examples/stm32/lwmem_stm32l496_discovery/cmake/gcc-arm-none-eabi.cmake new file mode 100644 index 0000000..3577ff8 --- /dev/null +++ b/examples/stm32/lwmem_stm32l496_discovery/cmake/gcc-arm-none-eabi.cmake @@ -0,0 +1,20 @@ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +# Some default GCC settings +# arm-none-eabi- must be part of path environment +set(TOOLCHAIN_PREFIX arm-none-eabi-) +set(FLAGS "-fdata-sections -ffunction-sections --specs=nano.specs -Wl,--gc-sections") +set(CPP_FLAGS "-fno-rtti -fno-exceptions -fno-threadsafe-statics") + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc ${FLAGS}) +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++ ${FLAGS} ${CPP_FLAGS}) +set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) +set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) + +set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) diff --git a/examples/stm32/lwmem_stm32l496_discovery/inc/lwmem_opts.h b/examples/stm32/lwmem_stm32l496_discovery/inc/lwmem_opts.h index 1f94312..7762a8b 100644 --- a/examples/stm32/lwmem_stm32l496_discovery/inc/lwmem_opts.h +++ b/examples/stm32/lwmem_stm32l496_discovery/inc/lwmem_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/stm32/lwmem_stm32l496_discovery/inc/main.h b/examples/stm32/lwmem_stm32l496_discovery/inc/main.h index 4bff3ec..e3fd5d3 100644 --- a/examples/stm32/lwmem_stm32l496_discovery/inc/main.h +++ b/examples/stm32/lwmem_stm32l496_discovery/inc/main.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/stm32/lwmem_stm32l496_discovery/src/main.c b/examples/stm32/lwmem_stm32l496_discovery/src/main.c index 0c47d50..e11c079 100644 --- a/examples/stm32/lwmem_stm32l496_discovery/src/main.c +++ b/examples/stm32/lwmem_stm32l496_discovery/src/main.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/win32/.vscode/c_cpp_properties.json b/examples/win32/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..4f457d1 --- /dev/null +++ b/examples/win32/.vscode/c_cpp_properties.json @@ -0,0 +1,14 @@ +{ + "version": 4, + "configurations": [ + { + /* + * Full configuration is provided by CMake plugin for vscode, + * that shall be installed by user + */ + "name": "Win32", + "intelliSenseMode": "${default}", + "configurationProvider": "ms-vscode.cmake-tools" + } + ] +} \ No newline at end of file diff --git a/examples/win32/.vscode/extensions.json b/examples/win32/.vscode/extensions.json new file mode 100644 index 0000000..6a07920 --- /dev/null +++ b/examples/win32/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools", + "twxs.cmake", + ] +} \ No newline at end of file diff --git a/examples/win32/.vscode/launch.json b/examples/win32/.vscode/launch.json new file mode 100644 index 0000000..a53089a --- /dev/null +++ b/examples/win32/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(Windows) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${command:cmake.launchTargetPath}", + "miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [] + } + ] +} \ No newline at end of file diff --git a/examples/win32/.vscode/settings.json b/examples/win32/.vscode/settings.json new file mode 100644 index 0000000..c7da4d9 --- /dev/null +++ b/examples/win32/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "files.associations": { + "lwevt_types.h": "c", + "lwevt_type.h": "c", + "lwevt.h": "c", + "string.h": "c", + "lwevt_opt.h": "c", + "cli.h": "c", + "windows.h": "c", + "lwesp_private.h": "c" + }, + "esbonio.sphinx.confDir": "" +} \ No newline at end of file diff --git a/examples/win32/.vscode/tasks.json b/examples/win32/.vscode/tasks.json new file mode 100644 index 0000000..5bc8468 --- /dev/null +++ b/examples/win32/.vscode/tasks.json @@ -0,0 +1,46 @@ +{ + "version": "2.1.0", + "tasks": [ + { + "type": "cppbuild", + "label": "Build project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "-j", "8"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "Re-build project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "--clean-first", "-v", "-j", "8"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": ["$gcc"], + }, + { + "type": "shell", + "label": "Clean project", + "command": "cmake", + "args": ["--build", "${command:cmake.buildDirectory}", "--target", "clean"], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "Run application", + "command": "${command:cmake.launchTargetPath}", + "args": [], + "problemMatcher": [], + } + ] +} \ No newline at end of file diff --git a/examples/win32/CMakeLists.txt b/examples/win32/CMakeLists.txt new file mode 100644 index 0000000..3407919 --- /dev/null +++ b/examples/win32/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.22) + +# Setup project +project(${PROJECT_NAME}) +add_executable(${PROJECT_NAME}) + +# Add source files +target_sources(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}/main.c +) + +# Add include paths +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}/ + + # Snippets + ${CMAKE_CURRENT_LIST_DIR}/../../snippets/include +) + +# Compilation definition information +target_compile_definitions(${PROJECT_NAME} PUBLIC + WIN32 + _DEBUG + CONSOLE +) + +# Compiler options +target_compile_options(${PROJECT_NAME} PRIVATE + -Wall + -Wextra + -Wpedantic +) + +# Add subdir with lwmem and link to the project +set(LWMEM_SYS_PORT "win32") +add_subdirectory("../../lwmem" lwmem) +target_link_libraries(${PROJECT_NAME} lwmem) diff --git a/examples/win32/CMakePresets.json b/examples/win32/CMakePresets.json new file mode 100644 index 0000000..0f15284 --- /dev/null +++ b/examples/win32/CMakePresets.json @@ -0,0 +1,62 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "toolchainFile": "${sourceDir}/../../cmake/i686-w64-mingw32-gcc.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "lwmem_basic", + "inherits": "default", + "cacheVariables": { + "PROJECT_NAME": "lwmem_basic" + } + }, + { + "name": "lwmem_multi_region", + "inherits": "default", + "cacheVariables": { + "PROJECT_NAME": "lwmem_multi_region" + } + }, + { + "name": "lwmem_multi_ins_multi_region", + "inherits": "default", + "cacheVariables": { + "PROJECT_NAME": "lwmem_multi_ins_multi_region" + } + }, + { + "name": "lwmem_os", + "inherits": "default", + "cacheVariables": { + "PROJECT_NAME": "lwmem_os" + } + } + ], + "buildPresets": [ + { + "name": "lwmem_basic", + "configurePreset": "lwmem_basic" + }, + { + "name": "lwmem_multi_region", + "configurePreset": "lwmem_multi_region" + }, + { + "name": "lwmem_multi_ins_multi_region", + "configurePreset": "lwmem_multi_ins_multi_region" + }, + { + "name": "lwmem_os", + "configurePreset": "lwmem_os" + } + ] +} \ No newline at end of file diff --git a/examples/win32/README.md b/examples/win32/README.md new file mode 100644 index 0000000..eba756c --- /dev/null +++ b/examples/win32/README.md @@ -0,0 +1,9 @@ +# WIN32 examples + +Examples are provided as CMake sources. +To run then, you can use VSCode or CMake directly. + +``` +cmake --preset +cmake --build --preset +``` diff --git a/examples/win32/build_all_examples.py b/examples/win32/build_all_examples.py new file mode 100644 index 0000000..9bc1747 --- /dev/null +++ b/examples/win32/build_all_examples.py @@ -0,0 +1,42 @@ +import os +import re + +# Get presets from the path +# Use cmake command line to list actual presets visible to cmake +def get_presets(): + presets = [] + resp = os.popen("cmake --list-presets").read().strip() + for line in resp.split("\n"): + l = line.strip() + r = re.findall("\"(.*)\"", l) + if r: + presets.append(r[0]) + return presets + +# Main execution +if __name__ == '__main__': + # Get all presets + failed = [] + presets = get_presets() + for preset in presets: + print("-------------------------------") + print("Configuring preset " + preset) + print("-------------------------------") + ret = os.system("cmake --preset " + preset) + if ret != 0: + print("!!!! Command failed !!!! with result code: " + str(ret)) + failed.append(preset) + print("Return: " + str(ret)) + print("-------------------------------") + print("Building preset " + preset) + print("-------------------------------") + ret = os.system("cmake --build --preset " + preset) + if ret != 0: + print("!!!! Command failed !!!! with result code: " + str(ret)) + failed.append(preset) + print("Return: " + str(ret)) + print("-------------------------------") + print("Failed presets:") + for p in failed: + print(p) + print("-------------------------------") \ No newline at end of file diff --git a/examples/win32/lwmem/lwmem.vcxproj b/examples/win32/lwmem/lwmem.vcxproj deleted file mode 100644 index 12b0fe0..0000000 --- a/examples/win32/lwmem/lwmem.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - 16.0 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E} - Win32Proj - LwMEMexamples - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - .;..\..\..\lwmem\src\include;$(IncludePath) - - - true - - - false - - - false - - - - - - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - \ No newline at end of file diff --git a/examples/win32/lwmem/lwmem.vcxproj.filters b/examples/win32/lwmem/lwmem.vcxproj.filters deleted file mode 100644 index e7e5e08..0000000 --- a/examples/win32/lwmem/lwmem.vcxproj.filters +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {9e597c89-5586-4692-864f-7152981cc7cf} - - - - - - LwMEM - - - LwMEM - - - \ No newline at end of file diff --git a/examples/win32/lwmem/lwmem_opts.h b/examples/win32/lwmem_basic/lwmem_opts.h similarity index 97% rename from examples/win32/lwmem/lwmem_opts.h rename to examples/win32/lwmem_basic/lwmem_opts.h index 1f94312..7762a8b 100644 --- a/examples/win32/lwmem/lwmem_opts.h +++ b/examples/win32/lwmem_basic/lwmem_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/win32/lwmem/main.c b/examples/win32/lwmem_basic/main.c similarity index 100% rename from examples/win32/lwmem/main.c rename to examples/win32/lwmem_basic/main.c diff --git a/examples/win32/lwmem_examples.sln b/examples/win32/lwmem_examples.sln deleted file mode 100644 index 189f567..0000000 --- a/examples/win32/lwmem_examples.sln +++ /dev/null @@ -1,61 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29418.71 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwmem", "lwmem\lwmem.vcxproj", "{85F83F03-72F0-4F31-B7D3-294DA7D64D4E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwmem_multi_ins_multi_region", "lwmem_multi_ins_multi_region\lwmem_multi_ins_multi_region.vcxproj", "{435D03A4-B3C0-4BC2-B739-542366BFBFAE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwmem_multi_region", "lwmem_multi_region\lwmem_multi_region.vcxproj", "{145E0F0F-D703-44A2-9375-7AD2E4EAB363}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwmem_os", "lwmem_os\lwmem_os.vcxproj", "{34D02135-7971-49BD-8933-88A9B27D0A86}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Debug|x64.ActiveCfg = Debug|x64 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Debug|x64.Build.0 = Debug|x64 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Debug|x86.ActiveCfg = Debug|Win32 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Debug|x86.Build.0 = Debug|Win32 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Release|x64.ActiveCfg = Release|x64 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Release|x64.Build.0 = Release|x64 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Release|x86.ActiveCfg = Release|Win32 - {85F83F03-72F0-4F31-B7D3-294DA7D64D4E}.Release|x86.Build.0 = Release|Win32 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Debug|x64.ActiveCfg = Debug|x64 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Debug|x64.Build.0 = Debug|x64 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Debug|x86.ActiveCfg = Debug|Win32 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Debug|x86.Build.0 = Debug|Win32 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Release|x64.ActiveCfg = Release|x64 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Release|x64.Build.0 = Release|x64 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Release|x86.ActiveCfg = Release|Win32 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE}.Release|x86.Build.0 = Release|Win32 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Debug|x64.ActiveCfg = Debug|x64 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Debug|x64.Build.0 = Debug|x64 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Debug|x86.ActiveCfg = Debug|Win32 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Debug|x86.Build.0 = Debug|Win32 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Release|x64.ActiveCfg = Release|x64 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Release|x64.Build.0 = Release|x64 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Release|x86.ActiveCfg = Release|Win32 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363}.Release|x86.Build.0 = Release|Win32 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Debug|x64.ActiveCfg = Debug|x64 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Debug|x64.Build.0 = Debug|x64 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Debug|x86.ActiveCfg = Debug|Win32 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Debug|x86.Build.0 = Debug|Win32 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Release|x64.ActiveCfg = Release|x64 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Release|x64.Build.0 = Release|x64 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Release|x86.ActiveCfg = Release|Win32 - {34D02135-7971-49BD-8933-88A9B27D0A86}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {301D859A-02BB-4B30-867F-ED2E18E3305B} - EndGlobalSection -EndGlobal diff --git a/examples/win32/lwmem_multi_ins_multi_region/lwmem_multi_ins_multi_region.vcxproj b/examples/win32/lwmem_multi_ins_multi_region/lwmem_multi_ins_multi_region.vcxproj deleted file mode 100644 index 9e6e480..0000000 --- a/examples/win32/lwmem_multi_ins_multi_region/lwmem_multi_ins_multi_region.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - 16.0 - {435D03A4-B3C0-4BC2-B739-542366BFBFAE} - Win32Proj - LwMEMexamples - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - .;..\..\..\lwmem\src\include;$(IncludePath) - - - true - - - false - - - false - - - - - - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - \ No newline at end of file diff --git a/examples/win32/lwmem_multi_ins_multi_region/lwmem_multi_ins_multi_region.vcxproj.filters b/examples/win32/lwmem_multi_ins_multi_region/lwmem_multi_ins_multi_region.vcxproj.filters deleted file mode 100644 index e7e5e08..0000000 --- a/examples/win32/lwmem_multi_ins_multi_region/lwmem_multi_ins_multi_region.vcxproj.filters +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {9e597c89-5586-4692-864f-7152981cc7cf} - - - - - - LwMEM - - - LwMEM - - - \ No newline at end of file diff --git a/examples/win32/lwmem_multi_ins_multi_region/lwmem_opts.h b/examples/win32/lwmem_multi_ins_multi_region/lwmem_opts.h index 1f94312..7762a8b 100644 --- a/examples/win32/lwmem_multi_ins_multi_region/lwmem_opts.h +++ b/examples/win32/lwmem_multi_ins_multi_region/lwmem_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/win32/lwmem_multi_ins_multi_region/main.c b/examples/win32/lwmem_multi_ins_multi_region/main.c index bc14e9a..ebbb7a8 100644 --- a/examples/win32/lwmem_multi_ins_multi_region/main.c +++ b/examples/win32/lwmem_multi_ins_multi_region/main.c @@ -75,6 +75,9 @@ main(void) { lw1_ptr1 = lwmem_malloc_ex(&lw1, NULL, 24); /* Allocate memory from custom LwMEM instance, any region */ lw1_ptr2 = lwmem_malloc_ex(&lw1, &lw1_regions[1], 24); /* Allocate memory from default LwMEM instance, force second region */ + (void)lw1_ptr1; + (void)lw1_ptr2; + /* Free memory after use */ lwmem_free_ex(&lw1, lw0_ptr1); lwmem_free_ex(&lw1, lw0_ptr2); diff --git a/examples/win32/lwmem_multi_region/lwmem_multi_region.vcxproj b/examples/win32/lwmem_multi_region/lwmem_multi_region.vcxproj deleted file mode 100644 index 21abf6e..0000000 --- a/examples/win32/lwmem_multi_region/lwmem_multi_region.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - 16.0 - {145E0F0F-D703-44A2-9375-7AD2E4EAB363} - Win32Proj - LwMEMexamples - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - .;..\..\..\lwmem\src\include;$(IncludePath) - - - true - - - false - - - false - - - - - - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - \ No newline at end of file diff --git a/examples/win32/lwmem_multi_region/lwmem_multi_region.vcxproj.filters b/examples/win32/lwmem_multi_region/lwmem_multi_region.vcxproj.filters deleted file mode 100644 index e7e5e08..0000000 --- a/examples/win32/lwmem_multi_region/lwmem_multi_region.vcxproj.filters +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {9e597c89-5586-4692-864f-7152981cc7cf} - - - - - - LwMEM - - - LwMEM - - - \ No newline at end of file diff --git a/examples/win32/lwmem_multi_region/lwmem_opts.h b/examples/win32/lwmem_multi_region/lwmem_opts.h index 1f94312..7762a8b 100644 --- a/examples/win32/lwmem_multi_region/lwmem_opts.h +++ b/examples/win32/lwmem_multi_region/lwmem_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/win32/lwmem_os/lwmem_opts.h b/examples/win32/lwmem_os/lwmem_opts.h index 8536f88..e86dbbe 100644 --- a/examples/win32/lwmem_os/lwmem_opts.h +++ b/examples/win32/lwmem_os/lwmem_opts.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/examples/win32/lwmem_os/lwmem_os.vcxproj b/examples/win32/lwmem_os/lwmem_os.vcxproj deleted file mode 100644 index d8064ff..0000000 --- a/examples/win32/lwmem_os/lwmem_os.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - 16.0 - {34D02135-7971-49BD-8933-88A9B27D0A86} - Win32Proj - LwMEMexamples - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - .;..\..\..\lwmem\src\include;$(IncludePath) - - - true - - - false - - - false - - - - - - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - - - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - \ No newline at end of file diff --git a/examples/win32/lwmem_os/lwmem_os.vcxproj.filters b/examples/win32/lwmem_os/lwmem_os.vcxproj.filters deleted file mode 100644 index e7e5e08..0000000 --- a/examples/win32/lwmem_os/lwmem_os.vcxproj.filters +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {9e597c89-5586-4692-864f-7152981cc7cf} - - - - - - LwMEM - - - LwMEM - - - \ No newline at end of file diff --git a/examples/win32/lwmem_os/main.c b/examples/win32/lwmem_os/main.c index a1a4733..3e82098 100644 --- a/examples/win32/lwmem_os/main.c +++ b/examples/win32/lwmem_os/main.c @@ -45,17 +45,17 @@ static int thread_func(void* arg) { void* ptr, * ptr2; + (void)arg; + /* Allocate memory */ - ptr = lwmem_malloc(24); - if (ptr == NULL) { + if ((ptr = lwmem_malloc(24)) == NULL) { printf("Could not allocate memory!\r\n"); return -1; } printf("Memory allocated at address 0x%p!\r\n", ptr); /* Increase its size */ - ptr2 = lwmem_realloc(ptr, 48); - if (ptr2 == NULL) { + if ((ptr2 = lwmem_realloc(ptr, 48)) == NULL) { printf("Could not reallocate existing ptr\r\n"); } else { printf("Memory reallocated at address 0x%p!\r\n", ptr2); diff --git a/library.json b/library.json index 972dba8..3e1f333 100644 --- a/library.json +++ b/library.json @@ -1,34 +1,33 @@ { - "name": "LwMEM", - "version": "2.0.0", - "description": "Lightweight dynamic memory manager optimized for embedded systems", - "keywords": "lwmem, memory, dynamic, heap, malloc, calloc, realloc, free, lightweight, manager, embedded, stm32, win32", - "repository": { - "type": "git", - "url": "https://github.com/MaJerle/lwmem.git" - }, - "authors": [ - { - "name": "Tilen Majerle", - "email": "tilen@majerle.eu", - "url": "https://majerle.eu" - } - ], - "license": "MIT", - "homepage": "https://github.com/MaJerle/lwmem", - "dependencies": { - - }, - "frameworks": "*", - "platforms": "*", - "export": { - "exclude": [ - ".github", - "dev" - "docs", - "**/.vs", - "**/Debug", - "build", - ] - } + "name": "LwMEM", + "version": "2.1.0", + "description": "Lightweight dynamic memory manager optimized for embedded systems", + "keywords": "lwmem, memory, dynamic, heap, malloc, calloc, realloc, free, lightweight, manager, embedded, stm32, win32", + "repository": { + "type": "git", + "url": "https://github.com/MaJerle/lwmem.git" + }, + "authors": [ + { + "name": "Tilen Majerle", + "email": "tilen@majerle.eu", + "url": "https://majerle.eu" + } + ], + "license": "MIT", + "homepage": "https://github.com/MaJerle/lwmem", + "dependencies": {}, + "frameworks": "*", + "platforms": "*", + "export": { + "exclude": [ + ".github", + "dev", + "docs", + "**/.vs", + "**/Debug", + "build", + "**/build" + ] + } } \ No newline at end of file diff --git a/lwmem/CMakeLists.txt b/lwmem/CMakeLists.txt new file mode 100644 index 0000000..ed6ca1e --- /dev/null +++ b/lwmem/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.22) + +# Debug message +message("Entering ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") + +# Register core library +add_library(lwmem INTERFACE) +target_sources(lwmem PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwmem/lwmem.c) +target_include_directories(lwmem INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) + +if (DEFINED LWMEM_SYS_PORT) +target_sources(lwmem PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/system/lwmem_sys_${LWMEM_SYS_PORT}.c) +endif() + +# Register core library with C++ extensions +add_library(lwmem_cpp INTERFACE) +target_sources(lwmem_cpp PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwmem/lwmem.cpp) +target_include_directories(lwmem_cpp INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) + +# Register other modules + +# Debug message +message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") diff --git a/lwmem/src/include/lwmem/lwmem.h b/lwmem/src/include/lwmem/lwmem.h index 90c579a..d854627 100644 --- a/lwmem/src/include/lwmem/lwmem.h +++ b/lwmem/src/include/lwmem/lwmem.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,13 +29,13 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v2.0.0 + * Version: v2.1.0 */ #ifndef LWMEM_HDR_H #define LWMEM_HDR_H -#include #include +#include #include "lwmem/lwmem_opt.h" #ifdef __cplusplus @@ -53,15 +53,15 @@ extern "C" { * \param[in] x: Object to get array size of * \return Number of elements in array */ -#define LWMEM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) +#define LWMEM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) /** * \brief Memory block structure */ typedef struct lwmem_block { - struct lwmem_block* next; /*!< Next free memory block on linked list. - Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */ - size_t size; /*!< Size of block, including metadata part. + struct lwmem_block* + next; /*!< Next free memory block on linked list. Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */ + size_t size; /*!< Size of block, including metadata part. MSB bit is set to `1` when block is allocated and in use, or `0` when block is considered free */ } lwmem_block_t; @@ -70,46 +70,53 @@ typedef struct lwmem_block { * \brief Statistics structure */ typedef struct { - uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */ - uint32_t nr_free; /*!< Number of frees in the LwMEM instance */ + uint32_t mem_size_bytes; /*!< Total memory size of all regions combined */ + uint32_t mem_available_bytes; /*!< Free memory available for allocation */ + uint32_t + minimum_ever_mem_available_bytes; /*!< Minimum amount of total free memory there has been in the heap since the system booted. */ + uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */ + uint32_t nr_free; /*!< Number of frees in the LwMEM instance */ } lwmem_stats_t; /** * \brief LwMEM main structure */ typedef struct lwmem { - lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */ - lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */ - size_t mem_available_bytes; /*!< Memory size available for allocation */ - size_t mem_regions_count; /*!< Number of regions used for allocation */ + lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */ + lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */ + size_t mem_available_bytes; /*!< Memory size available for allocation */ + size_t mem_regions_count; /*!< Number of regions used for allocation */ #if LWMEM_CFG_OS || __DOXYGEN__ - LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */ -#endif /* LWMEM_CFG_OS || __DOXYGEN__ */ + LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */ +#endif /* LWMEM_CFG_OS || __DOXYGEN__ */ #if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ - lwmem_stats_t stats; /*!< Statistics */ -#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ + lwmem_stats_t stats; /*!< Statistics */ +#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ #if defined(LWMEM_DEV) && !__DOXYGEN__ - lwmem_block_t start_block_first_use; /*!< Value of start block for very first time. + lwmem_block_t start_block_first_use; /*!< Value of start block for very first time. This is used only during validation process and is removed in final use */ -#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ +#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ } lwmem_t; /** * \brief Memory region descriptor */ typedef struct { - void* start_addr; /*!< Region start address */ - size_t size; /*!< Size of region in units of bytes */ + void* start_addr; /*!< Region start address */ + size_t size; /*!< Size of region in units of bytes */ } lwmem_region_t; -size_t lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions); -void* lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t size); -void* lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t nitems, const size_t size); -void* lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, const size_t size); -uint8_t lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const ptr, const size_t size); -void lwmem_free_ex(lwmem_t* const lw, void* const ptr); -void lwmem_free_s_ex(lwmem_t* const lw, void** const ptr); -size_t lwmem_get_size_ex(lwmem_t* const lw, void* ptr); +size_t lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions); +void* lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size); +void* lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size); +void* lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size); +uint8_t lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size); +void lwmem_free_ex(lwmem_t* lwobj, void* const ptr); +void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr); +size_t lwmem_get_size_ex(lwmem_t* lwobj, void* ptr); +#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ +void lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats); +#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ /** * \note This is a wrapper for \ref lwmem_assignmem_ex function. @@ -128,7 +135,7 @@ lwmem_region_t regions[] = { \endcode * \return `0` on failure, number of final regions used for memory manager on success */ -#define lwmem_assignmem(regions) lwmem_assignmem_ex(NULL, (regions)) +#define lwmem_assignmem(regions) lwmem_assignmem_ex(NULL, (regions)) /** * \note This is a wrapper for \ref lwmem_malloc_ex function. @@ -137,7 +144,7 @@ lwmem_region_t regions[] = { * \return Pointer to allocated memory on success, `NULL` otherwise * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ -#define lwmem_malloc(size) lwmem_malloc_ex(NULL, NULL, (size)) +#define lwmem_malloc(size) lwmem_malloc_ex(NULL, NULL, (size)) /** * \note This is a wrapper for \ref lwmem_calloc_ex function. @@ -147,7 +154,7 @@ lwmem_region_t regions[] = { * \return Pointer to allocated memory on success, `NULL` otherwise * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ -#define lwmem_calloc(nitems, size) lwmem_calloc_ex(NULL, NULL, (nitems), (size)) +#define lwmem_calloc(nitems, size) lwmem_calloc_ex(NULL, NULL, (nitems), (size)) /** * \note This is a wrapper for \ref lwmem_realloc_ex function. @@ -158,7 +165,7 @@ lwmem_region_t regions[] = { * \return Pointer to allocated memory on success, `NULL` otherwise * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ -#define lwmem_realloc(ptr, size) lwmem_realloc_ex(NULL, NULL, (ptr), (size)) +#define lwmem_realloc(ptr, size) lwmem_realloc_ex(NULL, NULL, (ptr), (size)) /** * \note This is a wrapper for \ref lwmem_realloc_s_ex function. @@ -170,7 +177,7 @@ lwmem_region_t regions[] = { * \return `1` if successfully reallocated, `0` otherwise * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ -#define lwmem_realloc_s(ptrptr, size) lwmem_realloc_s_ex(NULL, NULL, (ptrptr), (size)) +#define lwmem_realloc_s(ptrptr, size) lwmem_realloc_s_ex(NULL, NULL, (ptrptr), (size)) /** * \note This is a wrapper for \ref lwmem_free_ex function. @@ -178,7 +185,7 @@ lwmem_region_t regions[] = { * \param[in] ptr: Memory to free. `NULL` pointer is valid input * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ -#define lwmem_free(ptr) lwmem_free_ex(NULL, (ptr)) +#define lwmem_free(ptr) lwmem_free_ex(NULL, (ptr)) /** * \note This is a wrapper for \ref lwmem_free_s_ex function. @@ -187,7 +194,7 @@ lwmem_region_t regions[] = { * When set to non `NULL`, pointer is freed and set to `NULL` * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ -#define lwmem_free_s(ptrptr) lwmem_free_s_ex(NULL, (ptrptr)) +#define lwmem_free_s(ptrptr) lwmem_free_s_ex(NULL, (ptrptr)) /** * \note This is a wrapper for \ref lwmem_get_size_ex function. @@ -195,14 +202,21 @@ lwmem_region_t regions[] = { * \param[in] ptr: Pointer to allocated memory * \return Block size for user in units of bytes */ -#define lwmem_get_size(ptr) lwmem_get_size(NULL, (ptr)) +#define lwmem_get_size(ptr) lwmem_get_size_ex(NULL, (ptr)) + +/** + * \note This is a wrapper for \ref lwmem_get_stats_ex function. + * It operates in default LwMEM instance + * \param[in] ptr: Pointer to lwmem_stats_t to store result + */ +#define lwmem_get_stats(stats) lwmem_get_stats_ex(NULL, (stats)) #if defined(LWMEM_DEV) && !__DOXYGEN__ unsigned char lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size); -void lwmem_debug_save_state(void); -void lwmem_debug_restore_to_saved(void); +void lwmem_debug_save_state(void); +void lwmem_debug_restore_to_saved(void); -void lwmem_debug_print(unsigned char print_alloc, unsigned char print_free); +void lwmem_debug_print(unsigned char print_alloc, unsigned char print_free); #endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ /** diff --git a/lwmem/src/include/lwmem/lwmem.hpp b/lwmem/src/include/lwmem/lwmem.hpp new file mode 100644 index 0000000..2240947 --- /dev/null +++ b/lwmem/src/include/lwmem/lwmem.hpp @@ -0,0 +1,135 @@ +/** + * \file lwmem.hpp + * \brief Lightweight dynamic memory manager - C++ wrapper + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwMEM - Lightweight dynamic memory manager library. + * + * Author: Tilen MAJERLE + * Version: v2.1.0 + */ +#ifndef LWMEM_HDR_HPP +#define LWMEM_HDR_HPP + +#include "lwmem/lwmem.h" + +/** + * \ingroup LWMEM + * \defgroup LWMEM_CPP C++ wrapper functions for LwMEM + * \brief C++ wrapper functions for LwMEM + * \{ + */ + +namespace Lwmem { + +/** + * \brief LwMEM Light implementation with single memory region. + * \tparam LEN: Length of region in units of bytes + * + * This class provides C++ wrapper functions for LwMEM library. + * For detailed docs instructions, have a look at \ref lwmem.c file. + * + * Start lwmem with: + * \code{.c} +Lwmem::LwmemLight<1024> mngr; //Use 1024 bytes of data for memory operations +void* ptr = mngr.malloc(...); +... +... +mngr.free(ptr); +\endcode + */ +template +class LwmemLight { + public: + LwmemLight() { + /* Simple region descriptor with one region */ + const lwmem_region_t regions[] = {{m_reg_data, sizeof(m_reg_data)}, {NULL, 0}}; + lwmem_assignmem_ex(&m_lw, regions); + } + + /** + * \brief Allocate block of memory with selected size + * \param size: Block size to allocate in units of bytes + * \return Allocated memory or `NULL` on failure + * \sa lwmem_malloc_ex + */ + void* + malloc(size_t size) { + return lwmem_malloc_ex(&m_lw, nullptr, size); + } + + /** + * \brief Allocate block of memory with selected size and cleaned to all zeros + * \param[in] nitems: Number of items to allocate + * \param size: Size of each item in units of bytes + * \return Allocated memory or `NULL` on failure + * \sa lwmem_calloc_ex + */ + void* + calloc(size_t nitems, size_t size) { + return lwmem_calloc_ex(&m_lw, nullptr, nitems, size); + } + + /** + * \brief Reallocate block of memory + * \param ptr: Pointer to previously allocated memory block + * \param size: Block size to allocate in units of bytes + * \return Allocated memory or `NULL` on failure + * \sa lwmem_realloc_ex + */ + void* + realloc(void* ptr, size_t size) { + return lwmem_realloc_ex(&m_lw, nullptr, ptr, size); + } + + /** + * \brief Free memory block + * \param ptr: Pointer to previously allocated memory block + * \sa lwmem_realloc_ex + */ + void + free(void* ptr) { + lwmem_free_ex(&m_lw, ptr); + } + + private: + /* Delete unused constructors */ + LwmemLight(const LwmemLight& other) = delete; + /* Delete copy assignment operators */ + LwmemLight& operator=(const LwmemLight& other) = delete; + LwmemLight* operator=(const LwmemLight* other) = delete; + + lwmem_t m_lw; + uint8_t m_reg_data[LEN]; +}; + +}; // namespace Lwmem + +/** + * \} + */ + +#endif /* LWMEM_HDR_HPP */ diff --git a/lwmem/src/include/lwmem/lwmem_opt.h b/lwmem/src/include/lwmem/lwmem_opt.h index 8050d88..b17b5ce 100644 --- a/lwmem/src/include/lwmem/lwmem_opt.h +++ b/lwmem/src/include/lwmem/lwmem_opt.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,10 +29,10 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v2.0.0 + * Version: v2.1.0 */ -#ifndef LWMEM_HDR_OPT_H -#define LWMEM_HDR_OPT_H +#ifndef LWMEM_OPT_HDR_H +#define LWMEM_OPT_HDR_H /* Uncomment to ignore user options (or set macro in compiler flags) */ /* #define LWMEM_IGNORE_USER_OPTS */ @@ -58,7 +58,7 @@ extern "C" { * \note When `LWMEM_CFG_OS` is enabled, user must implement functions in \ref LWMEM_SYS group. */ #ifndef LWMEM_CFG_OS -#define LWMEM_CFG_OS 0 +#define LWMEM_CFG_OS 0 #endif /** @@ -69,7 +69,7 @@ extern "C" { * definition before you define handle type */ #ifndef LWMEM_CFG_OS_MUTEX_HANDLE -#define LWMEM_CFG_OS_MUTEX_HANDLE void * +#define LWMEM_CFG_OS_MUTEX_HANDLE void* #endif /** @@ -82,7 +82,7 @@ extern "C" { * Usually alignment of `4` bytes fits to all processors. */ #ifndef LWMEM_CFG_ALIGN_NUM -#define LWMEM_CFG_ALIGN_NUM ((size_t)4) +#define LWMEM_CFG_ALIGN_NUM ((size_t)4) #endif /** @@ -92,7 +92,7 @@ extern "C" { * It is disabled by default since it has performance penalties. */ #ifndef LWMEM_CFG_CLEAN_MEMORY -#define LWMEM_CFG_CLEAN_MEMORY 0 +#define LWMEM_CFG_CLEAN_MEMORY 0 #endif /** @@ -100,7 +100,7 @@ extern "C" { * */ #ifndef LWMEM_CFG_ENABLE_STATS -#define LWMEM_CFG_ENABLE_STATS 0 +#define LWMEM_CFG_ENABLE_STATS 0 #endif /** @@ -111,4 +111,4 @@ extern "C" { } #endif /* __cplusplus */ -#endif /* LWMEM_HDR_OPT_H */ +#endif /* LWMEM_OPT_HDR_H */ diff --git a/lwmem/src/include/lwmem/lwmem_opts_template.h b/lwmem/src/include/lwmem/lwmem_opts_template.h index ccac00c..deb5e80 100644 --- a/lwmem/src/include/lwmem/lwmem_opts_template.h +++ b/lwmem/src/include/lwmem/lwmem_opts_template.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,10 +29,10 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v2.0.0 + * Version: v2.1.0 */ -#ifndef LWMEM_HDR_OPTS_H -#define LWMEM_HDR_OPTS_H +#ifndef LWMEM_OPTS_HDR_H +#define LWMEM_OPTS_HDR_H /* Rename this file to "lwmem_opts.h" for your application */ @@ -41,4 +41,4 @@ * copy & replace here settings you want to change values */ -#endif /* LWMEM_HDR_OPTS_H */ +#endif /* LWMEM_OPTS_HDR_H */ diff --git a/lwmem/src/include/system/lwmem_sys.h b/lwmem/src/include/system/lwmem_sys.h index 9afb1e0..a837d89 100644 --- a/lwmem/src/include/system/lwmem_sys.h +++ b/lwmem/src/include/system/lwmem_sys.h @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,59 +29,63 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v2.0.0 + * Version: v2.1.0 */ -#ifndef LWMEM_HDR_SYS_H -#define LWMEM_HDR_SYS_H +#ifndef LWMEM_SYS_HDR_H +#define LWMEM_SYS_HDR_H -#include #include +#include #include "lwmem/lwmem.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +#if LWMEM_CFG_OS || __DOXYGEN__ + /** * \defgroup LWMEM_SYS System functions * \brief System functions when used with operating system * \{ */ - + /** * \brief Create a new mutex and assign value to handle * \param[out] m: Output variable to save mutex handle * \return `1` on success, `0` otherwise */ -uint8_t lwmem_sys_mutex_create(LWMEM_CFG_OS_MUTEX_HANDLE* m); +uint8_t lwmem_sys_mutex_create(LWMEM_CFG_OS_MUTEX_HANDLE* m); /** * \brief Check if mutex handle is valid * \param[in] m: Mutex handle to check if valid * \return `1` on success, `0` otherwise */ -uint8_t lwmem_sys_mutex_isvalid(LWMEM_CFG_OS_MUTEX_HANDLE* m); +uint8_t lwmem_sys_mutex_isvalid(LWMEM_CFG_OS_MUTEX_HANDLE* m); /** * \brief Wait for a mutex until ready (unlimited time) * \param[in] m: Mutex handle to wait for * \return `1` on success, `0` otherwise */ -uint8_t lwmem_sys_mutex_wait(LWMEM_CFG_OS_MUTEX_HANDLE* m); +uint8_t lwmem_sys_mutex_wait(LWMEM_CFG_OS_MUTEX_HANDLE* m); /** * \brief Release already locked mutex * \param[in] m: Mutex handle to release * \return `1` on success, `0` otherwise */ -uint8_t lwmem_sys_mutex_release(LWMEM_CFG_OS_MUTEX_HANDLE* m); +uint8_t lwmem_sys_mutex_release(LWMEM_CFG_OS_MUTEX_HANDLE* m); /** * \} */ +#endif /* LWMEM_CFG_OS || __DOXYGEN__ */ + #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* LWMEM_HDR_SYS_H */ +#endif /* LWMEM_SYS_HDR_H */ diff --git a/lwmem/src/lwmem/lwmem.c b/lwmem/src/lwmem/lwmem.c index 67f369e..02e755c 100644 --- a/lwmem/src/lwmem/lwmem.c +++ b/lwmem/src/lwmem/lwmem.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,24 +29,24 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v2.0.0 + * Version: v2.1.0 */ +#include "lwmem/lwmem.h" #include #include -#include "lwmem/lwmem.h" #if LWMEM_CFG_OS #include "system/lwmem_sys.h" #endif /* LWMEM_CFG_OS */ -#define LWMEM_MEMSET memset -#define LWMEM_MEMCPY memcpy -#define LWMEM_MEMMOVE memmove +#define LWMEM_MEMSET memset +#define LWMEM_MEMCPY memcpy +#define LWMEM_MEMMOVE memmove /** * \brief Transform alignment number (power of `2`) to bits */ -#define LWMEM_ALIGN_BITS ((size_t)(((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) +#define LWMEM_ALIGN_BITS ((size_t)(((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) /** * \brief Aligns input value to next alignment bits @@ -63,93 +63,108 @@ * - Input: `7`; Output: `8` * - Input: `8`; Output: `8` */ -#define LWMEM_ALIGN(x) (((x) + (LWMEM_ALIGN_BITS)) & ~(LWMEM_ALIGN_BITS)) +#define LWMEM_ALIGN(x) (((x) + (LWMEM_ALIGN_BITS)) & ~(LWMEM_ALIGN_BITS)) /** * \brief Size of metadata header for block information */ -#define LWMEM_BLOCK_META_SIZE LWMEM_ALIGN(sizeof(lwmem_block_t)) +#define LWMEM_BLOCK_META_SIZE LWMEM_ALIGN(sizeof(lwmem_block_t)) /** * \brief Cast input pointer to byte * \param[in] p: Input pointer to cast to byte pointer */ -#define LWMEM_TO_BYTE_PTR(p) ((uint8_t *)(p)) +#define LWMEM_TO_BYTE_PTR(p) ((uint8_t*)(p)) /** * \brief Bit indicating memory block is allocated */ -#define LWMEM_ALLOC_BIT ((size_t)((size_t)1 << (sizeof(size_t) * CHAR_BIT - 1))) +#define LWMEM_ALLOC_BIT ((size_t)((size_t)1 << (sizeof(size_t) * CHAR_BIT - 1))) /** * \brief Mark written in `next` field when block is allocated */ -#define LWMEM_BLOCK_ALLOC_MARK (0xDEADBEEF) +#define LWMEM_BLOCK_ALLOC_MARK (0xDEADBEEF) /** * \brief Set block as allocated * \param[in] block: Block to set as allocated */ -#define LWMEM_BLOCK_SET_ALLOC(block) do { if ((block) != NULL) { (block)->size |= LWMEM_ALLOC_BIT; (block)->next = (void *)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK); }} while (0) +#define LWMEM_BLOCK_SET_ALLOC(block) \ + do { \ + if ((block) != NULL) { \ + (block)->size |= LWMEM_ALLOC_BIT; \ + (block)->next = (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK); \ + } \ + } while (0) /** * \brief Check if input block is properly allocated and valid * \param[in] block: Block to check if properly set as allocated */ -#define LWMEM_BLOCK_IS_ALLOC(block) ((block) != NULL && ((block)->size & LWMEM_ALLOC_BIT) && (block)->next == (void *)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK)) +#define LWMEM_BLOCK_IS_ALLOC(block) \ + ((block) != NULL && ((block)->size & LWMEM_ALLOC_BIT) \ + && (block)->next == (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK)) /** * \brief Get block handle from application pointer * \param[in] ptr: Input pointer to get block from */ -#define LWMEM_GET_BLOCK_FROM_PTR(ptr) (void *)((ptr) != NULL ? ((LWMEM_TO_BYTE_PTR(ptr)) - LWMEM_BLOCK_META_SIZE) : NULL) +#define LWMEM_GET_BLOCK_FROM_PTR(ptr) (void*)((ptr) != NULL ? ((LWMEM_TO_BYTE_PTR(ptr)) - LWMEM_BLOCK_META_SIZE) : NULL) /** * \brief Get block handle from application pointer * \param[in] block: Input pointer to get block from */ -#define LWMEM_GET_PTR_FROM_BLOCK(block) (void *)((block) != NULL ? ((LWMEM_TO_BYTE_PTR(block)) + LWMEM_BLOCK_META_SIZE) : NULL) +#define LWMEM_GET_PTR_FROM_BLOCK(block) \ + (void*)((block) != NULL ? ((LWMEM_TO_BYTE_PTR(block)) + LWMEM_BLOCK_META_SIZE) : NULL) /** * \brief Minimum amount of memory required to make new empty block * * Default size is size of meta block */ -#define LWMEM_BLOCK_MIN_SIZE (LWMEM_BLOCK_META_SIZE) +#define LWMEM_BLOCK_MIN_SIZE (LWMEM_BLOCK_META_SIZE) /** * \brief Get LwMEM instance based on user input - * \param[in] in_lw: LwMEM instance. Set to `NULL` for default instance + * \param[in] in_lwobj: LwMEM instance. Set to `NULL` for default instance */ -#define LWMEM_GET_LW(in_lw) ((in_lw) != NULL ? (in_lw) : (&lwmem_default)) +#define LWMEM_GET_LWOBJ(in_lwobj) ((in_lwobj) != NULL ? (in_lwobj) : (&lwmem_default)) /** * \brief Gets block before input block (marked as prev) and its previous free block - * \param[in] in_lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] in_lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] in_b: Input block to find previous and its previous * \param[in] in_pp: Previous previous of input block * \param[in] in_p: Previous of input block */ -#define LWMEM_GET_PREV_CURR_OF_BLOCK(in_lw, in_b, in_pp, in_p) do { \ - for ((in_pp) = NULL, (in_p) = &(LWMEM_GET_LW(in_lw)->start_block); \ - (in_p) != NULL && (in_p)->next < (in_b); \ - (in_pp) = (in_p), (in_p) = (in_p)->next \ - ) {} \ +#define LWMEM_GET_PREV_CURR_OF_BLOCK(in_lwobj, in_b, in_pp, in_p) \ + do { \ + for ((in_pp) = NULL, (in_p) = &((in_lwobj)->start_block); (in_p) != NULL && (in_p)->next < (in_b); \ + (in_pp) = (in_p), (in_p) = (in_p)->next) {} \ } while (0) #if LWMEM_CFG_OS -#define LWMEM_PROTECT(lw) lwmem_sys_mutex_wait(&(LWMEM_GET_LW(lw)->mutex)) -#define LWMEM_UNPROTECT(lw) lwmem_sys_mutex_release(&(LWMEM_GET_LW(lw)->mutex)) +#define LWMEM_PROTECT(lwobj) lwmem_sys_mutex_wait(&((lwobj)->mutex)) +#define LWMEM_UNPROTECT(lwobj) lwmem_sys_mutex_release(&((lwobj)->mutex)) #else /* LWMEM_CFG_OS */ -#define LWMEM_PROTECT(lw) -#define LWMEM_UNPROTECT(lw) +#define LWMEM_PROTECT(lwobj) +#define LWMEM_UNPROTECT(lwobj) #endif /* !LWMEM_CFG_OS */ /* Statistics part */ #if LWMEM_CFG_ENABLE_STATS -#define LWMEM_INC_STATS(field) (++(field)) +#define LWMEM_INC_STATS(field) (++(field)) +#define LWMEM_UPDATE_MIN_FREE(lwobj) \ + do { \ + if ((lwobj)->mem_available_bytes < (lwobj)->stats.minimum_ever_mem_available_bytes) { \ + (lwobj)->stats.minimum_ever_mem_available_bytes = (lwobj)->mem_available_bytes; \ + } \ + } while (0) #else #define LWMEM_INC_STATS(field) +#define LWMEM_UPDATE_MIN_FREE(lwobj) #endif /* LWMEM_CFG_ENABLE_STATS */ /** @@ -165,7 +180,7 @@ static lwmem_t lwmem_default; * \return `1` if region valid, `0` otherwise */ static uint8_t -prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* ms) { +prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* ms) { size_t mem_size; uint8_t* mem_start_addr; @@ -176,7 +191,7 @@ prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* m *ms = 0; /* Check region size and align it to config bits */ - mem_size = region->size & ~LWMEM_ALIGN_BITS;/* Size does not include lower bits */ + mem_size = region->size & ~LWMEM_ALIGN_BITS; /* Size does not include lower bits */ if (mem_size < (2 * LWMEM_BLOCK_MIN_SIZE)) { return 0; } @@ -186,7 +201,7 @@ prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* m * Increase start address and decrease effective region size */ mem_start_addr = region->start_addr; - if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { /* Check alignment boundary */ + if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { /* Check alignment boundary */ mem_start_addr += ((size_t)LWMEM_CFG_ALIGN_NUM) - ((size_t)mem_start_addr & LWMEM_ALIGN_BITS); mem_size -= (size_t)(mem_start_addr - LWMEM_TO_BYTE_PTR(region->start_addr)); } @@ -203,11 +218,11 @@ prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* m /** * \brief Insert free block to linked list of free blocks - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] nb: New free block to insert into linked list */ static void -prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) { +prv_insert_free_block(lwmem_t* const lwobj, lwmem_block_t* nb) { lwmem_block_t* prev; /* Check valid inputs */ @@ -219,7 +234,7 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) { * Try to find position to put new block in-between * Search until all free block addresses are lower than entry block */ - for (prev = &(LWMEM_GET_LW(lw)->start_block); prev != NULL && prev->next < nb; prev = prev->next) {} + for (prev = &(lwobj->start_block); prev != NULL && prev->next < nb; prev = prev->next) {} /* This is hard error with wrong memory usage */ if (prev == NULL) { @@ -239,7 +254,12 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) { * By doing this, we protect data left by app * and we make sure new allocations cannot see old information */ - LWMEM_MEMSET(LWMEM_GET_PTR_FROM_BLOCK(nb), 0x00, nb->size - LWMEM_BLOCK_META_SIZE); + if (nb != NULL) { + void* p = LWMEM_GET_PTR_FROM_BLOCK(nb); + if (p != NULL) { + LWMEM_MEMSET(p, 0x00, nb->size - LWMEM_BLOCK_META_SIZE); + } + } #endif /* LWMEM_CFG_RESET_MEMORY */ /* @@ -247,9 +267,9 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) { * If this is the case, merge blocks together and increase previous block by input block size */ if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(nb)) { - prev->size += nb->size; /* Increase current block by size of new block */ - nb = prev; /* New block and current are now the same thing */ - /* + prev->size += nb->size; /* Increase current block by size of new block */ + nb = prev; /* New block and current are now the same thing */ + /* * It is important to set new block as current one * as this allows merging previous and next blocks together with new block * at the same time; follow next steps @@ -260,16 +280,18 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) { * Check if new block and next of previous create big contiguous block * Do not merge with "end of region" indication (commented part of if statement) */ - if (prev->next != NULL && prev->next->size > 0 /* Do not remove "end of region" indicator in each region */ + if (prev->next != NULL && prev->next->size > 0 /* Do not remove "end of region" indicator in each region */ && (LWMEM_TO_BYTE_PTR(nb) + nb->size) == LWMEM_TO_BYTE_PTR(prev->next)) { - if (prev->next == LWMEM_GET_LW(lw)->end_block) {/* Does it points to the end? */ - nb->next = LWMEM_GET_LW(lw)->end_block; /* Set end block pointer */ + if (prev->next == lwobj->end_block) { /* Does it points to the end? */ + nb->next = lwobj->end_block; /* Set end block pointer */ } else { - nb->size += prev->next->size; /* Expand of current block for size of next free block which is right behind new block */ - nb->next = prev->next->next; /* Next free is pointed to the next one of previous next */ + nb->size += + prev->next + ->size; /* Expand of current block for size of next free block which is right behind new block */ + nb->next = prev->next->next; /* Next free is pointed to the next one of previous next */ } } else { - nb->next = prev->next; /* Set next of input block as next of current one */ + nb->next = prev->next; /* Set next of input block as next of current one */ } /* @@ -283,19 +305,19 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) { /** * \brief Split too big block and add it to list of free blocks - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] block: Pointer to block with size already set * \param[in] new_block_size: New block size to be set * \return `1` if block splitted, `0` otherwise */ static uint8_t -prv_split_too_big_block(lwmem_t* const lw, lwmem_block_t* block, size_t new_block_size) { +prv_split_too_big_block(lwmem_t* const lwobj, lwmem_block_t* block, size_t new_block_size) { lwmem_block_t* next; size_t block_size, is_alloc_bit; uint8_t success = 0; - is_alloc_bit = block->size & LWMEM_ALLOC_BIT; /* Check if allocation bit is set */ - block_size = block->size & ~LWMEM_ALLOC_BIT;/* Use size without allocated bit */ + is_alloc_bit = block->size & LWMEM_ALLOC_BIT; /* Check if allocation bit is set */ + block_size = block->size & ~LWMEM_ALLOC_BIT; /* Use size without allocated bit */ /* * If current block size is greater than requested size, @@ -303,12 +325,12 @@ prv_split_too_big_block(lwmem_t* const lw, lwmem_block_t* block, size_t new_bloc * and add it back to list of empty blocks */ if ((block_size - new_block_size) >= LWMEM_BLOCK_MIN_SIZE) { - next = (void*)(LWMEM_TO_BYTE_PTR(block) + new_block_size); /* Put next block after size of current allocation */ - next->size = block_size - new_block_size; /* Modify block data */ - block->size = new_block_size; /* Current size is now smaller */ + next = (void*)(LWMEM_TO_BYTE_PTR(block) + new_block_size); /* Put next block after size of current allocation */ + next->size = block_size - new_block_size; /* Modify block data */ + block->size = new_block_size; /* Current size is now smaller */ - LWMEM_GET_LW(lw)->mem_available_bytes += next->size;/* Increase available bytes by new block size */ - prv_insert_free_block(lw, next); /* Add new block to the free list */ + lwobj->mem_available_bytes += next->size; /* Increase available bytes by new block size */ + prv_insert_free_block(lwobj, next); /* Add new block to the free list */ success = 1; } else { @@ -326,28 +348,28 @@ prv_split_too_big_block(lwmem_t* const lw, lwmem_block_t* block, size_t new_bloc /** * \brief Private allocation function - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] region: Pointer to region to allocate from. * Set to `NULL` for any region * \param[in] size: Application wanted size, excluding size of meta header * \return Pointer to allocated memory, `NULL` otherwise */ static void* -prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) { - lwmem_block_t* prev, *curr; +prv_alloc(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) { + lwmem_block_t *prev, *curr; void* retval = NULL; /* Calculate final size including meta data size */ const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; /* Check if initialized and if size is in the limits */ - if (LWMEM_GET_LW(lw)->end_block == NULL || final_size == LWMEM_BLOCK_META_SIZE || (final_size & LWMEM_ALLOC_BIT) > 0) { + if (lwobj->end_block == NULL || final_size == LWMEM_BLOCK_META_SIZE || (final_size & LWMEM_ALLOC_BIT) > 0) { return NULL; } /* Set default values */ - prev = &(LWMEM_GET_LW(lw)->start_block); /* Use pointer from custom lwmem block */ - curr = prev->next; /* Curr represents first actual free block */ + prev = &(lwobj->start_block); /* Use pointer from custom lwmem block */ + curr = prev->next; /* Curr represents first actual free block */ /* * If region is not set to NULL, @@ -371,17 +393,17 @@ prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) { */ for (; curr != NULL; prev = curr, curr = curr->next) { /* Check bounds */ - if (curr->next == NULL || curr == LWMEM_GET_LW(lw)->end_block) { + if (curr->next == NULL || curr == lwobj->end_block) { return NULL; } if ((uint8_t*)curr < (uint8_t*)region_start_addr) { /* Check if we reached region */ continue; } - if ((uint8_t*)curr >= (uint8_t*)(region_start_addr + region_size)) {/* Check if we are out already */ + if ((uint8_t*)curr >= (uint8_t*)(region_start_addr + region_size)) { /* Check if we are out already */ return NULL; } if (curr->size >= final_size) { - break; /* Free block identified */ + break; /* Free block identified */ } } } else { @@ -390,8 +412,8 @@ prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) { * Loop until size of current block is smaller than requested final size */ for (; curr != NULL && curr->size < final_size; prev = curr, curr = curr->next) { - if (curr->next == NULL || curr == LWMEM_GET_LW(lw)->end_block) {/* If no more blocks available */ - return NULL; /* No sufficient memory available to allocate block of memory */ + if (curr->next == NULL || curr == lwobj->end_block) { /* If no more blocks available */ + return NULL; /* No sufficient memory available to allocate block of memory */ } } } @@ -402,35 +424,36 @@ prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) { } /* There is a valid block available */ - retval = LWMEM_GET_PTR_FROM_BLOCK(curr); /* Return pointer does not include meta part */ - prev->next = curr->next; /* Remove this block from linked list by setting next of previous to next of current */ + retval = LWMEM_GET_PTR_FROM_BLOCK(curr); /* Return pointer does not include meta part */ + prev->next = curr->next; /* Remove this block from linked list by setting next of previous to next of current */ /* curr block is now removed from linked list */ - LWMEM_GET_LW(lw)->mem_available_bytes -= curr->size;/* Decrease available bytes by allocated block size */ - prv_split_too_big_block(lw, curr, final_size); /* Split block if it is too big */ - LWMEM_BLOCK_SET_ALLOC(curr); /* Set block as allocated */ + lwobj->mem_available_bytes -= curr->size; /* Decrease available bytes by allocated block size */ + prv_split_too_big_block(lwobj, curr, final_size); /* Split block if it is too big */ + LWMEM_BLOCK_SET_ALLOC(curr); /* Set block as allocated */ - LWMEM_INC_STATS(LWMEM_GET_LW(lw)->stats.nr_alloc); + LWMEM_UPDATE_MIN_FREE(lwobj); + LWMEM_INC_STATS(lwobj->stats.nr_alloc); return retval; } /** * \brief Free input pointer - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] ptr: Input pointer to free */ static void -prv_free(lwmem_t* const lw, void* const ptr) { +prv_free(lwmem_t* const lwobj, void* const ptr) { lwmem_block_t* const block = LWMEM_GET_BLOCK_FROM_PTR(ptr); - if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */ - block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */ + if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */ + block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */ - LWMEM_GET_LW(lw)->mem_available_bytes += block->size; /* Increase available bytes */ - prv_insert_free_block(lw, block); /* Put block back to list of free block */ + lwobj->mem_available_bytes += block->size; /* Increase available bytes */ + prv_insert_free_block(lwobj, block); /* Put block back to list of free block */ - LWMEM_INC_STATS(LWMEM_GET_LW(lw)->stats.nr_free); + LWMEM_INC_STATS(lwobj->stats.nr_free); } } @@ -444,7 +467,7 @@ prv_free(lwmem_t* const lw, void* const ptr) { * - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)` * - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success * - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] region: Pointer to region to allocate from. * Set to `NULL` for any region * \param[in] ptr: Memory block previously allocated with one of allocation functions. @@ -453,21 +476,22 @@ prv_free(lwmem_t* const lw, void* const ptr) { * \return Pointer to allocated memory on success, `NULL` otherwise */ static void* -prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, const size_t size) { - lwmem_block_t* block, *prevprev, *prev; - size_t block_size; /* Holds size of input block (ptr), including metadata size */ - const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE;/* Holds size of new requested block size, including metadata size */ - void* retval; /* Return pointer, used with LWMEM_RETURN macro */ +prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) { + lwmem_block_t *block, *prevprev, *prev; + size_t block_size; /* Holds size of input block (ptr), including metadata size */ + const size_t final_size = + LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; /* Holds size of new requested block size, including metadata size */ + void* retval; /* Return pointer, used with LWMEM_RETURN macro */ /* Check optional input parameters */ if (size == 0) { if (ptr != NULL) { - prv_free(lw, ptr); + prv_free(lwobj, ptr); } return NULL; } if (ptr == NULL) { - return prv_alloc(lw, region, size); + return prv_alloc(lwobj, region, size); } /* Try to reallocate existing pointer */ @@ -478,11 +502,11 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co /* Process existing block */ block = LWMEM_GET_BLOCK_FROM_PTR(ptr); if (LWMEM_BLOCK_IS_ALLOC(block)) { - block_size = block->size & ~LWMEM_ALLOC_BIT;/* Get actual block size, without memory allocation bit */ + block_size = block->size & ~LWMEM_ALLOC_BIT; /* Get actual block size, without memory allocation bit */ /* Check current block size is the same as new requested size */ if (block_size == final_size) { - return ptr; /* Just return pointer, nothing to do */ + return ptr; /* Just return pointer, nothing to do */ } /* @@ -505,7 +529,7 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co */ if (final_size < block_size) { if ((block_size - final_size) >= LWMEM_BLOCK_MIN_SIZE) { - prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */ + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ } else { /* * It is not possible to create new empty block at the end of input block @@ -515,11 +539,11 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co */ /* Find free blocks before input block */ - LWMEM_GET_PREV_CURR_OF_BLOCK(lw, block, prevprev, prev); + LWMEM_GET_PREV_CURR_OF_BLOCK(lwobj, block, prevprev, prev); /* Check if current block and next free are connected */ if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) - && prev->next->size > 0) { /* Must not be end of region indicator */ + && prev->next->size > 0) { /* Must not be end of region indicator */ /* Make temporary variables as prev->next will point to different location */ const size_t tmp_size = prev->next->size; void* const tmp_next = prev->next->next; @@ -528,19 +552,20 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co prev->next = (void*)(LWMEM_TO_BYTE_PTR(prev->next) - (block_size - final_size)); prev->next->size = tmp_size + (block_size - final_size); prev->next->next = tmp_next; - LWMEM_GET_LW(lw)->mem_available_bytes += block_size - final_size; /* Increase available bytes by increase of free block */ + lwobj->mem_available_bytes += + block_size - final_size; /* Increase available bytes by increase of free block */ - block->size = final_size; /* Block size is requested size */ + block->size = final_size; /* Block size is requested size */ } } - LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ - return ptr; /* Return existing pointer */ + LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ + return ptr; /* Return existing pointer */ } /* New requested size is bigger than current block size is */ /* Find last free (and its previous) block, located just before input block */ - LWMEM_GET_PREV_CURR_OF_BLOCK(lw, block, prevprev, prev); + LWMEM_GET_PREV_CURR_OF_BLOCK(lwobj, block, prevprev, prev); /* If entry could not be found, there is a hard error */ if (prev == NULL) { @@ -552,20 +577,23 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co /* Input block points to address somewhere between "prev" and "prev->next" pointers */ /* Check if "block" and next free "prev->next" create contiguous memory with size of at least new requested size */ - if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next)/* Blocks create contiguous block */ + if ((LWMEM_TO_BYTE_PTR(block) + block_size) + == LWMEM_TO_BYTE_PTR(prev->next) /* Blocks create contiguous block */ && (block_size + prev->next->size) >= final_size) { /* Size is greater or equal to requested */ /* * Merge blocks together by increasing current block with size of next free one * and remove next free from list of free blocks */ - LWMEM_GET_LW(lw)->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */ - block->size = block_size + prev->next->size;/* Increase effective size of new block */ - prev->next = prev->next->next; /* Set next to next's next, effectively remove expanded block from free list */ - - prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */ - LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ - return ptr; /* Return existing pointer */ + lwobj->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */ + LWMEM_UPDATE_MIN_FREE(lwobj); + block->size = block_size + prev->next->size; /* Increase effective size of new block */ + prev->next = + prev->next->next; /* Set next to next's next, effectively remove expanded block from free list */ + + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ + LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ + return ptr; /* Return existing pointer */ } /* @@ -573,8 +601,8 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co * * It is necessary to make a memory move and shift content up as new return pointer is now upper on address space */ - if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) /* Blocks create contiguous block */ - && (prev->size + block_size) >= final_size) { /* Size is greater or equal to requested */ + if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) /* Blocks create contiguous block */ + && (prev->size + block_size) >= final_size) { /* Size is greater or equal to requested */ /* Move memory from block to block previous to current */ void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); void* const new_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(prev); @@ -589,14 +617,16 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co */ LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); - LWMEM_GET_LW(lw)->mem_available_bytes -= prev->size;/* For now decrease effective available bytes */ - prev->size += block_size; /* Increase size of input block size */ - prevprev->next = prev->next; /* Remove prev from free list as it is now being used for allocation together with existing block */ - block = prev; /* Move block pointer to previous one */ + lwobj->mem_available_bytes -= prev->size; /* For now decrease effective available bytes */ + LWMEM_UPDATE_MIN_FREE(lwobj); + prev->size += block_size; /* Increase size of input block size */ + prevprev->next = + prev->next; /* Remove prev from free list as it is now being used for allocation together with existing block */ + block = prev; /* Move block pointer to previous one */ - prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */ - LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ - return new_data_ptr; /* Return new data ptr */ + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ + LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ + return new_data_ptr; /* Return new data ptr */ } /* @@ -607,9 +637,11 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co * Last option is to check if previous free block "prev", input block "block" and next free block "prev->next" create contiguous block * and size of new block (from 3 contiguous blocks) together is big enough */ - if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) /* Input block and free block before create contiguous block */ - && (LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) /* Input block and free block after create contiguous block */ - && (prev->size + block_size + prev->next->size) >= final_size) {/* Size is greater or equal to requested */ + if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) + == LWMEM_TO_BYTE_PTR(block) /* Input block and free block before create contiguous block */ + && (LWMEM_TO_BYTE_PTR(block) + block_size) + == LWMEM_TO_BYTE_PTR(prev->next) /* Input block and free block after create contiguous block */ + && (prev->size + block_size + prev->next->size) >= final_size) { /* Size is greater or equal to requested */ /* Move memory from block to block previous to current */ void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); @@ -623,16 +655,22 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co * * Metadata of "prev" are not modified during memmove */ - LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); /* Copy old buffer size to new location */ - - LWMEM_GET_LW(lw)->mem_available_bytes -= prev->size + prev->next->size; /* Decrease effective available bytes for free blocks before and after input block */ - prev->size += block_size + prev->next->size;/* Increase size of new block by size of 2 free blocks */ - prevprev->next = prev->next->next; /* Remove free block before current one and block after current one from linked list (remove 2) */ - block = prev; /* Previous block is now current */ - - prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */ - LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ - return new_data_ptr; /* Return new data ptr */ + LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); /* Copy old buffer size to new location */ + + lwobj->mem_available_bytes -= + prev->size + + prev->next + ->size; /* Decrease effective available bytes for free blocks before and after input block */ + LWMEM_UPDATE_MIN_FREE(lwobj); + prev->size += block_size + prev->next->size; /* Increase size of new block by size of 2 free blocks */ + prevprev->next = + prev->next + ->next; /* Remove free block before current one and block after current one from linked list (remove 2) */ + block = prev; /* Previous block is now current */ + + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ + LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ + return new_data_ptr; /* Return new data ptr */ } } else { /* Hard error. Input pointer is not NULL and block is not considered allocated */ @@ -648,18 +686,19 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co * * Final solution is to find completely new empty block of sufficient size and copy content from old one to new one */ - retval = prv_alloc(lw, region, size); /* Try to allocate new block */ + retval = prv_alloc(lwobj, region, size); /* Try to allocate new block */ if (retval != NULL) { - block_size = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; /* Get application size from input pointer */ - LWMEM_MEMCPY(retval, ptr, size > block_size ? block_size : size); /* Copy content to new allocated block */ - prv_free(lw, ptr); /* Free input pointer */ + block_size = + (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; /* Get application size from input pointer */ + LWMEM_MEMCPY(retval, ptr, size > block_size ? block_size : size); /* Copy content to new allocated block */ + prv_free(lwobj, ptr); /* Free input pointer */ } return retval; } /** * \brief Initializes and assigns user regions for memory used by allocator algorithm - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] regions: Pointer to array of regions with address and respective size. * Regions must be in increasing order (start address) and must not overlap in-between. * Last region entry must have address `NULL` and size set to `0` @@ -677,23 +716,23 @@ lwmem_region_t regions[] = { * It must be called only once to setup memory regions */ size_t -lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) { +lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) { uint8_t* mem_start_addr; size_t mem_size, len = 0; - lwmem_block_t* first_block, *prev_end_block; + lwmem_block_t *first_block, *prev_end_block; + lwobj = LWMEM_GET_LWOBJ(lwobj); /* Check first things first */ - if (regions == NULL - || LWMEM_GET_LW(lw)->end_block != NULL /* Init function may only be called once per lwmem instance */ + if (regions == NULL || lwobj->end_block != NULL /* Init function may only be called once per lwmem instance */ || (((size_t)LWMEM_CFG_ALIGN_NUM) & (((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) > 0) { /* Must be power of 2 */ - return 0; + return 0; } /* Check values entered by application */ mem_start_addr = (void*)0; mem_size = 0; for (size_t i = 0;; ++i) { - /* + /* * Check for valid entry or end of array descriptor * * Invalid entry is considered as "end-of-region" indicator @@ -719,10 +758,10 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) { /* Process further checks of valid inputs */ if (regions == NULL || len == 0 #if LWMEM_CFG_OS - || lwmem_sys_mutex_isvalid(&(LWMEM_GET_LW(lw)->mutex)) /* Check if mutex valid already = must not be */ - || !lwmem_sys_mutex_create(&(LWMEM_GET_LW(lw)->mutex)) /* Final step = try to create mutex for new instance */ -#endif /* LWMEM_CFG_OS */ - ) { + || lwmem_sys_mutex_isvalid(&(lwobj->mutex)) /* Check if mutex valid already = must not be */ + || !lwmem_sys_mutex_create(&(lwobj->mutex)) /* Final step = try to create mutex for new instance */ +#endif /* LWMEM_CFG_OS */ + ) { return 0; } @@ -737,23 +776,23 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) { * In first indication application shall set start_block and never again * end_block value holds */ - if (LWMEM_GET_LW(lw)->end_block == NULL) { + if (lwobj->end_block == NULL) { /* * Next entry of start block is first region * It points to beginning of region data * In the later step(s) first block is manually set on top of memory region */ - LWMEM_GET_LW(lw)->start_block.next = (void*)mem_start_addr; - LWMEM_GET_LW(lw)->start_block.size = 0; /* Size of dummy start block is zero */ + lwobj->start_block.next = (void*)mem_start_addr; + lwobj->start_block.size = 0; /* Size of dummy start block is zero */ } /* Save current end block status as it is used later for linked list insertion */ - prev_end_block = LWMEM_GET_LW(lw)->end_block; + prev_end_block = lwobj->end_block; /* Put end block to the end of the region with size = 0 */ - LWMEM_GET_LW(lw)->end_block = (void*)(mem_start_addr + mem_size - LWMEM_BLOCK_META_SIZE); - LWMEM_GET_LW(lw)->end_block->next = NULL; /* End block in region does not have next entry */ - LWMEM_GET_LW(lw)->end_block->size = 0; /* Size of end block is zero */ + lwobj->end_block = (void*)(mem_start_addr + mem_size - LWMEM_BLOCK_META_SIZE); + lwobj->end_block->next = NULL; /* End block in region does not have next entry */ + lwobj->end_block->size = 0; /* Size of end block is zero */ /* * Create memory region first block. @@ -764,7 +803,7 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) { * Actual maximal available size for application in the region is mem_size - 2 * MEM_BLOCK_META_SIZE */ first_block = (void*)mem_start_addr; - first_block->next = LWMEM_GET_LW(lw)->end_block;/* Next block of first is last block */ + first_block->next = lwobj->end_block; /* Next block of first is last block */ first_block->size = mem_size - LWMEM_BLOCK_META_SIZE; /* Check if previous regions exist by checking previous end block state */ @@ -772,22 +811,26 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) { prev_end_block->next = first_block; /* End block of previous region now points to start of current region */ } - LWMEM_GET_LW(lw)->mem_available_bytes += first_block->size; /* Increase number of available bytes */ - ++LWMEM_GET_LW(lw)->mem_regions_count; /* Increase number of used regions */ + lwobj->mem_available_bytes += first_block->size; /* Increase number of available bytes */ + ++lwobj->mem_regions_count; /* Increase number of used regions */ } #if defined(LWMEM_DEV) /* Copy default state of start block */ LWMEM_MEMCPY(&lwmem_default.start_block_first_use, &lwmem_default.start_block, sizeof(lwmem_default.start_block)); #endif /* defined(LWMEM_DEV) */ +#if LWMEM_CFG_ENABLE_STATS + lwobj->stats.mem_size_bytes = lwobj->mem_available_bytes; + lwobj->stats.minimum_ever_mem_available_bytes = lwobj->mem_available_bytes; +#endif - return LWMEM_GET_LW(lw)->mem_regions_count; /* Return number of regions used by manager */ + return lwobj->mem_regions_count; /* Return number of regions used by manager */ } /** * \brief Allocate memory of requested size in specific lwmem instance and optional region. * \note This is an extended malloc version function declaration to support advanced features - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] region: Optional region instance within LwMEM instance to force allocation from. * Set to `NULL` to use any region within LwMEM instance * \param[in] size: Number of bytes to allocate @@ -795,11 +838,12 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) { * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ void* -lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) { +lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size) { void* ptr; - LWMEM_PROTECT(lw); - ptr = prv_alloc(lw, region, size); - LWMEM_UNPROTECT(lw); + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + ptr = prv_alloc(lwobj, region, size); + LWMEM_UNPROTECT(lwobj); return ptr; } @@ -810,7 +854,7 @@ lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t si * It resets allocated block of memory to zero if allocation is successful * \note This is an extended calloc version function declaration to support advanced features - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] region: Optional region instance within LwMEM instance to force allocation from. * Set to `NULL` to use any region within LwMEM instance * \param[in] nitems: Number of elements to be allocated @@ -819,15 +863,16 @@ lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t si * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ void* -lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t nitems, const size_t size) { +lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size) { void* ptr; const size_t s = size * nitems; - LWMEM_PROTECT(lw); - if ((ptr = prv_alloc(lw, region, s)) != NULL) { + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + if ((ptr = prv_alloc(lwobj, region, s)) != NULL) { LWMEM_MEMSET(ptr, 0x00, s); } - LWMEM_UNPROTECT(lw); + LWMEM_UNPROTECT(lwobj); return ptr; } @@ -843,7 +888,7 @@ lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t ni * - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)` * - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success * - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] region: Pointer to region to allocate from. * Set to `NULL` to use any region within LwMEM instance. * Instance must be the same as used during allocation procedure @@ -854,11 +899,12 @@ lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t ni * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ void* -lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, const size_t size) { +lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) { void* p; - LWMEM_PROTECT(lw); - p = prv_realloc(lw, region, ptr, size); - LWMEM_UNPROTECT(lw); + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + p = prv_realloc(lwobj, region, ptr, size); + LWMEM_UNPROTECT(lwobj); return p; } @@ -879,7 +925,7 @@ lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const pt * - `*ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)`, sets input pointer pointing to `NULL` * - `*ptr != NULL; size > 0`: Function tries to reallocate existing pointer with new size and copy content to new block * - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance * \param[in] region: Pointer to region to allocate from. * Set to `NULL` to use any region within LwMEM instance. * Instance must be the same as used during allocation procedure @@ -891,7 +937,7 @@ lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const pt * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ uint8_t -lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const ptr, const size_t size) { +lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size) { void* new_ptr; /* @@ -903,10 +949,10 @@ lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const return 0; } - new_ptr = lwmem_realloc_ex(lw, region, *ptr, size); /* Try to reallocate existing pointer */ + new_ptr = lwmem_realloc_ex(lwobj, region, *ptr, size); /* Try to reallocate existing pointer */ if (new_ptr != NULL) { *ptr = new_ptr; - } else if (size == 0) { /* size == 0 means free input memory */ + } else if (size == 0) { /* size == 0 means free input memory */ *ptr = NULL; return 1; } @@ -916,17 +962,18 @@ lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const /** * \brief Free previously allocated memory using one of allocation functions * in specific lwmem instance. - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance. + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. * Instance must be the same as used during allocation procedure * \note This is an extended free version function declaration to support advanced features * \param[in] ptr: Memory to free. `NULL` pointer is valid input * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ void -lwmem_free_ex(lwmem_t* const lw, void* const ptr) { - LWMEM_PROTECT(lw); - prv_free(lw, ptr); - LWMEM_UNPROTECT(lw); +lwmem_free_ex(lwmem_t* lwobj, void* const ptr) { + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + prv_free(lwobj, ptr); + LWMEM_UNPROTECT(lwobj); } /** @@ -937,45 +984,68 @@ lwmem_free_ex(lwmem_t* const lw, void* const ptr) { * * It is advised to use this function when freeing memory. * - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance. + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. * Instance must be the same as used during allocation procedure * \param[in] ptr: Pointer to pointer to allocated memory. * When set to non `NULL`, pointer is freed and set to `NULL` * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled */ void -lwmem_free_s_ex(lwmem_t* const lw, void** const ptr) { +lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr) { if (ptr != NULL && *ptr != NULL) { - LWMEM_PROTECT(lw); - prv_free(lw, *ptr); - LWMEM_UNPROTECT(lw); + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + prv_free(lwobj, *ptr); + LWMEM_UNPROTECT(lwobj); *ptr = NULL; } } /** * \brief Get user size of allocated memory - * \param[in] lw: LwMEM instance. Set to `NULL` to use default instance. + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. * Instance must be the same as used during allocation procedure * \param[in] ptr: Pointer to allocated memory * \return Block size for user in units of bytes */ size_t -lwmem_get_size_ex(lwmem_t* const lw, void* ptr) { +lwmem_get_size_ex(lwmem_t* lwobj, void* ptr) { lwmem_block_t* block; uint32_t len = 0; if (ptr != NULL) { - LWMEM_PROTECT(lw); + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); block = LWMEM_GET_BLOCK_FROM_PTR(ptr); if (LWMEM_BLOCK_IS_ALLOC(block)) { len = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; } - LWMEM_UNPROTECT(lw); + LWMEM_UNPROTECT(lwobj); } return len; } +#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ + +/** + * \brief Get statistics of a LwMEM instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. + * Instance must be the same as used during allocation procedure + * \param[in] stats: Pointer to \ref lwmem_stats_t to store result + */ +void +lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats) { + if (stats != NULL) { + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + *stats = lwobj->stats; + stats->mem_available_bytes = lwobj->mem_available_bytes; + LWMEM_UNPROTECT(lwobj); + } +} + +#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ + /* Part of library used ONLY for LWMEM_DEV purposes */ /* To validate and test library */ @@ -1035,11 +1105,7 @@ print_block(size_t i, lwmem_block_t* block) { is_free = (block->size & LWMEM_ALLOC_BIT) == 0 && block != &lwmem_default.start_block_first_use && block->size > 0; block_size = block->size & ~LWMEM_ALLOC_BIT; - printf("| %5d | %16p | %6d | %4d | %16d |", - (int)i, - block, - (int)is_free, - (int)block_size, + printf("| %5d | %16p | %6d | %4d | %16d |", (int)i, (void*)block, (int)is_free, (int)block_size, (int)(is_free ? (block_size - LWMEM_BLOCK_META_SIZE) : 0)); if (block == &lwmem_default.start_block_first_use) { printf(" Start block "); @@ -1060,6 +1126,9 @@ lwmem_debug_print(uint8_t print_alloc, uint8_t print_free) { size_t block_size; lwmem_block_t* block; + (void)print_alloc; + (void)print_free; + printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); printf("| Block | Address | IsFree | Size | MaxUserAllocSize | Meta |\r\n"); printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); diff --git a/lwmem/src/lwmem/lwmem.cpp b/lwmem/src/lwmem/lwmem.cpp new file mode 100644 index 0000000..4229285 --- /dev/null +++ b/lwmem/src/lwmem/lwmem.cpp @@ -0,0 +1,33 @@ +/** + * \file lwmem.cpp + * \brief Lightweight dynamic memory manager - C++ wrapper + */ + +/* + * Copyright (c) 2020 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwMEM - Lightweight dynamic memory manager library. + * + * Author: Tilen MAJERLE + * Version: v2.1.0 + */ diff --git a/lwmem/src/system/lwmem_sys_cmsis_os.c b/lwmem/src/system/lwmem_sys_cmsis_os.c index 17bf646..a327f78 100644 --- a/lwmem/src/system/lwmem_sys_cmsis_os.c +++ b/lwmem/src/system/lwmem_sys_cmsis_os.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,7 +29,7 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v2.0.0 + * Version: v2.1.0 */ #include "system/lwmem_sys.h" diff --git a/lwmem/src/system/lwmem_sys_threadx.c b/lwmem/src/system/lwmem_sys_threadx.c new file mode 100644 index 0000000..f6713ef --- /dev/null +++ b/lwmem/src/system/lwmem_sys_threadx.c @@ -0,0 +1,69 @@ +/** + * \file lwmem_sys_cmsis_os.c + * \brief System functions for CMSIS-OS based operating system + */ + +/* + * Copyright (c) 2023 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwMEM - Lightweight dynamic memory manager library. + * + * Author: Tilen MAJERLE + * Version: v2.1.0 + */ +#include "system/lwmem_sys.h" + +#if LWMEM_CFG_OS && !__DOXYGEN__ + +/* + * To use this module, options must be defined as + * + * #define LWMEM_CFG_OS_MUTEX_HANDLE TX_MUTEX + */ + +/* Include ThreadX API module */ +#include "tx_api.h" +#include "tx_mutex.h" + +uint8_t +lwmem_sys_mutex_create(LWMEM_CFG_OS_MUTEX_HANDLE* m) { + static char name[] = "lwmem_mutex"; + return tx_mutex_create(m, name, TX_INHERIT) == TX_SUCCESS; +} + +uint8_t +lwmem_sys_mutex_isvalid(LWMEM_CFG_OS_MUTEX_HANDLE* m) { + return m->tx_mutex_id == TX_MUTEX_ID; +} + +uint8_t +lwmem_sys_mutex_wait(LWMEM_CFG_OS_MUTEX_HANDLE* m) { + return tx_mutex_get(m, TX_WAIT_FOREVER) == TX_SUCCESS; +} + +uint8_t +lwmem_sys_mutex_release(LWMEM_CFG_OS_MUTEX_HANDLE* m) { + return tx_mutex_put(m) == TX_SUCCESS; +} + +#endif /* LWMEM_CFG_OS && !__DOXYGEN__ */ diff --git a/lwmem/src/system/lwmem_sys_win32.c b/lwmem/src/system/lwmem_sys_win32.c index 5fdb647..0a7bb8e 100644 --- a/lwmem/src/system/lwmem_sys_win32.c +++ b/lwmem/src/system/lwmem_sys_win32.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2020 Tilen MAJERLE + * Copyright (c) 2023 Tilen MAJERLE * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,7 +29,7 @@ * This file is part of LwMEM - Lightweight dynamic memory manager library. * * Author: Tilen MAJERLE - * Version: v2.0.0 + * Version: v2.1.0 */ #include "system/lwmem_sys.h" diff --git a/tests/lwmem_test.c b/tests/lwmem_test.c index e3b33d6..3737c2b 100644 --- a/tests/lwmem_test.c +++ b/tests/lwmem_test.c @@ -54,8 +54,8 @@ lw_c_regions[] = { void lwmem_test_run(void) { - void* ptr_1, * ptr_2, * ptr_3, * ptr_4; - void* ptr_c_1, * ptr_c_2, * ptr_c_3, * ptr_c_4; + void* ptr_1, * ptr_2, * ptr_3; + void* ptr_c_1, * ptr_c_2, * ptr_c_3; /* Initialize default lwmem instance */ /* Use one of 2 possible function calls: */