Merge branch 'develop'

This commit is contained in:
Tilen Majerle 2023-01-31 07:56:00 +01:00
commit c1463a4025
95 changed files with 2766 additions and 1192 deletions

193
.clang-format Normal file
View File

@ -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
---

View File

@ -2,22 +2,12 @@
"version": 4, "version": 4,
"configurations": [ "configurations": [
{ {
/*
* Full configuration is provided by CMake plugin for vscode,
* that shall be installed by user
*/
"name": "Win32", "name": "Win32",
"includePath": [ "intelliSenseMode": "${default}",
"${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",
"configurationProvider": "ms-vscode.cmake-tools" "configurationProvider": "ms-vscode.cmake-tools"
} }
] ]

7
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"recommendations": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools",
"twxs.cmake",
]
}

10
.vscode/launch.json vendored
View File

@ -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", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
/* GDB must in be in the PATH environment */
"name": "(Windows) Launch", "name": "(Windows) Launch",
"type": "cppdbg", "type": "cppdbg",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}\\build\\LwLibPROJECT.exe", "program": "${command:cmake.launchTargetPath}",
"miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe",
"args": [], "args": [],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${fileDirname}", "cwd": "${fileDirname}",
"environment": [], "environment": []
"console": "integratedTerminal"
} }
] ]
} }

10
.vscode/settings.json vendored Normal file
View File

@ -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": ""
}

57
.vscode/tasks.json vendored
View File

@ -1,19 +1,11 @@
{ {
"version": "2.0.0", "version": "2.1.0",
/* For this builds, you need
*
* - Ninja build system
* - MSYS2 compiler with ninja support
* - C/C++ extension for VSCode
* - CMake-Tools extension for VSCode
*/
"tasks": [ "tasks": [
{ {
"type": "cppbuild", "type": "cppbuild",
"label": "Build project", "label": "Build project",
"command": "cmake", "command": "cmake",
"args": ["--build", "\"build\""], "args": ["--build", "${command:cmake.buildDirectory}", "-j", "8"],
"options": { "options": {
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"
}, },
@ -27,7 +19,7 @@
"type": "shell", "type": "shell",
"label": "Re-build project", "label": "Re-build project",
"command": "cmake", "command": "cmake",
"args": ["--build", "\"build\"", "--clean-first", "-v"], "args": ["--build", "${command:cmake.buildDirectory}", "--clean-first", "-v", "-j", "8"],
"options": { "options": {
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"
}, },
@ -37,7 +29,7 @@
"type": "shell", "type": "shell",
"label": "Clean project", "label": "Clean project",
"command": "cmake", "command": "cmake",
"args": ["--build", "\"build\"", "--target", "clean"], "args": ["--build", "${command:cmake.buildDirectory}", "--target", "clean"],
"options": { "options": {
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"
}, },
@ -46,9 +38,48 @@
{ {
"type": "shell", "type": "shell",
"label": "Run application", "label": "Run application",
"command": "${workspaceFolder}\\build\\LwLibPROJECT.exe", "command": "${command:cmake.launchTargetPath}",
"args": [], "args": [],
"problemMatcher": [], "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": []
}
] ]
} }

View File

@ -2,6 +2,15 @@
## Develop ## 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 ## v2.0.0
- Remove `len` parameter for regions definition. Affected functions: `lwmem_assignmem` and `lwmem_assignmem_ex` - Remove `len` parameter for regions definition. Affected functions: `lwmem_assignmem` and `lwmem_assignmem_ex`

View File

@ -1,28 +1,46 @@
cmake_minimum_required(VERSION 3.0.0) cmake_minimum_required(VERSION 3.22)
project(LwLibPROJECT VERSION 0.1.0)
include(CTest) # Setup project
enable_testing() project(LwLibPROJECT)
add_executable(${PROJECT_NAME} if(NOT PROJECT_IS_TOP_LEVEL)
lwmem/src/lwmem/lwmem.c add_subdirectory(lwmem)
lwmem/src/system/lwmem_sys_win32.c else()
tests/lwmem_test.c # Set as executable
dev/VisualStudio/main.c 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
) )
target_include_directories(${PROJECT_NAME} PRIVATE # Add key include paths
dev/VisualStudio target_include_directories(${PROJECT_NAME} PUBLIC
lwmem/src/include ${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/dev
) )
target_compile_definitions(${PROJECT_NAME} PRIVATE # Compilation definition information
WIN32 target_compile_definitions(${PROJECT_NAME} PUBLIC
_DEBUG WIN32
CONSOLE _DEBUG
LWMEM_DEV CONSOLE
LWMEM_DEV
) )
set(CPACK_PROJECT_NAME ${PROJECT_NAME}) # Compiler options
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) target_compile_options(${PROJECT_NAME} PRIVATE
include(CPack) -Wall
-Wextra
-Wpedantic
)
# 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()

40
CMakePresets.json Normal file
View File

@ -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"
}
]
}

View File

@ -1,6 +1,6 @@
MIT License 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -14,6 +14,7 @@
* Supports automotive applications * Supports automotive applications
* Supports advanced free/realloc algorithms to optimize memory usage * Supports advanced free/realloc algorithms to optimize memory usage
* Operating system ready, thread-safe API * Operating system ready, thread-safe API
* C++ wrapper functions
* User friendly MIT license * User friendly MIT license
## Contribute ## Contribute

View File

@ -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)

View File

@ -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)

View File

@ -1,14 +0,0 @@
#include <stdio.h>
#include "lwmem/lwmem.h"
#include <string.h>
#include <stdint.h>
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;
}

View File

@ -73,7 +73,7 @@
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>..\..\lwmem\src\include;.;$(IncludePath)</IncludePath> <IncludePath>..\lwmem\src\include;.;$(IncludePath)</IncludePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
@ -143,9 +143,9 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\lwmem\src\lwmem\lwmem.c" /> <ClCompile Include="..\lwmem\src\lwmem\lwmem.c" />
<ClCompile Include="..\..\lwmem\src\system\lwmem_sys_win32.c" /> <ClCompile Include="..\lwmem\src\system\lwmem_sys_win32.c" />
<ClCompile Include="..\..\tests\lwmem_test.c" /> <ClCompile Include="..\tests\lwmem_test.c" />
<ClCompile Include="main.c" /> <ClCompile Include="main.c" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -16,13 +16,13 @@
<ClCompile Include="main.c"> <ClCompile Include="main.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\lwmem\src\lwmem\lwmem.c"> <ClCompile Include="..\lwmem\src\lwmem\lwmem.c">
<Filter>Source Files\LWMEM</Filter> <Filter>Source Files\LWMEM</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\lwmem\src\system\lwmem_sys_win32.c"> <ClCompile Include="..\lwmem\src\system\lwmem_sys_win32.c">
<Filter>Source Files\LWMEM</Filter> <Filter>Source Files\LWMEM</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\tests\lwmem_test.c"> <ClCompile Include="..\tests\lwmem_test.c">
<Filter>Source Files\Tests</Filter> <Filter>Source Files\Tests</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

24
dev/main.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "lwmem/lwmem.h"
#include "lwmem/lwmem.hpp"
#include <iostream>
#include <stdint.h>
#include <string.h>
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;
}

View File

@ -10,3 +10,4 @@ When any of the settings shall be modified, it shall be done in dedicated applic
Check :ref:`getting_started` for guidelines on how to create and use configuration file. Check :ref:`getting_started` for guidelines on how to create and use configuration file.
.. doxygengroup:: LWMEM_OPT .. doxygengroup:: LWMEM_OPT
:inner:

6
docs/changelog/index.rst Normal file
View File

@ -0,0 +1,6 @@
.. _changelof:
Changelog
=========
.. literalinclude:: ../../CHANGELOG.md

View File

@ -23,15 +23,25 @@ subprocess.call('doxygen doxyfile.doxy', shell=True)
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
project = 'LwMEM' project = 'LwMEM'
copyright = '2020, Tilen MAJERLE' copyright = '2022, Tilen MAJERLE'
author = 'Tilen MAJERLE' author = 'Tilen MAJERLE'
# Try to get branch at which this is running # Try to get branch at which this is running
# and try to determine which version to display in sphinx # 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 = '' version = ''
git_branch = '' 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 # Get current branch
res = os.popen('git branch').read().strip() res = os.popen('git branch').read().strip()
for line in res.split("\n"): for line in res.split("\n"):
@ -41,17 +51,18 @@ for line in res.split("\n"):
# Decision for display version # Decision for display version
git_branch = git_branch.replace('(HEAD detached at ', '').replace(')', '') git_branch = git_branch.replace('(HEAD detached at ', '').replace(')', '')
if git_branch.find('master') >= 0 or git_branch.find('main') >= 0: if git_branch.find('master') >= 0 or git_branch.find('main') >= 0:
version = os.popen('git describe --tags --abbrev=0').read().strip() #version = os.popen('git describe --tags --abbrev=0').read().strip()
if version == '': version = 'latest-stable'
version = 'v0.0.0' elif git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0:
elif git_branch.find('develop') != -1 and not (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' version = 'latest-develop'
else: else:
version = 'branch-' + git_branch version = os.popen('git describe --tags --abbrev=0').read().strip()
# For debugging purpose only # For debugging purpose only
print("GIT BRANCH: " + git_branch) print("GIT BRANCH: " + git_branch)
print("GIT VERSION: " + version) print("PROJ VERSION: " + version)
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
@ -115,20 +126,19 @@ html_static_path = ['static']
html_css_files = [ html_css_files = [
'css/common.css', 'css/common.css',
'css/custom.css', 'css/custom.css',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css',
] ]
html_js_files = [ html_js_files = [
'https://kit.fontawesome.com/3102794088.js' ''
] ]
# Master index file
master_doc = 'index' master_doc = 'index'
# # --- Breathe configuration -----------------------------------------------------
# Breathe configuration
#
#
#
breathe_projects = { breathe_projects = {
"lwmem": "_build/xml/" "lwmem": "_build/xml/"
} }
breathe_default_project = "lwmem" breathe_default_project = "lwmem"
breathe_default_members = ('members', 'undoc-members') breathe_default_members = ('members', 'undoc-members')
breathe_show_enumvalue_initializer = True

View File

@ -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: 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 <https://visualstudio.microsoft.com/vs/community/>`_ projects * WIN32 examples, prepared as `CMake` projects, ready for `MSYS2 GCC compiler`
* ARM Cortex-M examples for STM32, prepared as `STM32CubeIDE <https://www.st.com/en/development-tools/stm32cubeide.html>`_ GCC projects * ARM Cortex-M examples for STM32, prepared as `STM32CubeIDE <https://www.st.com/en/development-tools/stm32cubeide.html>`_ GCC projects. These are also supported in *Visual Studio Code* through *CMake* and *ninja* build system. `Dedicated tutorial <https://github.com/MaJerle/stm32-cube-cmake-vscode>`_ is available to get started in *VSCode*.
.. warning:: .. warning::
Library is platform independent and can be used on any platform. 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 WIN32
***** *****
Examples for *WIN32* are prepared as `Visual Studio Community <https://visualstudio.microsoft.com/vs/community/>`_ projects. Examples for *WIN32* are CMake-ready and *VSCode*-ready.
You can directly open project in the IDE, compile & debug. 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 <project name>`` to configure cmake and later ``cmake --build --preset <project name>`` to compile the project
STM32 STM32
***** *****

View File

@ -13,10 +13,10 @@ Download library
Library is primarly hosted on `Github <https://github.com/MaJerle/lwmem>`_. Library is primarly hosted on `Github <https://github.com/MaJerle/lwmem>`_.
You can get it with: You can get it by:
* Downloading latest release from `releases area <https://github.com/MaJerle/lwmem/releases>`_ on Github * Downloading latest release from `releases area <https://github.com/MaJerle/lwmem/releases>`_ on Github
* Cloning ``master`` branch for latest stable version * Cloning ``main`` branch for latest stable version
* Cloning ``develop`` branch for latest development * Cloning ``develop`` branch for latest development
Download from releases 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. * Make sure ``git`` is installed.
* Open console and navigate to path in the system to clone repository to. Use command ``cd your_path`` * 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 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 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 * Navigate to ``examples`` directory and run favourite example
Update cloned to latest version Update cloned to latest version
""""""""""""""""""""""""""""""" """""""""""""""""""""""""""""""
* Open console and navigate to path in the system where your resources repository is. Use command ``cd your_path`` * Open console and navigate to path in the system where your repository is located. 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 main`` command to get latest changes on ``main`` 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 pull origin develop`` command to get latest changes on ``develop`` branch
* Run ``git submodule foreach git pull origin master`` to update & merge all submodules * Run ``git submodule update --init --remote`` to update submodules to latest version
.. note:: .. note::
This is preferred option to use when you want to evaluate library and run prepared examples. This is preferred option to use when you want to evaluate library and run prepared examples.

View File

@ -26,6 +26,7 @@ Features
* Supports automotive applications * Supports automotive applications
* Supports advanced free/realloc algorithms to optimize memory usage * Supports advanced free/realloc algorithms to optimize memory usage
* Operating system ready, thread-safe API * Operating system ready, thread-safe API
* C++ wrapper functions
* User friendly MIT license * User friendly MIT license
Requirements Requirements
@ -58,9 +59,31 @@ Table of contents
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Contents
self self
get-started/index get-started/index
user-manual/index user-manual/index
api-reference/index api-reference/index
examples/index examples/index
changelog/index
.. toctree::
:maxdepth: 2
:caption: Other projects
:hidden:
LwBTN - Button manager <https://github.com/MaJerle/lwbtn>
LwDTC - DateTimeCron <https://github.com/MaJerle/lwdtc>
LwESP - ESP-AT library <https://github.com/MaJerle/lwesp>
LwEVT - Event manager <https://github.com/MaJerle/lwevt>
LwGPS - GPS NMEA parser <https://github.com/MaJerle/lwgps>
LwGSM - GSM-AT library <https://github.com/MaJerle/lwgsm>
LwJSON - JSON parser <https://github.com/MaJerle/lwjson>
LwMEM - Memory manager <https://github.com/MaJerle/lwmem>
LwOW - OneWire with UART <https://github.com/MaJerle/lwow>
LwPKT - Packet protocol <https://github.com/MaJerle/lwpkt>
LwPRINTF - Printf <https://github.com/MaJerle/lwprintf>
LwRB - Ring buffer <https://github.com/MaJerle/lwrb>
LwSHELL - Shell <https://github.com/MaJerle/lwshell>
LwUTIL - Utility functions <https://github.com/MaJerle/lwutil>

View File

@ -2,7 +2,7 @@ breathe>=4.9.1
colorama colorama
docutils==0.16 docutils==0.16
sphinx>=3.5.1 sphinx>=3.5.1
sphinx_rtd_theme sphinx_rtd_theme>=1.0.0
sphinx-tabs sphinx-tabs
sphinxcontrib-svg2pdfconverter sphinxcontrib-svg2pdfconverter
sphinx-sitemap sphinx-sitemap

1
docs/static/dark-light/checked.svg vendored Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>

After

Width:  |  Height:  |  Size: 269 B

View File

@ -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%);
}

View File

@ -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 = `<style>*,::after,::before{box-sizing:border-box}:host{contain:content;display:block}:host([hidden]){display:none}form{background-color:var(--${NAME}-background-color,transparent);color:var(--${NAME}-color,inherit);padding:0}fieldset{border:none;margin:0;padding-block:.25rem;padding-inline:.25rem}legend{font:var(--${NAME}-legend-font,inherit);padding:0}input,label{cursor:pointer}label{white-space:nowrap}input{opacity:0;position:absolute;pointer-events:none}input:focus-visible+label{outline:#e59700 auto 2px;outline:-webkit-focus-ring-color auto 5px}label:not(:empty)::before{margin-inline-end:.5rem;}label::before{content:"";display:inline-block;background-size:var(--${NAME}-icon-size,1rem);background-repeat:no-repeat;height:var(--${NAME}-icon-size,1rem);width:var(--${NAME}-icon-size,1rem);vertical-align:middle;}[part=lightLabel]::before{background-image:var(--${NAME}-light-icon, url("${DEFAULT_URL}sun.png"))}[part=darkLabel]::before{filter:var(--${NAME}-icon-filter, none);background-image:var(--${NAME}-dark-icon, url("${DEFAULT_URL}moon.png"))}[part=toggleLabel]::before{background-image:var(--${NAME}-checkbox-icon,none)}[part=permanentLabel]::before{background-image:var(--${NAME}-remember-icon-unchecked, url("${DEFAULT_URL}unchecked.svg"))}[part=darkLabel],[part=lightLabel],[part=toggleLabel]{font:var(--${NAME}-label-font,inherit)}[part=darkLabel]:empty,[part=lightLabel]:empty,[part=toggleLabel]:empty{font-size:0;padding:0}[part=permanentLabel]{font:var(--${NAME}-remember-font,inherit)}input:checked+[part=permanentLabel]::before{background-image:var(--${NAME}-remember-icon-checked, url("${DEFAULT_URL}checked.svg"))}input:checked+[part=darkLabel],input:checked+[part=lightLabel]{background-color:var(--${NAME}-active-mode-background-color,transparent)}input:checked+[part=darkLabel]::before,input:checked+[part=lightLabel]::before{background-color:var(--${NAME}-active-mode-background-color,transparent)}input:checked+[part=toggleLabel]::before{filter:var(--${NAME}-icon-filter, none)}input:checked+[part=toggleLabel]+aside [part=permanentLabel]::before{filter:var(--${NAME}-remember-filter, invert(100%))}aside{visibility:hidden;margin-block-start:.15rem}[part=darkLabel]:focus-visible~aside,[part=lightLabel]:focus-visible~aside,[part=toggleLabel]:focus-visible~aside{visibility:visible;transition:visibility 0s}aside [part=permanentLabel]:empty{display:none}@media (hover:hover){aside{transition:visibility 3s}aside:hover{visibility:visible}[part=darkLabel]:hover~aside,[part=lightLabel]:hover~aside,[part=toggleLabel]:hover~aside{visibility:visible;transition:visibility 0s}}</style><form part=form><fieldset part=fieldset><legend part=legend></legend><input part=lightRadio id=l name=mode type=radio><label part=lightLabel for=l></label><input part=darkRadio id=d name=mode type=radio><label part=darkLabel for=d></label><input part=toggleCheckbox id=t type=checkbox><label part=toggleLabel for=t></label><aside part=aside><input part=permanentCheckbox id=p type=checkbox><label part=permanentLabel for=p></label></aside></fieldset></form>`;
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);

36
docs/static/dark-light/dark.css vendored Normal file
View File

@ -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;
}

24
docs/static/dark-light/light.css vendored Normal file
View File

@ -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%);
}

BIN
docs/static/dark-light/moon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

7
docs/static/dark-light/moon.svg vendored Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<title>
moon
</title>
<path d="M17.39 15.14A7.33 7.33 0 0 1 11.75 1.6c.23-.11.56-.23.79-.34a8.19 8.19 0 0 0-5.41.45 9 9 0 1 0 7 16.58 8.42 8.42 0 0 0 4.29-3.84 5.3 5.3 0 0 1-1.03.69z"/>
</svg>

After

Width:  |  Height:  |  Size: 326 B

BIN
docs/static/dark-light/sun.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

5
docs/static/dark-light/sun.svg vendored Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
<path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
<circle cx="12" cy="11" r="4"/>
</svg>

After

Width:  |  Height:  |  Size: 569 B

1
docs/static/dark-light/unchecked.svg vendored Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@ -1,5 +1,5 @@
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
* Portions Copyright <EFBFBD> 2017 STMicroelectronics International N.V. All rights reserved. * Portions Copyright <EFBFBD> 2017 STMicroelectronics International N.V. All rights reserved.
* Portions Copyright (c) 2013-2017 ARM Limited. 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: * Control functions for short timeouts in microsecond resolution:
* Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
* Removed: osSignalGet * Removed: osSignalGet
* Version 2.0.0 * Version 2.1.0
* OS objects creation without macros (dynamic creation and resource allocation): * OS objects creation without macros (dynamic creation and resource allocation):
* - added: osXxxxNew functions which replace osXxxxCreate * - added: osXxxxNew functions which replace osXxxxCreate
* - added: osXxxxAttr_t structures * - added: osXxxxAttr_t structures

View File

@ -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}"
}
]
}

View File

@ -0,0 +1,10 @@
{
"recommendations": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools",
"marus25.cortex-debug",
"twxs.cmake",
"dan-c-underwood.arm",
"zixuanwang.linkerscript"
]
}

View File

@ -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"],
}
]
}

View File

@ -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=<yourserialnumber>",
"--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": []
},
]
}

View File

@ -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
$<$<COMPILE_LANGUAGE:C>: ${symbols_c_SYMB}>
$<$<COMPILE_LANGUAGE:CXX>: ${symbols_cxx_SYMB}>
$<$<COMPILE_LANGUAGE:ASM>: ${symbols_asm_SYMB}>
# Configuration specific
$<$<CONFIG:Debug>:
DEBUG
>
$<$<CONFIG:Release>: >
)
#
# Add include paths for each of the compiler
#
target_include_directories(${EXECUTABLE} PRIVATE
# Language specific only
$<$<COMPILE_LANGUAGE:C>: ${include_c_DIRS}>
$<$<COMPILE_LANGUAGE:CXX>: ${include_cxx_DIRS}>
$<$<COMPILE_LANGUAGE:ASM>: ${include_asm_DIRS}>
# Configuration specific
$<$<CONFIG:Debug>: >
$<$<CONFIG:Release>: >
)
# Compiler and linker options
target_compile_options(${EXECUTABLE} PRIVATE
${CPU_PARAMETERS}
-Wall
-Wextra
-Wpedantic
-Wno-unused-parameter
$<$<COMPILE_LANGUAGE:C>:
>
$<$<COMPILE_LANGUAGE:CXX>:
#-Wno-volatile
#-Wold-style-cast
#-Wuseless-cast
#-Wsuggest-override
>
$<$<COMPILE_LANGUAGE:ASM>:
-x assembler-with-cpp
-MMD
-MP
>
$<$<CONFIG:Debug>:
-Og -g3 -ggdb
>
$<$<CONFIG:Release>:
-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} $<TARGET_FILE:${EXECUTABLE}>
)
# Convert output to hex and binary
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.hex
)
# Convert to bin file -> add conditional check?
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.bin
)
message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")

View File

@ -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"
}
}
]
}

View File

@ -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)

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -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}"
}
]
}

View File

@ -0,0 +1,10 @@
{
"recommendations": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools",
"marus25.cortex-debug",
"twxs.cmake",
"dan-c-underwood.arm",
"zixuanwang.linkerscript"
]
}

View File

@ -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"],
}
]
}

View File

@ -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=<yourserialnumber>",
"--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": []
},
]
}

View File

@ -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
$<$<COMPILE_LANGUAGE:C>: ${symbols_c_SYMB}>
$<$<COMPILE_LANGUAGE:CXX>: ${symbols_cxx_SYMB}>
$<$<COMPILE_LANGUAGE:ASM>: ${symbols_asm_SYMB}>
# Configuration specific
$<$<CONFIG:Debug>:
DEBUG
>
$<$<CONFIG:Release>: >
)
#
# Add include paths for each of the compiler
#
target_include_directories(${EXECUTABLE} PRIVATE
# Language specific only
$<$<COMPILE_LANGUAGE:C>: ${include_c_DIRS}>
$<$<COMPILE_LANGUAGE:CXX>: ${include_cxx_DIRS}>
$<$<COMPILE_LANGUAGE:ASM>: ${include_asm_DIRS}>
# Configuration specific
$<$<CONFIG:Debug>: >
$<$<CONFIG:Release>: >
)
# Compiler and linker options
target_compile_options(${EXECUTABLE} PRIVATE
${CPU_PARAMETERS}
-Wall
-Wextra
-Wpedantic
-Wno-unused-parameter
$<$<COMPILE_LANGUAGE:C>:
>
$<$<COMPILE_LANGUAGE:CXX>:
#-Wno-volatile
#-Wold-style-cast
#-Wuseless-cast
#-Wsuggest-override
>
$<$<COMPILE_LANGUAGE:ASM>:
-x assembler-with-cpp
-MMD
-MP
>
$<$<CONFIG:Debug>:
-Og -g3 -ggdb
>
$<$<CONFIG:Release>:
-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} $<TARGET_FILE:${EXECUTABLE}>
)
# Convert output to hex and binary
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.hex
)
# Convert to bin file -> add conditional check?
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.bin
)
message("Exiting ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")

View File

@ -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"
}
}
]
}

View File

@ -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)

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -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"
}
]
}

View File

@ -0,0 +1,7 @@
{
"recommendations": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools",
"twxs.cmake",
]
}

19
examples/win32/.vscode/launch.json vendored Normal file
View File

@ -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": []
}
]
}

13
examples/win32/.vscode/settings.json vendored Normal file
View File

@ -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": ""
}

46
examples/win32/.vscode/tasks.json vendored Normal file
View File

@ -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": [],
}
]
}

View File

@ -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)

View File

@ -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"
}
]
}

9
examples/win32/README.md Normal file
View File

@ -0,0 +1,9 @@
# WIN32 examples
Examples are provided as CMake sources.
To run then, you can use VSCode or CMake directly.
```
cmake --preset <example_preset_from_CMakePresets.json_file>
cmake --build --preset <example_preset_from_CMakePresets.json_file>
```

View File

@ -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("-------------------------------")

View File

@ -1,162 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c" />
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{85F83F03-72F0-4F31-B7D3-294DA7D64D4E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>LwMEMexamples</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>.;..\..\..\lwmem\src\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="LwMEM">
<UniqueIdentifier>{9e597c89-5586-4692-864f-7152981cc7cf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c" />
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c">
<Filter>LwMEM</Filter>
</ClCompile>
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c">
<Filter>LwMEM</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -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

View File

@ -1,162 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c" />
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{435D03A4-B3C0-4BC2-B739-542366BFBFAE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>LwMEMexamples</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>.;..\..\..\lwmem\src\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="LwMEM">
<UniqueIdentifier>{9e597c89-5586-4692-864f-7152981cc7cf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c" />
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c">
<Filter>LwMEM</Filter>
</ClCompile>
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c">
<Filter>LwMEM</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -75,6 +75,9 @@ main(void) {
lw1_ptr1 = lwmem_malloc_ex(&lw1, NULL, 24); /* Allocate memory from custom LwMEM instance, any region */ 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 */ 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 */ /* Free memory after use */
lwmem_free_ex(&lw1, lw0_ptr1); lwmem_free_ex(&lw1, lw0_ptr1);
lwmem_free_ex(&lw1, lw0_ptr2); lwmem_free_ex(&lw1, lw0_ptr2);

View File

@ -1,162 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c" />
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{145E0F0F-D703-44A2-9375-7AD2E4EAB363}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>LwMEMexamples</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>.;..\..\..\lwmem\src\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="LwMEM">
<UniqueIdentifier>{9e597c89-5586-4692-864f-7152981cc7cf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c" />
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c">
<Filter>LwMEM</Filter>
</ClCompile>
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c">
<Filter>LwMEM</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation

View File

@ -1,162 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c" />
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{34D02135-7971-49BD-8933-88A9B27D0A86}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>LwMEMexamples</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>.;..\..\..\lwmem\src\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="LwMEM">
<UniqueIdentifier>{9e597c89-5586-4692-864f-7152981cc7cf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c" />
<ClCompile Include="..\..\..\lwmem\src\lwmem\lwmem.c">
<Filter>LwMEM</Filter>
</ClCompile>
<ClCompile Include="..\..\..\lwmem\src\system\lwmem_sys_win32.c">
<Filter>LwMEM</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -45,17 +45,17 @@ static int
thread_func(void* arg) { thread_func(void* arg) {
void* ptr, * ptr2; void* ptr, * ptr2;
(void)arg;
/* Allocate memory */ /* Allocate memory */
ptr = lwmem_malloc(24); if ((ptr = lwmem_malloc(24)) == NULL) {
if (ptr == NULL) {
printf("Could not allocate memory!\r\n"); printf("Could not allocate memory!\r\n");
return -1; return -1;
} }
printf("Memory allocated at address 0x%p!\r\n", ptr); printf("Memory allocated at address 0x%p!\r\n", ptr);
/* Increase its size */ /* Increase its size */
ptr2 = lwmem_realloc(ptr, 48); if ((ptr2 = lwmem_realloc(ptr, 48)) == NULL) {
if (ptr2 == NULL) {
printf("Could not reallocate existing ptr\r\n"); printf("Could not reallocate existing ptr\r\n");
} else { } else {
printf("Memory reallocated at address 0x%p!\r\n", ptr2); printf("Memory reallocated at address 0x%p!\r\n", ptr2);

View File

@ -1,34 +1,33 @@
{ {
"name": "LwMEM", "name": "LwMEM",
"version": "2.0.0", "version": "2.1.0",
"description": "Lightweight dynamic memory manager optimized for embedded systems", "description": "Lightweight dynamic memory manager optimized for embedded systems",
"keywords": "lwmem, memory, dynamic, heap, malloc, calloc, realloc, free, lightweight, manager, embedded, stm32, win32", "keywords": "lwmem, memory, dynamic, heap, malloc, calloc, realloc, free, lightweight, manager, embedded, stm32, win32",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/MaJerle/lwmem.git" "url": "https://github.com/MaJerle/lwmem.git"
}, },
"authors": [ "authors": [
{ {
"name": "Tilen Majerle", "name": "Tilen Majerle",
"email": "tilen@majerle.eu", "email": "tilen@majerle.eu",
"url": "https://majerle.eu" "url": "https://majerle.eu"
} }
], ],
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/MaJerle/lwmem", "homepage": "https://github.com/MaJerle/lwmem",
"dependencies": { "dependencies": {},
"frameworks": "*",
}, "platforms": "*",
"frameworks": "*", "export": {
"platforms": "*", "exclude": [
"export": { ".github",
"exclude": [ "dev",
".github", "docs",
"dev" "**/.vs",
"docs", "**/Debug",
"**/.vs", "build",
"**/Debug", "**/build"
"build", ]
] }
}
} }

23
lwmem/CMakeLists.txt Normal file
View File

@ -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")

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation
@ -29,13 +29,13 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library. * This file is part of LwMEM - Lightweight dynamic memory manager library.
* *
* Author: Tilen MAJERLE <tilen@majerle.eu> * Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0 * Version: v2.1.0
*/ */
#ifndef LWMEM_HDR_H #ifndef LWMEM_HDR_H
#define LWMEM_HDR_H #define LWMEM_HDR_H
#include <stdint.h>
#include <limits.h> #include <limits.h>
#include <stdint.h>
#include "lwmem/lwmem_opt.h" #include "lwmem/lwmem_opt.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -53,15 +53,15 @@ extern "C" {
* \param[in] x: Object to get array size of * \param[in] x: Object to get array size of
* \return Number of elements in array * \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 * \brief Memory block structure
*/ */
typedef struct lwmem_block { typedef struct lwmem_block {
struct lwmem_block* next; /*!< Next free memory block on linked list. struct lwmem_block*
Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */ 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. size_t size; /*!< Size of block, including metadata part.
MSB bit is set to `1` when block is allocated and in use, MSB bit is set to `1` when block is allocated and in use,
or `0` when block is considered free */ or `0` when block is considered free */
} lwmem_block_t; } lwmem_block_t;
@ -70,46 +70,53 @@ typedef struct lwmem_block {
* \brief Statistics structure * \brief Statistics structure
*/ */
typedef struct { typedef struct {
uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */ uint32_t mem_size_bytes; /*!< Total memory size of all regions combined */
uint32_t nr_free; /*!< Number of frees in the LwMEM instance */ 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; } lwmem_stats_t;
/** /**
* \brief LwMEM main structure * \brief LwMEM main structure
*/ */
typedef struct lwmem { typedef struct lwmem {
lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */ 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 */ 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_available_bytes; /*!< Memory size available for allocation */
size_t mem_regions_count; /*!< Number of regions used for allocation */ size_t mem_regions_count; /*!< Number of regions used for allocation */
#if LWMEM_CFG_OS || __DOXYGEN__ #if LWMEM_CFG_OS || __DOXYGEN__
LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */ LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */
#endif /* LWMEM_CFG_OS || __DOXYGEN__ */ #endif /* LWMEM_CFG_OS || __DOXYGEN__ */
#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ #if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__
lwmem_stats_t stats; /*!< Statistics */ lwmem_stats_t stats; /*!< Statistics */
#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ #endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */
#if defined(LWMEM_DEV) && !__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 */ 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; } lwmem_t;
/** /**
* \brief Memory region descriptor * \brief Memory region descriptor
*/ */
typedef struct { typedef struct {
void* start_addr; /*!< Region start address */ void* start_addr; /*!< Region start address */
size_t size; /*!< Size of region in units of bytes */ size_t size; /*!< Size of region in units of bytes */
} lwmem_region_t; } lwmem_region_t;
size_t lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions); size_t lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions);
void* lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t size); void* lwmem_malloc_ex(lwmem_t* lwobj, 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_calloc_ex(lwmem_t* lwobj, 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); 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* const lw, 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* const lw, void* const ptr); void lwmem_free_ex(lwmem_t* lwobj, void* const ptr);
void lwmem_free_s_ex(lwmem_t* const lw, void** const ptr); void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr);
size_t lwmem_get_size_ex(lwmem_t* const lw, void* 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. * \note This is a wrapper for \ref lwmem_assignmem_ex function.
@ -128,7 +135,7 @@ lwmem_region_t regions[] = {
\endcode \endcode
* \return `0` on failure, number of final regions used for memory manager on success * \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. * \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 * \return Pointer to allocated memory on success, `NULL` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled * \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. * \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 * \return Pointer to allocated memory on success, `NULL` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled * \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. * \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 * \return Pointer to allocated memory on success, `NULL` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled * \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. * \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 * \return `1` if successfully reallocated, `0` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled * \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. * \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 * \param[in] ptr: Memory to free. `NULL` pointer is valid input
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled * \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. * \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` * 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 * \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. * \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 * \param[in] ptr: Pointer to allocated memory
* \return Block size for user in units of bytes * \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__ #if defined(LWMEM_DEV) && !__DOXYGEN__
unsigned char lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size); 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_save_state(void);
void lwmem_debug_restore_to_saved(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__ */ #endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */
/** /**

View File

@ -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 <tilen@majerle.eu>
* 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 <size_t LEN>
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 */

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation
@ -29,10 +29,10 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library. * This file is part of LwMEM - Lightweight dynamic memory manager library.
* *
* Author: Tilen MAJERLE <tilen@majerle.eu> * Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0 * Version: v2.1.0
*/ */
#ifndef LWMEM_HDR_OPT_H #ifndef LWMEM_OPT_HDR_H
#define LWMEM_HDR_OPT_H #define LWMEM_OPT_HDR_H
/* Uncomment to ignore user options (or set macro in compiler flags) */ /* Uncomment to ignore user options (or set macro in compiler flags) */
/* #define LWMEM_IGNORE_USER_OPTS */ /* #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. * \note When `LWMEM_CFG_OS` is enabled, user must implement functions in \ref LWMEM_SYS group.
*/ */
#ifndef LWMEM_CFG_OS #ifndef LWMEM_CFG_OS
#define LWMEM_CFG_OS 0 #define LWMEM_CFG_OS 0
#endif #endif
/** /**
@ -69,7 +69,7 @@ extern "C" {
* definition before you define handle type * definition before you define handle type
*/ */
#ifndef LWMEM_CFG_OS_MUTEX_HANDLE #ifndef LWMEM_CFG_OS_MUTEX_HANDLE
#define LWMEM_CFG_OS_MUTEX_HANDLE void * #define LWMEM_CFG_OS_MUTEX_HANDLE void*
#endif #endif
/** /**
@ -82,7 +82,7 @@ extern "C" {
* Usually alignment of `4` bytes fits to all processors. * Usually alignment of `4` bytes fits to all processors.
*/ */
#ifndef LWMEM_CFG_ALIGN_NUM #ifndef LWMEM_CFG_ALIGN_NUM
#define LWMEM_CFG_ALIGN_NUM ((size_t)4) #define LWMEM_CFG_ALIGN_NUM ((size_t)4)
#endif #endif
/** /**
@ -92,7 +92,7 @@ extern "C" {
* It is disabled by default since it has performance penalties. * It is disabled by default since it has performance penalties.
*/ */
#ifndef LWMEM_CFG_CLEAN_MEMORY #ifndef LWMEM_CFG_CLEAN_MEMORY
#define LWMEM_CFG_CLEAN_MEMORY 0 #define LWMEM_CFG_CLEAN_MEMORY 0
#endif #endif
/** /**
@ -100,7 +100,7 @@ extern "C" {
* *
*/ */
#ifndef LWMEM_CFG_ENABLE_STATS #ifndef LWMEM_CFG_ENABLE_STATS
#define LWMEM_CFG_ENABLE_STATS 0 #define LWMEM_CFG_ENABLE_STATS 0
#endif #endif
/** /**
@ -111,4 +111,4 @@ extern "C" {
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* LWMEM_HDR_OPT_H */ #endif /* LWMEM_OPT_HDR_H */

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation
@ -29,10 +29,10 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library. * This file is part of LwMEM - Lightweight dynamic memory manager library.
* *
* Author: Tilen MAJERLE <tilen@majerle.eu> * Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0 * Version: v2.1.0
*/ */
#ifndef LWMEM_HDR_OPTS_H #ifndef LWMEM_OPTS_HDR_H
#define LWMEM_HDR_OPTS_H #define LWMEM_OPTS_HDR_H
/* Rename this file to "lwmem_opts.h" for your application */ /* Rename this file to "lwmem_opts.h" for your application */
@ -41,4 +41,4 @@
* copy & replace here settings you want to change values * copy & replace here settings you want to change values
*/ */
#endif /* LWMEM_HDR_OPTS_H */ #endif /* LWMEM_OPTS_HDR_H */

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation
@ -29,19 +29,21 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library. * This file is part of LwMEM - Lightweight dynamic memory manager library.
* *
* Author: Tilen MAJERLE <tilen@majerle.eu> * Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0 * Version: v2.1.0
*/ */
#ifndef LWMEM_HDR_SYS_H #ifndef LWMEM_SYS_HDR_H
#define LWMEM_HDR_SYS_H #define LWMEM_SYS_HDR_H
#include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include "lwmem/lwmem.h" #include "lwmem/lwmem.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
#if LWMEM_CFG_OS || __DOXYGEN__
/** /**
* \defgroup LWMEM_SYS System functions * \defgroup LWMEM_SYS System functions
* \brief System functions when used with operating system * \brief System functions when used with operating system
@ -53,35 +55,37 @@ extern "C" {
* \param[out] m: Output variable to save mutex handle * \param[out] m: Output variable to save mutex handle
* \return `1` on success, `0` otherwise * \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 * \brief Check if mutex handle is valid
* \param[in] m: Mutex handle to check if valid * \param[in] m: Mutex handle to check if valid
* \return `1` on success, `0` otherwise * \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) * \brief Wait for a mutex until ready (unlimited time)
* \param[in] m: Mutex handle to wait for * \param[in] m: Mutex handle to wait for
* \return `1` on success, `0` otherwise * \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 * \brief Release already locked mutex
* \param[in] m: Mutex handle to release * \param[in] m: Mutex handle to release
* \return `1` on success, `0` otherwise * \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 #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* LWMEM_HDR_SYS_H */ #endif /* LWMEM_SYS_HDR_H */

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation
@ -29,24 +29,24 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library. * This file is part of LwMEM - Lightweight dynamic memory manager library.
* *
* Author: Tilen MAJERLE <tilen@majerle.eu> * Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0 * Version: v2.1.0
*/ */
#include "lwmem/lwmem.h"
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include "lwmem/lwmem.h"
#if LWMEM_CFG_OS #if LWMEM_CFG_OS
#include "system/lwmem_sys.h" #include "system/lwmem_sys.h"
#endif /* LWMEM_CFG_OS */ #endif /* LWMEM_CFG_OS */
#define LWMEM_MEMSET memset #define LWMEM_MEMSET memset
#define LWMEM_MEMCPY memcpy #define LWMEM_MEMCPY memcpy
#define LWMEM_MEMMOVE memmove #define LWMEM_MEMMOVE memmove
/** /**
* \brief Transform alignment number (power of `2`) to bits * \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 * \brief Aligns input value to next alignment bits
@ -63,93 +63,108 @@
* - Input: `7`; Output: `8` * - Input: `7`; Output: `8`
* - Input: `8`; 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 * \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 * \brief Cast input pointer to byte
* \param[in] p: Input pointer to cast to byte pointer * \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 * \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 * \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 * \brief Set block as allocated
* \param[in] block: Block to set 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 * \brief Check if input block is properly allocated and valid
* \param[in] block: Block to check if properly set as allocated * \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 * \brief Get block handle from application pointer
* \param[in] ptr: Input pointer to get block from * \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 * \brief Get block handle from application pointer
* \param[in] block: Input pointer to get block from * \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 * \brief Minimum amount of memory required to make new empty block
* *
* Default size is size of meta 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 * \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 * \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_b: Input block to find previous and its previous
* \param[in] in_pp: Previous previous of input block * \param[in] in_pp: Previous previous of input block
* \param[in] in_p: 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 { \ #define LWMEM_GET_PREV_CURR_OF_BLOCK(in_lwobj, in_b, in_pp, in_p) \
for ((in_pp) = NULL, (in_p) = &(LWMEM_GET_LW(in_lw)->start_block); \ do { \
(in_p) != NULL && (in_p)->next < (in_b); \ 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 \ (in_pp) = (in_p), (in_p) = (in_p)->next) {} \
) {} \
} while (0) } while (0)
#if LWMEM_CFG_OS #if LWMEM_CFG_OS
#define LWMEM_PROTECT(lw) lwmem_sys_mutex_wait(&(LWMEM_GET_LW(lw)->mutex)) #define LWMEM_PROTECT(lwobj) lwmem_sys_mutex_wait(&((lwobj)->mutex))
#define LWMEM_UNPROTECT(lw) lwmem_sys_mutex_release(&(LWMEM_GET_LW(lw)->mutex)) #define LWMEM_UNPROTECT(lwobj) lwmem_sys_mutex_release(&((lwobj)->mutex))
#else /* LWMEM_CFG_OS */ #else /* LWMEM_CFG_OS */
#define LWMEM_PROTECT(lw) #define LWMEM_PROTECT(lwobj)
#define LWMEM_UNPROTECT(lw) #define LWMEM_UNPROTECT(lwobj)
#endif /* !LWMEM_CFG_OS */ #endif /* !LWMEM_CFG_OS */
/* Statistics part */ /* Statistics part */
#if LWMEM_CFG_ENABLE_STATS #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 #else
#define LWMEM_INC_STATS(field) #define LWMEM_INC_STATS(field)
#define LWMEM_UPDATE_MIN_FREE(lwobj)
#endif /* LWMEM_CFG_ENABLE_STATS */ #endif /* LWMEM_CFG_ENABLE_STATS */
/** /**
@ -165,7 +180,7 @@ static lwmem_t lwmem_default;
* \return `1` if region valid, `0` otherwise * \return `1` if region valid, `0` otherwise
*/ */
static uint8_t 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; size_t mem_size;
uint8_t* mem_start_addr; 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; *ms = 0;
/* Check region size and align it to config bits */ /* 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)) { if (mem_size < (2 * LWMEM_BLOCK_MIN_SIZE)) {
return 0; 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 * Increase start address and decrease effective region size
*/ */
mem_start_addr = region->start_addr; 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_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)); 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 * \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 * \param[in] nb: New free block to insert into linked list
*/ */
static void 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; lwmem_block_t* prev;
/* Check valid inputs */ /* 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 * Try to find position to put new block in-between
* Search until all free block addresses are lower than entry block * 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 */ /* This is hard error with wrong memory usage */
if (prev == NULL) { 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 * By doing this, we protect data left by app
* and we make sure new allocations cannot see old information * 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 */ #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 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)) { 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 */ prev->size += nb->size; /* Increase current block by size of new block */
nb = prev; /* New block and current are now the same thing */ nb = prev; /* New block and current are now the same thing */
/* /*
* It is important to set new block as current one * It is important to set new block as current one
* as this allows merging previous and next blocks together with new block * as this allows merging previous and next blocks together with new block
* at the same time; follow next steps * 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 * 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) * 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)) { && (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? */ if (prev->next == lwobj->end_block) { /* Does it points to the end? */
nb->next = LWMEM_GET_LW(lw)->end_block; /* Set end block pointer */ nb->next = lwobj->end_block; /* Set end block pointer */
} else { } else {
nb->size += prev->next->size; /* Expand of current block for size of next free block which is right behind new block */ nb->size +=
nb->next = prev->next->next; /* Next free is pointed to the next one of previous next */ 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 { } 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 * \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] block: Pointer to block with size already set
* \param[in] new_block_size: New block size to be set * \param[in] new_block_size: New block size to be set
* \return `1` if block splitted, `0` otherwise * \return `1` if block splitted, `0` otherwise
*/ */
static uint8_t 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; lwmem_block_t* next;
size_t block_size, is_alloc_bit; size_t block_size, is_alloc_bit;
uint8_t success = 0; uint8_t success = 0;
is_alloc_bit = block->size & LWMEM_ALLOC_BIT; /* Check if allocation bit is set */ 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 */ block_size = block->size & ~LWMEM_ALLOC_BIT; /* Use size without allocated bit */
/* /*
* If current block size is greater than requested size, * 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 * and add it back to list of empty blocks
*/ */
if ((block_size - new_block_size) >= LWMEM_BLOCK_MIN_SIZE) { 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 = (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 */ next->size = block_size - new_block_size; /* Modify block data */
block->size = new_block_size; /* Current size is now smaller */ 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 */ lwobj->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 */ prv_insert_free_block(lwobj, next); /* Add new block to the free list */
success = 1; success = 1;
} else { } 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 * \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. * \param[in] region: Pointer to region to allocate from.
* Set to `NULL` for any region * Set to `NULL` for any region
* \param[in] size: Application wanted size, excluding size of meta header * \param[in] size: Application wanted size, excluding size of meta header
* \return Pointer to allocated memory, `NULL` otherwise * \return Pointer to allocated memory, `NULL` otherwise
*/ */
static void* static void*
prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) { prv_alloc(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) {
lwmem_block_t* prev, *curr; lwmem_block_t *prev, *curr;
void* retval = NULL; void* retval = NULL;
/* Calculate final size including meta data size */ /* Calculate final size including meta data size */
const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE;
/* Check if initialized and if size is in the limits */ /* 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; return NULL;
} }
/* Set default values */ /* Set default values */
prev = &(LWMEM_GET_LW(lw)->start_block); /* Use pointer from custom lwmem block */ prev = &(lwobj->start_block); /* Use pointer from custom lwmem block */
curr = prev->next; /* Curr represents first actual free block */ curr = prev->next; /* Curr represents first actual free block */
/* /*
* If region is not set to NULL, * 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) { for (; curr != NULL; prev = curr, curr = curr->next) {
/* Check bounds */ /* Check bounds */
if (curr->next == NULL || curr == LWMEM_GET_LW(lw)->end_block) { if (curr->next == NULL || curr == lwobj->end_block) {
return NULL; return NULL;
} }
if ((uint8_t*)curr < (uint8_t*)region_start_addr) { /* Check if we reached region */ if ((uint8_t*)curr < (uint8_t*)region_start_addr) { /* Check if we reached region */
continue; 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; return NULL;
} }
if (curr->size >= final_size) { if (curr->size >= final_size) {
break; /* Free block identified */ break; /* Free block identified */
} }
} }
} else { } 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 * Loop until size of current block is smaller than requested final size
*/ */
for (; curr != NULL && curr->size < final_size; prev = curr, curr = curr->next) { 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 */ if (curr->next == NULL || curr == lwobj->end_block) { /* If no more blocks available */
return NULL; /* No sufficient memory available to allocate block of memory */ 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 */ /* There is a valid block available */
retval = LWMEM_GET_PTR_FROM_BLOCK(curr); /* Return pointer does not include meta part */ 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 */ 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 */ /* curr block is now removed from linked list */
LWMEM_GET_LW(lw)->mem_available_bytes -= curr->size;/* Decrease available bytes by allocated block size */ lwobj->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 */ 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_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; return retval;
} }
/** /**
* \brief Free input pointer * \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 * \param[in] ptr: Input pointer to free
*/ */
static void 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); lwmem_block_t* const block = LWMEM_GET_BLOCK_FROM_PTR(ptr);
if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */ if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */
block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */ block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */
LWMEM_GET_LW(lw)->mem_available_bytes += block->size; /* Increase available bytes */ lwobj->mem_available_bytes += block->size; /* Increase available bytes */
prv_insert_free_block(lw, block); /* Put block back to list of free block */ 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 frees memory, equivalent to `free(ptr)`
* - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success * - `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. * \param[in] region: Pointer to region to allocate from.
* Set to `NULL` for any region * Set to `NULL` for any region
* \param[in] ptr: Memory block previously allocated with one of allocation functions. * \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 * \return Pointer to allocated memory on success, `NULL` otherwise
*/ */
static void* static void*
prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, const size_t size) { prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) {
lwmem_block_t* block, *prevprev, *prev; lwmem_block_t *block, *prevprev, *prev;
size_t block_size; /* Holds size of input block (ptr), including metadata size */ 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 */ const size_t final_size =
void* retval; /* Return pointer, used with LWMEM_RETURN macro */ 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 */ /* Check optional input parameters */
if (size == 0) { if (size == 0) {
if (ptr != NULL) { if (ptr != NULL) {
prv_free(lw, ptr); prv_free(lwobj, ptr);
} }
return NULL; return NULL;
} }
if (ptr == NULL) { if (ptr == NULL) {
return prv_alloc(lw, region, size); return prv_alloc(lwobj, region, size);
} }
/* Try to reallocate existing pointer */ /* 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 */ /* Process existing block */
block = LWMEM_GET_BLOCK_FROM_PTR(ptr); block = LWMEM_GET_BLOCK_FROM_PTR(ptr);
if (LWMEM_BLOCK_IS_ALLOC(block)) { 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 */ /* Check current block size is the same as new requested size */
if (block_size == final_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 (final_size < block_size) {
if ((block_size - final_size) >= LWMEM_BLOCK_MIN_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 { } else {
/* /*
* It is not possible to create new empty block at the end of input block * 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 */ /* 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 */ /* Check if current block and next free are connected */
if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) 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 */ /* Make temporary variables as prev->next will point to different location */
const size_t tmp_size = prev->next->size; const size_t tmp_size = prev->next->size;
void* const tmp_next = prev->next->next; 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 = (void*)(LWMEM_TO_BYTE_PTR(prev->next) - (block_size - final_size));
prev->next->size = tmp_size + (block_size - final_size); prev->next->size = tmp_size + (block_size - final_size);
prev->next->next = tmp_next; 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 */ LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return ptr; /* Return existing pointer */ return ptr; /* Return existing pointer */
} }
/* New requested size is bigger than current block size is */ /* New requested size is bigger than current block size is */
/* Find last free (and its previous) block, located just before input block */ /* 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 entry could not be found, there is a hard error */
if (prev == NULL) { 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 */ /* 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 */ /* 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 */ && (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 * Merge blocks together by increasing current block with size of next free one
* and remove next free from list of free blocks * 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 */ lwobj->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 */ LWMEM_UPDATE_MIN_FREE(lwobj);
prev->next = prev->next->next; /* Set next to next's next, effectively remove expanded block from free list */ 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 */ 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 */ LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return ptr; /* Return existing pointer */ 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 * 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 */ 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 */ && (prev->size + block_size) >= final_size) { /* Size is greater or equal to requested */
/* Move memory from block to block previous to current */ /* Move memory from block to block previous to current */
void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block);
void* const new_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(prev); 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_MEMMOVE(new_data_ptr, old_data_ptr, block_size);
LWMEM_GET_LW(lw)->mem_available_bytes -= prev->size;/* For now decrease effective available bytes */ lwobj->mem_available_bytes -= prev->size; /* For now decrease effective available bytes */
prev->size += block_size; /* Increase size of input block size */ LWMEM_UPDATE_MIN_FREE(lwobj);
prevprev->next = prev->next; /* Remove prev from free list as it is now being used for allocation together with existing block */ prev->size += block_size; /* Increase size of input block size */
block = prev; /* Move block pointer to previous one */ 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 */ 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 */ LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return new_data_ptr; /* Return new data ptr */ 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 * 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 * 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 */ if ((LWMEM_TO_BYTE_PTR(prev) + prev->size)
&& (LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) /* Input block and free block after create contiguous block */ == LWMEM_TO_BYTE_PTR(block) /* Input block and free block before create contiguous block */
&& (prev->size + block_size + prev->next->size) >= final_size) {/* Size is greater or equal to requested */ && (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 */ /* Move memory from block to block previous to current */
void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); 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 * 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_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 */ lwobj->mem_available_bytes -=
prev->size += block_size + prev->next->size;/* Increase size of new block by size of 2 free blocks */ prev->size
prevprev->next = prev->next->next; /* Remove free block before current one and block after current one from linked list (remove 2) */ + prev->next
block = prev; /* Previous block is now current */ ->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(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 */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */ LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return new_data_ptr; /* Return new data ptr */ return new_data_ptr; /* Return new data ptr */
} }
} else { } else {
/* Hard error. Input pointer is not NULL and block is not considered allocated */ /* 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 * 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) { if (retval != NULL) {
block_size = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; /* Get application size from input pointer */ block_size =
LWMEM_MEMCPY(retval, ptr, size > block_size ? block_size : size); /* Copy content to new allocated block */ (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; /* Get application size from input pointer */
prv_free(lw, ptr); /* Free 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; return retval;
} }
/** /**
* \brief Initializes and assigns user regions for memory used by allocator algorithm * \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. * \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. * 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` * Last region entry must have address `NULL` and size set to `0`
@ -677,14 +716,14 @@ lwmem_region_t regions[] = {
* It must be called only once to setup memory regions * It must be called only once to setup memory regions
*/ */
size_t 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; uint8_t* mem_start_addr;
size_t mem_size, len = 0; 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 */ /* Check first things first */
if (regions == NULL if (regions == NULL || lwobj->end_block != NULL /* Init function may only be called once per lwmem instance */
|| LWMEM_GET_LW(lw)->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 */ || (((size_t)LWMEM_CFG_ALIGN_NUM) & (((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) > 0) { /* Must be power of 2 */
return 0; return 0;
} }
@ -719,10 +758,10 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) {
/* Process further checks of valid inputs */ /* Process further checks of valid inputs */
if (regions == NULL || len == 0 if (regions == NULL || len == 0
#if LWMEM_CFG_OS #if LWMEM_CFG_OS
|| lwmem_sys_mutex_isvalid(&(LWMEM_GET_LW(lw)->mutex)) /* Check if mutex valid already = must not be */ || lwmem_sys_mutex_isvalid(&(lwobj->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 */ || !lwmem_sys_mutex_create(&(lwobj->mutex)) /* Final step = try to create mutex for new instance */
#endif /* LWMEM_CFG_OS */ #endif /* LWMEM_CFG_OS */
) { ) {
return 0; 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 * In first indication application shall set start_block and never again
* end_block value holds * 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 * Next entry of start block is first region
* It points to beginning of region data * It points to beginning of region data
* In the later step(s) first block is manually set on top of memory region * 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; lwobj->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.size = 0; /* Size of dummy start block is zero */
} }
/* Save current end block status as it is used later for linked list insertion */ /* 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 */ /* 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); lwobj->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 */ lwobj->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->size = 0; /* Size of end block is zero */
/* /*
* Create memory region first block. * 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 * 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 = (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; first_block->size = mem_size - LWMEM_BLOCK_META_SIZE;
/* Check if previous regions exist by checking previous end block state */ /* 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 */ 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 */ lwobj->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_regions_count; /* Increase number of used regions */
} }
#if defined(LWMEM_DEV) #if defined(LWMEM_DEV)
/* Copy default state of start block */ /* Copy default state of start block */
LWMEM_MEMCPY(&lwmem_default.start_block_first_use, &lwmem_default.start_block, sizeof(lwmem_default.start_block)); LWMEM_MEMCPY(&lwmem_default.start_block_first_use, &lwmem_default.start_block, sizeof(lwmem_default.start_block));
#endif /* defined(LWMEM_DEV) */ #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. * \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 * \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. * \param[in] region: Optional region instance within LwMEM instance to force allocation from.
* Set to `NULL` to use any region within LwMEM instance * Set to `NULL` to use any region within LwMEM instance
* \param[in] size: Number of bytes to allocate * \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 * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/ */
void* 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; void* ptr;
LWMEM_PROTECT(lw); lwobj = LWMEM_GET_LWOBJ(lwobj);
ptr = prv_alloc(lw, region, size); LWMEM_PROTECT(lwobj);
LWMEM_UNPROTECT(lw); ptr = prv_alloc(lwobj, region, size);
LWMEM_UNPROTECT(lwobj);
return ptr; 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 * 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 * \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. * \param[in] region: Optional region instance within LwMEM instance to force allocation from.
* Set to `NULL` to use any region within LwMEM instance * Set to `NULL` to use any region within LwMEM instance
* \param[in] nitems: Number of elements to be allocated * \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 * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/ */
void* 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; void* ptr;
const size_t s = size * nitems; const size_t s = size * nitems;
LWMEM_PROTECT(lw); lwobj = LWMEM_GET_LWOBJ(lwobj);
if ((ptr = prv_alloc(lw, region, s)) != NULL) { LWMEM_PROTECT(lwobj);
if ((ptr = prv_alloc(lwobj, region, s)) != NULL) {
LWMEM_MEMSET(ptr, 0x00, s); LWMEM_MEMSET(ptr, 0x00, s);
} }
LWMEM_UNPROTECT(lw); LWMEM_UNPROTECT(lwobj);
return ptr; 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 frees memory, equivalent to `free(ptr)`
* - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success * - `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. * \param[in] region: Pointer to region to allocate from.
* Set to `NULL` to use any region within LwMEM instance. * Set to `NULL` to use any region within LwMEM instance.
* Instance must be the same as used during allocation procedure * 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 * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/ */
void* 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; void* p;
LWMEM_PROTECT(lw); lwobj = LWMEM_GET_LWOBJ(lwobj);
p = prv_realloc(lw, region, ptr, size); LWMEM_PROTECT(lwobj);
LWMEM_UNPROTECT(lw); p = prv_realloc(lwobj, region, ptr, size);
LWMEM_UNPROTECT(lwobj);
return p; 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 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 * - `*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. * \param[in] region: Pointer to region to allocate from.
* Set to `NULL` to use any region within LwMEM instance. * Set to `NULL` to use any region within LwMEM instance.
* Instance must be the same as used during allocation procedure * 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 * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/ */
uint8_t 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; void* new_ptr;
/* /*
@ -903,10 +949,10 @@ lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const
return 0; 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) { if (new_ptr != NULL) {
*ptr = new_ptr; *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; *ptr = NULL;
return 1; 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 * \brief Free previously allocated memory using one of allocation functions
* in specific lwmem instance. * 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 * Instance must be the same as used during allocation procedure
* \note This is an extended free version function declaration to support advanced features * \note This is an extended free version function declaration to support advanced features
* \param[in] ptr: Memory to free. `NULL` pointer is valid input * \param[in] ptr: Memory to free. `NULL` pointer is valid input
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/ */
void void
lwmem_free_ex(lwmem_t* const lw, void* const ptr) { lwmem_free_ex(lwmem_t* lwobj, void* const ptr) {
LWMEM_PROTECT(lw); lwobj = LWMEM_GET_LWOBJ(lwobj);
prv_free(lw, ptr); LWMEM_PROTECT(lwobj);
LWMEM_UNPROTECT(lw); 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. * 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 * Instance must be the same as used during allocation procedure
* \param[in] ptr: Pointer to pointer to allocated memory. * \param[in] ptr: Pointer to pointer to allocated memory.
* When set to non `NULL`, pointer is freed and set to `NULL` * 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 * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/ */
void 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) { if (ptr != NULL && *ptr != NULL) {
LWMEM_PROTECT(lw); lwobj = LWMEM_GET_LWOBJ(lwobj);
prv_free(lw, *ptr); LWMEM_PROTECT(lwobj);
LWMEM_UNPROTECT(lw); prv_free(lwobj, *ptr);
LWMEM_UNPROTECT(lwobj);
*ptr = NULL; *ptr = NULL;
} }
} }
/** /**
* \brief Get user size of allocated memory * \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 * Instance must be the same as used during allocation procedure
* \param[in] ptr: Pointer to allocated memory * \param[in] ptr: Pointer to allocated memory
* \return Block size for user in units of bytes * \return Block size for user in units of bytes
*/ */
size_t 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; lwmem_block_t* block;
uint32_t len = 0; uint32_t len = 0;
if (ptr != NULL) { if (ptr != NULL) {
LWMEM_PROTECT(lw); lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
block = LWMEM_GET_BLOCK_FROM_PTR(ptr); block = LWMEM_GET_BLOCK_FROM_PTR(ptr);
if (LWMEM_BLOCK_IS_ALLOC(block)) { if (LWMEM_BLOCK_IS_ALLOC(block)) {
len = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; len = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE;
} }
LWMEM_UNPROTECT(lw); LWMEM_UNPROTECT(lwobj);
} }
return len; 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 */ /* Part of library used ONLY for LWMEM_DEV purposes */
/* To validate and test library */ /* 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; 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; block_size = block->size & ~LWMEM_ALLOC_BIT;
printf("| %5d | %16p | %6d | %4d | %16d |", printf("| %5d | %16p | %6d | %4d | %16d |", (int)i, (void*)block, (int)is_free, (int)block_size,
(int)i,
block,
(int)is_free,
(int)block_size,
(int)(is_free ? (block_size - LWMEM_BLOCK_META_SIZE) : 0)); (int)(is_free ? (block_size - LWMEM_BLOCK_META_SIZE) : 0));
if (block == &lwmem_default.start_block_first_use) { if (block == &lwmem_default.start_block_first_use) {
printf(" Start block "); printf(" Start block ");
@ -1060,6 +1126,9 @@ lwmem_debug_print(uint8_t print_alloc, uint8_t print_free) {
size_t block_size; size_t block_size;
lwmem_block_t* block; lwmem_block_t* block;
(void)print_alloc;
(void)print_free;
printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); printf("|-------|------------------|--------|------|------------------|-----------------|\r\n");
printf("| Block | Address | IsFree | Size | MaxUserAllocSize | Meta |\r\n"); printf("| Block | Address | IsFree | Size | MaxUserAllocSize | Meta |\r\n");
printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); printf("|-------|------------------|--------|------|------------------|-----------------|\r\n");

33
lwmem/src/lwmem/lwmem.cpp Normal file
View File

@ -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 <tilen@majerle.eu>
* Version: v2.1.0
*/

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation
@ -29,7 +29,7 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library. * This file is part of LwMEM - Lightweight dynamic memory manager library.
* *
* Author: Tilen MAJERLE <tilen@majerle.eu> * Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0 * Version: v2.1.0
*/ */
#include "system/lwmem_sys.h" #include "system/lwmem_sys.h"

View File

@ -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 <tilen@majerle.eu>
* 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__ */

View File

@ -4,7 +4,7 @@
*/ */
/* /*
* Copyright (c) 2020 Tilen MAJERLE * Copyright (c) 2023 Tilen MAJERLE
* *
* Permission is hereby granted, free of charge, to any person * Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation * obtaining a copy of this software and associated documentation
@ -29,7 +29,7 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library. * This file is part of LwMEM - Lightweight dynamic memory manager library.
* *
* Author: Tilen MAJERLE <tilen@majerle.eu> * Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0 * Version: v2.1.0
*/ */
#include "system/lwmem_sys.h" #include "system/lwmem_sys.h"

View File

@ -54,8 +54,8 @@ lw_c_regions[] = {
void void
lwmem_test_run(void) { lwmem_test_run(void) {
void* ptr_1, * ptr_2, * ptr_3, * ptr_4; void* ptr_1, * ptr_2, * ptr_3;
void* ptr_c_1, * ptr_c_2, * ptr_c_3, * ptr_c_4; void* ptr_c_1, * ptr_c_2, * ptr_c_3;
/* Initialize default lwmem instance */ /* Initialize default lwmem instance */
/* Use one of 2 possible function calls: */ /* Use one of 2 possible function calls: */