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,
"configurations": [
{
/*
* Full configuration is provided by CMake plugin for vscode,
* that shall be installed by user
*/
"name": "Win32",
"includePath": [
"${workspaceFolder}\\dev\\VisualStudio\\",
"${workspaceFolder}\\lwmem\\src\\include\\"
],
"defines": [
"WIN32",
"_DEBUG",
"UNICODE",
"_UNICODE",
"LWMEM_DEV"
],
"compilerPath": "c:\\msys64\\mingw64\\bin\\gcc.exe",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "windows-gcc-x86",
"intelliSenseMode": "${default}",
"configurationProvider": "ms-vscode.cmake-tools"
}
]

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

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",
/* For this builds, you need
*
* - Ninja build system
* - MSYS2 compiler with ninja support
* - C/C++ extension for VSCode
* - CMake-Tools extension for VSCode
*/
"version": "2.1.0",
"tasks": [
{
"type": "cppbuild",
"label": "Build project",
"command": "cmake",
"args": ["--build", "\"build\""],
"args": ["--build", "${command:cmake.buildDirectory}", "-j", "8"],
"options": {
"cwd": "${workspaceFolder}"
},
@ -27,7 +19,7 @@
"type": "shell",
"label": "Re-build project",
"command": "cmake",
"args": ["--build", "\"build\"", "--clean-first", "-v"],
"args": ["--build", "${command:cmake.buildDirectory}", "--clean-first", "-v", "-j", "8"],
"options": {
"cwd": "${workspaceFolder}"
},
@ -37,7 +29,7 @@
"type": "shell",
"label": "Clean project",
"command": "cmake",
"args": ["--build", "\"build\"", "--target", "clean"],
"args": ["--build", "${command:cmake.buildDirectory}", "--target", "clean"],
"options": {
"cwd": "${workspaceFolder}"
},
@ -46,9 +38,48 @@
{
"type": "shell",
"label": "Run application",
"command": "${workspaceFolder}\\build\\LwLibPROJECT.exe",
"command": "${command:cmake.launchTargetPath}",
"args": [],
"problemMatcher": [],
},
{
"label": "Docs: Install python plugins from requirements.txt file",
"type": "shell",
"command": "python -m pip install -r requirements.txt",
"options": {
"cwd": "${workspaceFolder}/docs"
},
"problemMatcher": []
},
{
"label": "Docs: Generate html",
"type": "shell",
"command": ".\\make html",
"options": {
"cwd": "${workspaceFolder}/docs"
},
"problemMatcher": []
},
{
"label": "Docs: Clean build directory",
"type": "shell",
"command": ".\\make clean",
"options": {
"cwd": "${workspaceFolder}/docs"
},
"problemMatcher": []
},
{
"label": "Build all WIN32 examples",
"type": "shell",
"command": "python",
"args": [
"build_all_examples.py"
],
"options": {
"cwd": "${workspaceFolder}/examples/win32"
},
"problemMatcher": []
}
]
}

View File

@ -2,6 +2,15 @@
## Develop
## v2.1.0
- Split CMakeLists.txt files between library and executable
- Add C++ wrapper functions
- Change license year to 2022
- Update code style with astyle
- Fix wrong length function usage
- Add `.clang-format` draft
## v2.0.0
- Remove `len` parameter for regions definition. Affected functions: `lwmem_assignmem` and `lwmem_assignmem_ex`

View File

@ -1,28 +1,46 @@
cmake_minimum_required(VERSION 3.0.0)
project(LwLibPROJECT VERSION 0.1.0)
cmake_minimum_required(VERSION 3.22)
include(CTest)
enable_testing()
# Setup project
project(LwLibPROJECT)
add_executable(${PROJECT_NAME}
lwmem/src/lwmem/lwmem.c
lwmem/src/system/lwmem_sys_win32.c
tests/lwmem_test.c
dev/VisualStudio/main.c
if(NOT PROJECT_IS_TOP_LEVEL)
add_subdirectory(lwmem)
else()
# Set as executable
add_executable(${PROJECT_NAME})
# Add key executable block
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/dev/main.cpp
${CMAKE_CURRENT_LIST_DIR}/tests/lwmem_test.c
# win32 port
${CMAKE_CURRENT_LIST_DIR}/lwmem/src/system/lwmem_sys_win32.c
)
target_include_directories(${PROJECT_NAME} PRIVATE
dev/VisualStudio
lwmem/src/include
# Add key include paths
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/dev
)
target_compile_definitions(${PROJECT_NAME} PRIVATE
WIN32
_DEBUG
CONSOLE
LWMEM_DEV
# Compilation definition information
target_compile_definitions(${PROJECT_NAME} PUBLIC
WIN32
_DEBUG
CONSOLE
LWMEM_DEV
)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
# Compiler options
target_compile_options(${PROJECT_NAME} PRIVATE
-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
Copyright (c) 2020 Tilen MAJERLE
Copyright (c) 2023 Tilen MAJERLE
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

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

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

View File

@ -16,13 +16,13 @@
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\lwmem\src\lwmem\lwmem.c">
<ClCompile Include="..\lwmem\src\lwmem\lwmem.c">
<Filter>Source Files\LWMEM</Filter>
</ClCompile>
<ClCompile Include="..\..\lwmem\src\system\lwmem_sys_win32.c">
<ClCompile Include="..\lwmem\src\system\lwmem_sys_win32.c">
<Filter>Source Files\LWMEM</Filter>
</ClCompile>
<ClCompile Include="..\..\tests\lwmem_test.c">
<ClCompile Include="..\tests\lwmem_test.c">
<Filter>Source Files\Tests</Filter>
</ClCompile>
</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
* 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.
.. 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 = 'LwMEM'
copyright = '2020, Tilen MAJERLE'
copyright = '2022, Tilen MAJERLE'
author = 'Tilen MAJERLE'
# Try to get branch at which this is running
# and try to determine which version to display in sphinx
# Version is using git tag if on master or "latest-develop" if on develop branch
# Version is using git tag if on master/main or "latest-develop" if on develop branch
version = ''
git_branch = ''
def cmd_exec_print(t):
print("cmd > ", t, "\n", os.popen(t).read().strip(), "\n")
# Print demo data here
cmd_exec_print('git branch')
cmd_exec_print('git describe')
cmd_exec_print('git describe --tags')
cmd_exec_print('git describe --tags --abbrev=0')
cmd_exec_print('git describe --tags --abbrev=1')
# Get current branch
res = os.popen('git branch').read().strip()
for line in res.split("\n"):
@ -41,17 +51,18 @@ for line in res.split("\n"):
# Decision for display version
git_branch = git_branch.replace('(HEAD detached at ', '').replace(')', '')
if git_branch.find('master') >= 0 or git_branch.find('main') >= 0:
version = os.popen('git describe --tags --abbrev=0').read().strip()
if version == '':
version = 'v0.0.0'
elif git_branch.find('develop') != -1 and not (git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0):
#version = os.popen('git describe --tags --abbrev=0').read().strip()
version = 'latest-stable'
elif git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0:
version = 'branch-' + git_branch
elif git_branch == 'develop' or git_branch == 'origin/develop':
version = 'latest-develop'
else:
version = 'branch-' + git_branch
version = os.popen('git describe --tags --abbrev=0').read().strip()
# For debugging purpose only
print("GIT BRANCH: " + git_branch)
print("GIT VERSION: " + version)
print("PROJ VERSION: " + version)
# -- General configuration ---------------------------------------------------
@ -115,20 +126,19 @@ html_static_path = ['static']
html_css_files = [
'css/common.css',
'css/custom.css',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css',
]
html_js_files = [
'https://kit.fontawesome.com/3102794088.js'
''
]
# Master index file
master_doc = 'index'
#
# Breathe configuration
#
#
#
# --- Breathe configuration -----------------------------------------------------
breathe_projects = {
"lwmem": "_build/xml/"
}
breathe_default_project = "lwmem"
breathe_default_members = ('members', 'undoc-members')
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:
* WIN32 examples, prepared as `Visual Studio Community <https://visualstudio.microsoft.com/vs/community/>`_ projects
* ARM Cortex-M examples for STM32, prepared as `STM32CubeIDE <https://www.st.com/en/development-tools/stm32cubeide.html>`_ GCC 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. 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::
Library is platform independent and can be used on any platform.
@ -20,8 +20,12 @@ Therefore it has been decided to support (for purpose of examples) ``2`` platfor
WIN32
*****
Examples for *WIN32* are prepared as `Visual Studio Community <https://visualstudio.microsoft.com/vs/community/>`_ projects.
You can directly open project in the IDE, compile & debug.
Examples for *WIN32* are CMake-ready and *VSCode*-ready.
It utilizes CMake-presets feature to let you select the example and compile it directly.
* Make sure you have installed GCC compiler and is in env path (you can get it through MSYS2 packet manager)
* Install ninja and cmake and make them available in the path (you can get all through MSYS2 packet manager)
* Go to *examples win32* folder, open vscode there or run cmd: ``cmake --preset <project name>`` to configure cmake and later ``cmake --build --preset <project name>`` to compile the project
STM32
*****

View File

@ -13,10 +13,10 @@ Download library
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
* Cloning ``master`` branch for latest stable version
* Cloning ``main`` branch for latest stable version
* Cloning ``develop`` branch for latest development
Download from releases
@ -34,21 +34,21 @@ This is used when you do not have yet local copy on your machine.
* Make sure ``git`` is installed.
* Open console and navigate to path in the system to clone repository to. Use command ``cd your_path``
* Clone repository with one of available ``3`` options
* Clone repository with one of available options below
* Run ``git clone --recurse-submodules https://github.com/MaJerle/lwmem`` command to clone entire repository, including submodules
* Run ``git clone --recurse-submodules --branch develop https://github.com/MaJerle/lwmem`` to clone `development` branch, including submodules
* Run ``git clone --recurse-submodules --branch master https://github.com/MaJerle/lwmem`` to clone `latest stable` branch, including submodules
* Run ``git clone --recurse-submodules --branch main https://github.com/MaJerle/lwmem`` to clone `latest stable` branch, including submodules
* Navigate to ``examples`` directory and run favourite example
Update cloned to latest version
"""""""""""""""""""""""""""""""
* Open console and navigate to path in the system where your resources repository is. Use command ``cd your_path``
* Run ``git pull origin master --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``master`` branch
* Run ``git pull origin develop --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``develop`` branch
* Run ``git submodule foreach git pull origin master`` to update & merge all submodules
* Open console and navigate to path in the system where your repository is located. Use command ``cd your_path``
* Run ``git pull origin main`` command to get latest changes on ``main`` branch
* Run ``git pull origin develop`` command to get latest changes on ``develop`` branch
* Run ``git submodule update --init --remote`` to update submodules to latest version
.. note::
This is preferred option to use when you want to evaluate library and run prepared examples.

View File

@ -26,6 +26,7 @@ Features
* Supports automotive applications
* Supports advanced free/realloc algorithms to optimize memory usage
* Operating system ready, thread-safe API
* C++ wrapper functions
* User friendly MIT license
Requirements
@ -58,9 +59,31 @@ Table of contents
.. toctree::
:maxdepth: 2
:caption: Contents
self
get-started/index
user-manual/index
api-reference/index
examples/index
changelog/index
.. toctree::
:maxdepth: 2
:caption: Other projects
:hidden:
LwBTN - Button manager <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
docutils==0.16
sphinx>=3.5.1
sphinx_rtd_theme
sphinx_rtd_theme>=1.0.0
sphinx-tabs
sphinxcontrib-svg2pdfconverter
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.
* --------------------------------------------------------------------------
*
@ -37,7 +37,7 @@
* Control functions for short timeouts in microsecond resolution:
* Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
* Removed: osSignalGet
* Version 2.0.0
* Version 2.1.0
* OS objects creation without macros (dynamic creation and resource allocation):
* - added: osXxxxNew functions which replace osXxxxCreate
* - added: osXxxxAttr_t structures

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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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_ptr2 = lwmem_malloc_ex(&lw1, &lw1_regions[1], 24); /* Allocate memory from default LwMEM instance, force second region */
(void)lw1_ptr1;
(void)lw1_ptr2;
/* Free memory after use */
lwmem_free_ex(&lw1, lw0_ptr1);
lwmem_free_ex(&lw1, lw0_ptr2);

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
* 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
* 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) {
void* ptr, * ptr2;
(void)arg;
/* Allocate memory */
ptr = lwmem_malloc(24);
if (ptr == NULL) {
if ((ptr = lwmem_malloc(24)) == NULL) {
printf("Could not allocate memory!\r\n");
return -1;
}
printf("Memory allocated at address 0x%p!\r\n", ptr);
/* Increase its size */
ptr2 = lwmem_realloc(ptr, 48);
if (ptr2 == NULL) {
if ((ptr2 = lwmem_realloc(ptr, 48)) == NULL) {
printf("Could not reallocate existing ptr\r\n");
} else {
printf("Memory reallocated at address 0x%p!\r\n", ptr2);

View File

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

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
* obtaining a copy of this software and associated documentation
@ -29,13 +29,13 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0
* Version: v2.1.0
*/
#ifndef LWMEM_HDR_H
#define LWMEM_HDR_H
#include <stdint.h>
#include <limits.h>
#include <stdint.h>
#include "lwmem/lwmem_opt.h"
#ifdef __cplusplus
@ -53,15 +53,15 @@ extern "C" {
* \param[in] x: Object to get array size of
* \return Number of elements in array
*/
#define LWMEM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
#define LWMEM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
/**
* \brief Memory block structure
*/
typedef struct lwmem_block {
struct lwmem_block* next; /*!< Next free memory block on linked list.
Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */
size_t size; /*!< Size of block, including metadata part.
struct lwmem_block*
next; /*!< Next free memory block on linked list. Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */
size_t size; /*!< Size of block, including metadata part.
MSB bit is set to `1` when block is allocated and in use,
or `0` when block is considered free */
} lwmem_block_t;
@ -70,46 +70,53 @@ typedef struct lwmem_block {
* \brief Statistics structure
*/
typedef struct {
uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */
uint32_t nr_free; /*!< Number of frees in the LwMEM instance */
uint32_t mem_size_bytes; /*!< Total memory size of all regions combined */
uint32_t mem_available_bytes; /*!< Free memory available for allocation */
uint32_t
minimum_ever_mem_available_bytes; /*!< Minimum amount of total free memory there has been in the heap since the system booted. */
uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */
uint32_t nr_free; /*!< Number of frees in the LwMEM instance */
} lwmem_stats_t;
/**
* \brief LwMEM main structure
*/
typedef struct lwmem {
lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */
lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */
size_t mem_available_bytes; /*!< Memory size available for allocation */
size_t mem_regions_count; /*!< Number of regions used for allocation */
lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */
lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */
size_t mem_available_bytes; /*!< Memory size available for allocation */
size_t mem_regions_count; /*!< Number of regions used for allocation */
#if LWMEM_CFG_OS || __DOXYGEN__
LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */
#endif /* LWMEM_CFG_OS || __DOXYGEN__ */
LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */
#endif /* LWMEM_CFG_OS || __DOXYGEN__ */
#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__
lwmem_stats_t stats; /*!< Statistics */
#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */
lwmem_stats_t stats; /*!< Statistics */
#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */
#if defined(LWMEM_DEV) && !__DOXYGEN__
lwmem_block_t start_block_first_use; /*!< Value of start block for very first time.
lwmem_block_t start_block_first_use; /*!< Value of start block for very first time.
This is used only during validation process and is removed in final use */
#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */
#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */
} lwmem_t;
/**
* \brief Memory region descriptor
*/
typedef struct {
void* start_addr; /*!< Region start address */
size_t size; /*!< Size of region in units of bytes */
void* start_addr; /*!< Region start address */
size_t size; /*!< Size of region in units of bytes */
} lwmem_region_t;
size_t lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions);
void* lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t size);
void* lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t nitems, const size_t size);
void* lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, const size_t size);
uint8_t lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const ptr, const size_t size);
void lwmem_free_ex(lwmem_t* const lw, void* const ptr);
void lwmem_free_s_ex(lwmem_t* const lw, void** const ptr);
size_t lwmem_get_size_ex(lwmem_t* const lw, void* ptr);
size_t lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions);
void* lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size);
void* lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size);
void* lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size);
uint8_t lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size);
void lwmem_free_ex(lwmem_t* lwobj, void* const ptr);
void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr);
size_t lwmem_get_size_ex(lwmem_t* lwobj, void* ptr);
#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__
void lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats);
#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */
/**
* \note This is a wrapper for \ref lwmem_assignmem_ex function.
@ -128,7 +135,7 @@ lwmem_region_t regions[] = {
\endcode
* \return `0` on failure, number of final regions used for memory manager on success
*/
#define lwmem_assignmem(regions) lwmem_assignmem_ex(NULL, (regions))
#define lwmem_assignmem(regions) lwmem_assignmem_ex(NULL, (regions))
/**
* \note This is a wrapper for \ref lwmem_malloc_ex function.
@ -137,7 +144,7 @@ lwmem_region_t regions[] = {
* \return Pointer to allocated memory on success, `NULL` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
#define lwmem_malloc(size) lwmem_malloc_ex(NULL, NULL, (size))
#define lwmem_malloc(size) lwmem_malloc_ex(NULL, NULL, (size))
/**
* \note This is a wrapper for \ref lwmem_calloc_ex function.
@ -147,7 +154,7 @@ lwmem_region_t regions[] = {
* \return Pointer to allocated memory on success, `NULL` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
#define lwmem_calloc(nitems, size) lwmem_calloc_ex(NULL, NULL, (nitems), (size))
#define lwmem_calloc(nitems, size) lwmem_calloc_ex(NULL, NULL, (nitems), (size))
/**
* \note This is a wrapper for \ref lwmem_realloc_ex function.
@ -158,7 +165,7 @@ lwmem_region_t regions[] = {
* \return Pointer to allocated memory on success, `NULL` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
#define lwmem_realloc(ptr, size) lwmem_realloc_ex(NULL, NULL, (ptr), (size))
#define lwmem_realloc(ptr, size) lwmem_realloc_ex(NULL, NULL, (ptr), (size))
/**
* \note This is a wrapper for \ref lwmem_realloc_s_ex function.
@ -170,7 +177,7 @@ lwmem_region_t regions[] = {
* \return `1` if successfully reallocated, `0` otherwise
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
#define lwmem_realloc_s(ptrptr, size) lwmem_realloc_s_ex(NULL, NULL, (ptrptr), (size))
#define lwmem_realloc_s(ptrptr, size) lwmem_realloc_s_ex(NULL, NULL, (ptrptr), (size))
/**
* \note This is a wrapper for \ref lwmem_free_ex function.
@ -178,7 +185,7 @@ lwmem_region_t regions[] = {
* \param[in] ptr: Memory to free. `NULL` pointer is valid input
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
#define lwmem_free(ptr) lwmem_free_ex(NULL, (ptr))
#define lwmem_free(ptr) lwmem_free_ex(NULL, (ptr))
/**
* \note This is a wrapper for \ref lwmem_free_s_ex function.
@ -187,7 +194,7 @@ lwmem_region_t regions[] = {
* When set to non `NULL`, pointer is freed and set to `NULL`
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
#define lwmem_free_s(ptrptr) lwmem_free_s_ex(NULL, (ptrptr))
#define lwmem_free_s(ptrptr) lwmem_free_s_ex(NULL, (ptrptr))
/**
* \note This is a wrapper for \ref lwmem_get_size_ex function.
@ -195,14 +202,21 @@ lwmem_region_t regions[] = {
* \param[in] ptr: Pointer to allocated memory
* \return Block size for user in units of bytes
*/
#define lwmem_get_size(ptr) lwmem_get_size(NULL, (ptr))
#define lwmem_get_size(ptr) lwmem_get_size_ex(NULL, (ptr))
/**
* \note This is a wrapper for \ref lwmem_get_stats_ex function.
* It operates in default LwMEM instance
* \param[in] ptr: Pointer to lwmem_stats_t to store result
*/
#define lwmem_get_stats(stats) lwmem_get_stats_ex(NULL, (stats))
#if defined(LWMEM_DEV) && !__DOXYGEN__
unsigned char lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size);
void lwmem_debug_save_state(void);
void lwmem_debug_restore_to_saved(void);
void lwmem_debug_save_state(void);
void lwmem_debug_restore_to_saved(void);
void lwmem_debug_print(unsigned char print_alloc, unsigned char print_free);
void lwmem_debug_print(unsigned char print_alloc, unsigned char print_free);
#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */
/**

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

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
* obtaining a copy of this software and associated documentation
@ -29,10 +29,10 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0
* Version: v2.1.0
*/
#ifndef LWMEM_HDR_OPTS_H
#define LWMEM_HDR_OPTS_H
#ifndef LWMEM_OPTS_HDR_H
#define LWMEM_OPTS_HDR_H
/* Rename this file to "lwmem_opts.h" for your application */
@ -41,4 +41,4 @@
* copy & replace here settings you want to change values
*/
#endif /* LWMEM_HDR_OPTS_H */
#endif /* LWMEM_OPTS_HDR_H */

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

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
* obtaining a copy of this software and associated documentation
@ -29,24 +29,24 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0
* Version: v2.1.0
*/
#include "lwmem/lwmem.h"
#include <limits.h>
#include <string.h>
#include "lwmem/lwmem.h"
#if LWMEM_CFG_OS
#include "system/lwmem_sys.h"
#endif /* LWMEM_CFG_OS */
#define LWMEM_MEMSET memset
#define LWMEM_MEMCPY memcpy
#define LWMEM_MEMMOVE memmove
#define LWMEM_MEMSET memset
#define LWMEM_MEMCPY memcpy
#define LWMEM_MEMMOVE memmove
/**
* \brief Transform alignment number (power of `2`) to bits
*/
#define LWMEM_ALIGN_BITS ((size_t)(((size_t)LWMEM_CFG_ALIGN_NUM) - 1))
#define LWMEM_ALIGN_BITS ((size_t)(((size_t)LWMEM_CFG_ALIGN_NUM) - 1))
/**
* \brief Aligns input value to next alignment bits
@ -63,93 +63,108 @@
* - Input: `7`; Output: `8`
* - Input: `8`; Output: `8`
*/
#define LWMEM_ALIGN(x) (((x) + (LWMEM_ALIGN_BITS)) & ~(LWMEM_ALIGN_BITS))
#define LWMEM_ALIGN(x) (((x) + (LWMEM_ALIGN_BITS)) & ~(LWMEM_ALIGN_BITS))
/**
* \brief Size of metadata header for block information
*/
#define LWMEM_BLOCK_META_SIZE LWMEM_ALIGN(sizeof(lwmem_block_t))
#define LWMEM_BLOCK_META_SIZE LWMEM_ALIGN(sizeof(lwmem_block_t))
/**
* \brief Cast input pointer to byte
* \param[in] p: Input pointer to cast to byte pointer
*/
#define LWMEM_TO_BYTE_PTR(p) ((uint8_t *)(p))
#define LWMEM_TO_BYTE_PTR(p) ((uint8_t*)(p))
/**
* \brief Bit indicating memory block is allocated
*/
#define LWMEM_ALLOC_BIT ((size_t)((size_t)1 << (sizeof(size_t) * CHAR_BIT - 1)))
#define LWMEM_ALLOC_BIT ((size_t)((size_t)1 << (sizeof(size_t) * CHAR_BIT - 1)))
/**
* \brief Mark written in `next` field when block is allocated
*/
#define LWMEM_BLOCK_ALLOC_MARK (0xDEADBEEF)
#define LWMEM_BLOCK_ALLOC_MARK (0xDEADBEEF)
/**
* \brief Set block as allocated
* \param[in] block: Block to set as allocated
*/
#define LWMEM_BLOCK_SET_ALLOC(block) do { if ((block) != NULL) { (block)->size |= LWMEM_ALLOC_BIT; (block)->next = (void *)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK); }} while (0)
#define LWMEM_BLOCK_SET_ALLOC(block) \
do { \
if ((block) != NULL) { \
(block)->size |= LWMEM_ALLOC_BIT; \
(block)->next = (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK); \
} \
} while (0)
/**
* \brief Check if input block is properly allocated and valid
* \param[in] block: Block to check if properly set as allocated
*/
#define LWMEM_BLOCK_IS_ALLOC(block) ((block) != NULL && ((block)->size & LWMEM_ALLOC_BIT) && (block)->next == (void *)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK))
#define LWMEM_BLOCK_IS_ALLOC(block) \
((block) != NULL && ((block)->size & LWMEM_ALLOC_BIT) \
&& (block)->next == (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK))
/**
* \brief Get block handle from application pointer
* \param[in] ptr: Input pointer to get block from
*/
#define LWMEM_GET_BLOCK_FROM_PTR(ptr) (void *)((ptr) != NULL ? ((LWMEM_TO_BYTE_PTR(ptr)) - LWMEM_BLOCK_META_SIZE) : NULL)
#define LWMEM_GET_BLOCK_FROM_PTR(ptr) (void*)((ptr) != NULL ? ((LWMEM_TO_BYTE_PTR(ptr)) - LWMEM_BLOCK_META_SIZE) : NULL)
/**
* \brief Get block handle from application pointer
* \param[in] block: Input pointer to get block from
*/
#define LWMEM_GET_PTR_FROM_BLOCK(block) (void *)((block) != NULL ? ((LWMEM_TO_BYTE_PTR(block)) + LWMEM_BLOCK_META_SIZE) : NULL)
#define LWMEM_GET_PTR_FROM_BLOCK(block) \
(void*)((block) != NULL ? ((LWMEM_TO_BYTE_PTR(block)) + LWMEM_BLOCK_META_SIZE) : NULL)
/**
* \brief Minimum amount of memory required to make new empty block
*
* Default size is size of meta block
*/
#define LWMEM_BLOCK_MIN_SIZE (LWMEM_BLOCK_META_SIZE)
#define LWMEM_BLOCK_MIN_SIZE (LWMEM_BLOCK_META_SIZE)
/**
* \brief Get LwMEM instance based on user input
* \param[in] in_lw: LwMEM instance. Set to `NULL` for default instance
* \param[in] in_lwobj: LwMEM instance. Set to `NULL` for default instance
*/
#define LWMEM_GET_LW(in_lw) ((in_lw) != NULL ? (in_lw) : (&lwmem_default))
#define LWMEM_GET_LWOBJ(in_lwobj) ((in_lwobj) != NULL ? (in_lwobj) : (&lwmem_default))
/**
* \brief Gets block before input block (marked as prev) and its previous free block
* \param[in] in_lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] in_lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] in_b: Input block to find previous and its previous
* \param[in] in_pp: Previous previous of input block
* \param[in] in_p: Previous of input block
*/
#define LWMEM_GET_PREV_CURR_OF_BLOCK(in_lw, in_b, in_pp, in_p) do { \
for ((in_pp) = NULL, (in_p) = &(LWMEM_GET_LW(in_lw)->start_block); \
(in_p) != NULL && (in_p)->next < (in_b); \
(in_pp) = (in_p), (in_p) = (in_p)->next \
) {} \
#define LWMEM_GET_PREV_CURR_OF_BLOCK(in_lwobj, in_b, in_pp, in_p) \
do { \
for ((in_pp) = NULL, (in_p) = &((in_lwobj)->start_block); (in_p) != NULL && (in_p)->next < (in_b); \
(in_pp) = (in_p), (in_p) = (in_p)->next) {} \
} while (0)
#if LWMEM_CFG_OS
#define LWMEM_PROTECT(lw) lwmem_sys_mutex_wait(&(LWMEM_GET_LW(lw)->mutex))
#define LWMEM_UNPROTECT(lw) lwmem_sys_mutex_release(&(LWMEM_GET_LW(lw)->mutex))
#define LWMEM_PROTECT(lwobj) lwmem_sys_mutex_wait(&((lwobj)->mutex))
#define LWMEM_UNPROTECT(lwobj) lwmem_sys_mutex_release(&((lwobj)->mutex))
#else /* LWMEM_CFG_OS */
#define LWMEM_PROTECT(lw)
#define LWMEM_UNPROTECT(lw)
#define LWMEM_PROTECT(lwobj)
#define LWMEM_UNPROTECT(lwobj)
#endif /* !LWMEM_CFG_OS */
/* Statistics part */
#if LWMEM_CFG_ENABLE_STATS
#define LWMEM_INC_STATS(field) (++(field))
#define LWMEM_INC_STATS(field) (++(field))
#define LWMEM_UPDATE_MIN_FREE(lwobj) \
do { \
if ((lwobj)->mem_available_bytes < (lwobj)->stats.minimum_ever_mem_available_bytes) { \
(lwobj)->stats.minimum_ever_mem_available_bytes = (lwobj)->mem_available_bytes; \
} \
} while (0)
#else
#define LWMEM_INC_STATS(field)
#define LWMEM_UPDATE_MIN_FREE(lwobj)
#endif /* LWMEM_CFG_ENABLE_STATS */
/**
@ -165,7 +180,7 @@ static lwmem_t lwmem_default;
* \return `1` if region valid, `0` otherwise
*/
static uint8_t
prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* ms) {
prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* ms) {
size_t mem_size;
uint8_t* mem_start_addr;
@ -176,7 +191,7 @@ prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* m
*ms = 0;
/* Check region size and align it to config bits */
mem_size = region->size & ~LWMEM_ALIGN_BITS;/* Size does not include lower bits */
mem_size = region->size & ~LWMEM_ALIGN_BITS; /* Size does not include lower bits */
if (mem_size < (2 * LWMEM_BLOCK_MIN_SIZE)) {
return 0;
}
@ -186,7 +201,7 @@ prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* m
* Increase start address and decrease effective region size
*/
mem_start_addr = region->start_addr;
if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { /* Check alignment boundary */
if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { /* Check alignment boundary */
mem_start_addr += ((size_t)LWMEM_CFG_ALIGN_NUM) - ((size_t)mem_start_addr & LWMEM_ALIGN_BITS);
mem_size -= (size_t)(mem_start_addr - LWMEM_TO_BYTE_PTR(region->start_addr));
}
@ -203,11 +218,11 @@ prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* m
/**
* \brief Insert free block to linked list of free blocks
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] nb: New free block to insert into linked list
*/
static void
prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) {
prv_insert_free_block(lwmem_t* const lwobj, lwmem_block_t* nb) {
lwmem_block_t* prev;
/* Check valid inputs */
@ -219,7 +234,7 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) {
* Try to find position to put new block in-between
* Search until all free block addresses are lower than entry block
*/
for (prev = &(LWMEM_GET_LW(lw)->start_block); prev != NULL && prev->next < nb; prev = prev->next) {}
for (prev = &(lwobj->start_block); prev != NULL && prev->next < nb; prev = prev->next) {}
/* This is hard error with wrong memory usage */
if (prev == NULL) {
@ -239,7 +254,12 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) {
* By doing this, we protect data left by app
* and we make sure new allocations cannot see old information
*/
LWMEM_MEMSET(LWMEM_GET_PTR_FROM_BLOCK(nb), 0x00, nb->size - LWMEM_BLOCK_META_SIZE);
if (nb != NULL) {
void* p = LWMEM_GET_PTR_FROM_BLOCK(nb);
if (p != NULL) {
LWMEM_MEMSET(p, 0x00, nb->size - LWMEM_BLOCK_META_SIZE);
}
}
#endif /* LWMEM_CFG_RESET_MEMORY */
/*
@ -247,9 +267,9 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) {
* If this is the case, merge blocks together and increase previous block by input block size
*/
if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(nb)) {
prev->size += nb->size; /* Increase current block by size of new block */
nb = prev; /* New block and current are now the same thing */
/*
prev->size += nb->size; /* Increase current block by size of new block */
nb = prev; /* New block and current are now the same thing */
/*
* It is important to set new block as current one
* as this allows merging previous and next blocks together with new block
* at the same time; follow next steps
@ -260,16 +280,18 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) {
* Check if new block and next of previous create big contiguous block
* Do not merge with "end of region" indication (commented part of if statement)
*/
if (prev->next != NULL && prev->next->size > 0 /* Do not remove "end of region" indicator in each region */
if (prev->next != NULL && prev->next->size > 0 /* Do not remove "end of region" indicator in each region */
&& (LWMEM_TO_BYTE_PTR(nb) + nb->size) == LWMEM_TO_BYTE_PTR(prev->next)) {
if (prev->next == LWMEM_GET_LW(lw)->end_block) {/* Does it points to the end? */
nb->next = LWMEM_GET_LW(lw)->end_block; /* Set end block pointer */
if (prev->next == lwobj->end_block) { /* Does it points to the end? */
nb->next = lwobj->end_block; /* Set end block pointer */
} else {
nb->size += prev->next->size; /* Expand of current block for size of next free block which is right behind new block */
nb->next = prev->next->next; /* Next free is pointed to the next one of previous next */
nb->size +=
prev->next
->size; /* Expand of current block for size of next free block which is right behind new block */
nb->next = prev->next->next; /* Next free is pointed to the next one of previous next */
}
} else {
nb->next = prev->next; /* Set next of input block as next of current one */
nb->next = prev->next; /* Set next of input block as next of current one */
}
/*
@ -283,19 +305,19 @@ prv_insert_free_block(lwmem_t* const lw, lwmem_block_t* nb) {
/**
* \brief Split too big block and add it to list of free blocks
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] block: Pointer to block with size already set
* \param[in] new_block_size: New block size to be set
* \return `1` if block splitted, `0` otherwise
*/
static uint8_t
prv_split_too_big_block(lwmem_t* const lw, lwmem_block_t* block, size_t new_block_size) {
prv_split_too_big_block(lwmem_t* const lwobj, lwmem_block_t* block, size_t new_block_size) {
lwmem_block_t* next;
size_t block_size, is_alloc_bit;
uint8_t success = 0;
is_alloc_bit = block->size & LWMEM_ALLOC_BIT; /* Check if allocation bit is set */
block_size = block->size & ~LWMEM_ALLOC_BIT;/* Use size without allocated bit */
is_alloc_bit = block->size & LWMEM_ALLOC_BIT; /* Check if allocation bit is set */
block_size = block->size & ~LWMEM_ALLOC_BIT; /* Use size without allocated bit */
/*
* If current block size is greater than requested size,
@ -303,12 +325,12 @@ prv_split_too_big_block(lwmem_t* const lw, lwmem_block_t* block, size_t new_bloc
* and add it back to list of empty blocks
*/
if ((block_size - new_block_size) >= LWMEM_BLOCK_MIN_SIZE) {
next = (void*)(LWMEM_TO_BYTE_PTR(block) + new_block_size); /* Put next block after size of current allocation */
next->size = block_size - new_block_size; /* Modify block data */
block->size = new_block_size; /* Current size is now smaller */
next = (void*)(LWMEM_TO_BYTE_PTR(block) + new_block_size); /* Put next block after size of current allocation */
next->size = block_size - new_block_size; /* Modify block data */
block->size = new_block_size; /* Current size is now smaller */
LWMEM_GET_LW(lw)->mem_available_bytes += next->size;/* Increase available bytes by new block size */
prv_insert_free_block(lw, next); /* Add new block to the free list */
lwobj->mem_available_bytes += next->size; /* Increase available bytes by new block size */
prv_insert_free_block(lwobj, next); /* Add new block to the free list */
success = 1;
} else {
@ -326,28 +348,28 @@ prv_split_too_big_block(lwmem_t* const lw, lwmem_block_t* block, size_t new_bloc
/**
* \brief Private allocation function
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] region: Pointer to region to allocate from.
* Set to `NULL` for any region
* \param[in] size: Application wanted size, excluding size of meta header
* \return Pointer to allocated memory, `NULL` otherwise
*/
static void*
prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) {
lwmem_block_t* prev, *curr;
prv_alloc(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) {
lwmem_block_t *prev, *curr;
void* retval = NULL;
/* Calculate final size including meta data size */
const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE;
/* Check if initialized and if size is in the limits */
if (LWMEM_GET_LW(lw)->end_block == NULL || final_size == LWMEM_BLOCK_META_SIZE || (final_size & LWMEM_ALLOC_BIT) > 0) {
if (lwobj->end_block == NULL || final_size == LWMEM_BLOCK_META_SIZE || (final_size & LWMEM_ALLOC_BIT) > 0) {
return NULL;
}
/* Set default values */
prev = &(LWMEM_GET_LW(lw)->start_block); /* Use pointer from custom lwmem block */
curr = prev->next; /* Curr represents first actual free block */
prev = &(lwobj->start_block); /* Use pointer from custom lwmem block */
curr = prev->next; /* Curr represents first actual free block */
/*
* If region is not set to NULL,
@ -371,17 +393,17 @@ prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) {
*/
for (; curr != NULL; prev = curr, curr = curr->next) {
/* Check bounds */
if (curr->next == NULL || curr == LWMEM_GET_LW(lw)->end_block) {
if (curr->next == NULL || curr == lwobj->end_block) {
return NULL;
}
if ((uint8_t*)curr < (uint8_t*)region_start_addr) { /* Check if we reached region */
continue;
}
if ((uint8_t*)curr >= (uint8_t*)(region_start_addr + region_size)) {/* Check if we are out already */
if ((uint8_t*)curr >= (uint8_t*)(region_start_addr + region_size)) { /* Check if we are out already */
return NULL;
}
if (curr->size >= final_size) {
break; /* Free block identified */
break; /* Free block identified */
}
}
} else {
@ -390,8 +412,8 @@ prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) {
* Loop until size of current block is smaller than requested final size
*/
for (; curr != NULL && curr->size < final_size; prev = curr, curr = curr->next) {
if (curr->next == NULL || curr == LWMEM_GET_LW(lw)->end_block) {/* If no more blocks available */
return NULL; /* No sufficient memory available to allocate block of memory */
if (curr->next == NULL || curr == lwobj->end_block) { /* If no more blocks available */
return NULL; /* No sufficient memory available to allocate block of memory */
}
}
}
@ -402,35 +424,36 @@ prv_alloc(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) {
}
/* There is a valid block available */
retval = LWMEM_GET_PTR_FROM_BLOCK(curr); /* Return pointer does not include meta part */
prev->next = curr->next; /* Remove this block from linked list by setting next of previous to next of current */
retval = LWMEM_GET_PTR_FROM_BLOCK(curr); /* Return pointer does not include meta part */
prev->next = curr->next; /* Remove this block from linked list by setting next of previous to next of current */
/* curr block is now removed from linked list */
LWMEM_GET_LW(lw)->mem_available_bytes -= curr->size;/* Decrease available bytes by allocated block size */
prv_split_too_big_block(lw, curr, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(curr); /* Set block as allocated */
lwobj->mem_available_bytes -= curr->size; /* Decrease available bytes by allocated block size */
prv_split_too_big_block(lwobj, curr, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(curr); /* Set block as allocated */
LWMEM_INC_STATS(LWMEM_GET_LW(lw)->stats.nr_alloc);
LWMEM_UPDATE_MIN_FREE(lwobj);
LWMEM_INC_STATS(lwobj->stats.nr_alloc);
return retval;
}
/**
* \brief Free input pointer
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] ptr: Input pointer to free
*/
static void
prv_free(lwmem_t* const lw, void* const ptr) {
prv_free(lwmem_t* const lwobj, void* const ptr) {
lwmem_block_t* const block = LWMEM_GET_BLOCK_FROM_PTR(ptr);
if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */
block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */
if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */
block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */
LWMEM_GET_LW(lw)->mem_available_bytes += block->size; /* Increase available bytes */
prv_insert_free_block(lw, block); /* Put block back to list of free block */
lwobj->mem_available_bytes += block->size; /* Increase available bytes */
prv_insert_free_block(lwobj, block); /* Put block back to list of free block */
LWMEM_INC_STATS(LWMEM_GET_LW(lw)->stats.nr_free);
LWMEM_INC_STATS(lwobj->stats.nr_free);
}
}
@ -444,7 +467,7 @@ prv_free(lwmem_t* const lw, void* const ptr) {
* - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)`
* - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success
*
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] region: Pointer to region to allocate from.
* Set to `NULL` for any region
* \param[in] ptr: Memory block previously allocated with one of allocation functions.
@ -453,21 +476,22 @@ prv_free(lwmem_t* const lw, void* const ptr) {
* \return Pointer to allocated memory on success, `NULL` otherwise
*/
static void*
prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, const size_t size) {
lwmem_block_t* block, *prevprev, *prev;
size_t block_size; /* Holds size of input block (ptr), including metadata size */
const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE;/* Holds size of new requested block size, including metadata size */
void* retval; /* Return pointer, used with LWMEM_RETURN macro */
prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) {
lwmem_block_t *block, *prevprev, *prev;
size_t block_size; /* Holds size of input block (ptr), including metadata size */
const size_t final_size =
LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; /* Holds size of new requested block size, including metadata size */
void* retval; /* Return pointer, used with LWMEM_RETURN macro */
/* Check optional input parameters */
if (size == 0) {
if (ptr != NULL) {
prv_free(lw, ptr);
prv_free(lwobj, ptr);
}
return NULL;
}
if (ptr == NULL) {
return prv_alloc(lw, region, size);
return prv_alloc(lwobj, region, size);
}
/* Try to reallocate existing pointer */
@ -478,11 +502,11 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
/* Process existing block */
block = LWMEM_GET_BLOCK_FROM_PTR(ptr);
if (LWMEM_BLOCK_IS_ALLOC(block)) {
block_size = block->size & ~LWMEM_ALLOC_BIT;/* Get actual block size, without memory allocation bit */
block_size = block->size & ~LWMEM_ALLOC_BIT; /* Get actual block size, without memory allocation bit */
/* Check current block size is the same as new requested size */
if (block_size == final_size) {
return ptr; /* Just return pointer, nothing to do */
return ptr; /* Just return pointer, nothing to do */
}
/*
@ -505,7 +529,7 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
*/
if (final_size < block_size) {
if ((block_size - final_size) >= LWMEM_BLOCK_MIN_SIZE) {
prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
} else {
/*
* It is not possible to create new empty block at the end of input block
@ -515,11 +539,11 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
*/
/* Find free blocks before input block */
LWMEM_GET_PREV_CURR_OF_BLOCK(lw, block, prevprev, prev);
LWMEM_GET_PREV_CURR_OF_BLOCK(lwobj, block, prevprev, prev);
/* Check if current block and next free are connected */
if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next)
&& prev->next->size > 0) { /* Must not be end of region indicator */
&& prev->next->size > 0) { /* Must not be end of region indicator */
/* Make temporary variables as prev->next will point to different location */
const size_t tmp_size = prev->next->size;
void* const tmp_next = prev->next->next;
@ -528,19 +552,20 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
prev->next = (void*)(LWMEM_TO_BYTE_PTR(prev->next) - (block_size - final_size));
prev->next->size = tmp_size + (block_size - final_size);
prev->next->next = tmp_next;
LWMEM_GET_LW(lw)->mem_available_bytes += block_size - final_size; /* Increase available bytes by increase of free block */
lwobj->mem_available_bytes +=
block_size - final_size; /* Increase available bytes by increase of free block */
block->size = final_size; /* Block size is requested size */
block->size = final_size; /* Block size is requested size */
}
}
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return ptr; /* Return existing pointer */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return ptr; /* Return existing pointer */
}
/* New requested size is bigger than current block size is */
/* Find last free (and its previous) block, located just before input block */
LWMEM_GET_PREV_CURR_OF_BLOCK(lw, block, prevprev, prev);
LWMEM_GET_PREV_CURR_OF_BLOCK(lwobj, block, prevprev, prev);
/* If entry could not be found, there is a hard error */
if (prev == NULL) {
@ -552,20 +577,23 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
/* Input block points to address somewhere between "prev" and "prev->next" pointers */
/* Check if "block" and next free "prev->next" create contiguous memory with size of at least new requested size */
if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next)/* Blocks create contiguous block */
if ((LWMEM_TO_BYTE_PTR(block) + block_size)
== LWMEM_TO_BYTE_PTR(prev->next) /* Blocks create contiguous block */
&& (block_size + prev->next->size) >= final_size) { /* Size is greater or equal to requested */
/*
* Merge blocks together by increasing current block with size of next free one
* and remove next free from list of free blocks
*/
LWMEM_GET_LW(lw)->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */
block->size = block_size + prev->next->size;/* Increase effective size of new block */
prev->next = prev->next->next; /* Set next to next's next, effectively remove expanded block from free list */
lwobj->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */
LWMEM_UPDATE_MIN_FREE(lwobj);
block->size = block_size + prev->next->size; /* Increase effective size of new block */
prev->next =
prev->next->next; /* Set next to next's next, effectively remove expanded block from free list */
prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return ptr; /* Return existing pointer */
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return ptr; /* Return existing pointer */
}
/*
@ -573,8 +601,8 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
*
* It is necessary to make a memory move and shift content up as new return pointer is now upper on address space
*/
if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) /* Blocks create contiguous block */
&& (prev->size + block_size) >= final_size) { /* Size is greater or equal to requested */
if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) /* Blocks create contiguous block */
&& (prev->size + block_size) >= final_size) { /* Size is greater or equal to requested */
/* Move memory from block to block previous to current */
void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block);
void* const new_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(prev);
@ -589,14 +617,16 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
*/
LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size);
LWMEM_GET_LW(lw)->mem_available_bytes -= prev->size;/* For now decrease effective available bytes */
prev->size += block_size; /* Increase size of input block size */
prevprev->next = prev->next; /* Remove prev from free list as it is now being used for allocation together with existing block */
block = prev; /* Move block pointer to previous one */
lwobj->mem_available_bytes -= prev->size; /* For now decrease effective available bytes */
LWMEM_UPDATE_MIN_FREE(lwobj);
prev->size += block_size; /* Increase size of input block size */
prevprev->next =
prev->next; /* Remove prev from free list as it is now being used for allocation together with existing block */
block = prev; /* Move block pointer to previous one */
prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return new_data_ptr; /* Return new data ptr */
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return new_data_ptr; /* Return new data ptr */
}
/*
@ -607,9 +637,11 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
* Last option is to check if previous free block "prev", input block "block" and next free block "prev->next" create contiguous block
* and size of new block (from 3 contiguous blocks) together is big enough
*/
if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) /* Input block and free block before create contiguous block */
&& (LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) /* Input block and free block after create contiguous block */
&& (prev->size + block_size + prev->next->size) >= final_size) {/* Size is greater or equal to requested */
if ((LWMEM_TO_BYTE_PTR(prev) + prev->size)
== LWMEM_TO_BYTE_PTR(block) /* Input block and free block before create contiguous block */
&& (LWMEM_TO_BYTE_PTR(block) + block_size)
== LWMEM_TO_BYTE_PTR(prev->next) /* Input block and free block after create contiguous block */
&& (prev->size + block_size + prev->next->size) >= final_size) { /* Size is greater or equal to requested */
/* Move memory from block to block previous to current */
void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block);
@ -623,16 +655,22 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
*
* Metadata of "prev" are not modified during memmove
*/
LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); /* Copy old buffer size to new location */
LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); /* Copy old buffer size to new location */
LWMEM_GET_LW(lw)->mem_available_bytes -= prev->size + prev->next->size; /* Decrease effective available bytes for free blocks before and after input block */
prev->size += block_size + prev->next->size;/* Increase size of new block by size of 2 free blocks */
prevprev->next = prev->next->next; /* Remove free block before current one and block after current one from linked list (remove 2) */
block = prev; /* Previous block is now current */
lwobj->mem_available_bytes -=
prev->size
+ prev->next
->size; /* Decrease effective available bytes for free blocks before and after input block */
LWMEM_UPDATE_MIN_FREE(lwobj);
prev->size += block_size + prev->next->size; /* Increase size of new block by size of 2 free blocks */
prevprev->next =
prev->next
->next; /* Remove free block before current one and block after current one from linked list (remove 2) */
block = prev; /* Previous block is now current */
prv_split_too_big_block(lw, block, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return new_data_ptr; /* Return new data ptr */
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
return new_data_ptr; /* Return new data ptr */
}
} else {
/* Hard error. Input pointer is not NULL and block is not considered allocated */
@ -648,18 +686,19 @@ prv_realloc(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, co
*
* Final solution is to find completely new empty block of sufficient size and copy content from old one to new one
*/
retval = prv_alloc(lw, region, size); /* Try to allocate new block */
retval = prv_alloc(lwobj, region, size); /* Try to allocate new block */
if (retval != NULL) {
block_size = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; /* Get application size from input pointer */
LWMEM_MEMCPY(retval, ptr, size > block_size ? block_size : size); /* Copy content to new allocated block */
prv_free(lw, ptr); /* Free input pointer */
block_size =
(block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; /* Get application size from input pointer */
LWMEM_MEMCPY(retval, ptr, size > block_size ? block_size : size); /* Copy content to new allocated block */
prv_free(lwobj, ptr); /* Free input pointer */
}
return retval;
}
/**
* \brief Initializes and assigns user regions for memory used by allocator algorithm
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] regions: Pointer to array of regions with address and respective size.
* Regions must be in increasing order (start address) and must not overlap in-between.
* Last region entry must have address `NULL` and size set to `0`
@ -677,14 +716,14 @@ lwmem_region_t regions[] = {
* It must be called only once to setup memory regions
*/
size_t
lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) {
lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) {
uint8_t* mem_start_addr;
size_t mem_size, len = 0;
lwmem_block_t* first_block, *prev_end_block;
lwmem_block_t *first_block, *prev_end_block;
lwobj = LWMEM_GET_LWOBJ(lwobj);
/* Check first things first */
if (regions == NULL
|| LWMEM_GET_LW(lw)->end_block != NULL /* Init function may only be called once per lwmem instance */
if (regions == NULL || lwobj->end_block != NULL /* Init function may only be called once per lwmem instance */
|| (((size_t)LWMEM_CFG_ALIGN_NUM) & (((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) > 0) { /* Must be power of 2 */
return 0;
}
@ -719,10 +758,10 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) {
/* Process further checks of valid inputs */
if (regions == NULL || len == 0
#if LWMEM_CFG_OS
|| lwmem_sys_mutex_isvalid(&(LWMEM_GET_LW(lw)->mutex)) /* Check if mutex valid already = must not be */
|| !lwmem_sys_mutex_create(&(LWMEM_GET_LW(lw)->mutex)) /* Final step = try to create mutex for new instance */
#endif /* LWMEM_CFG_OS */
) {
|| lwmem_sys_mutex_isvalid(&(lwobj->mutex)) /* Check if mutex valid already = must not be */
|| !lwmem_sys_mutex_create(&(lwobj->mutex)) /* Final step = try to create mutex for new instance */
#endif /* LWMEM_CFG_OS */
) {
return 0;
}
@ -737,23 +776,23 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) {
* In first indication application shall set start_block and never again
* end_block value holds
*/
if (LWMEM_GET_LW(lw)->end_block == NULL) {
if (lwobj->end_block == NULL) {
/*
* Next entry of start block is first region
* It points to beginning of region data
* In the later step(s) first block is manually set on top of memory region
*/
LWMEM_GET_LW(lw)->start_block.next = (void*)mem_start_addr;
LWMEM_GET_LW(lw)->start_block.size = 0; /* Size of dummy start block is zero */
lwobj->start_block.next = (void*)mem_start_addr;
lwobj->start_block.size = 0; /* Size of dummy start block is zero */
}
/* Save current end block status as it is used later for linked list insertion */
prev_end_block = LWMEM_GET_LW(lw)->end_block;
prev_end_block = lwobj->end_block;
/* Put end block to the end of the region with size = 0 */
LWMEM_GET_LW(lw)->end_block = (void*)(mem_start_addr + mem_size - LWMEM_BLOCK_META_SIZE);
LWMEM_GET_LW(lw)->end_block->next = NULL; /* End block in region does not have next entry */
LWMEM_GET_LW(lw)->end_block->size = 0; /* Size of end block is zero */
lwobj->end_block = (void*)(mem_start_addr + mem_size - LWMEM_BLOCK_META_SIZE);
lwobj->end_block->next = NULL; /* End block in region does not have next entry */
lwobj->end_block->size = 0; /* Size of end block is zero */
/*
* Create memory region first block.
@ -764,7 +803,7 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) {
* Actual maximal available size for application in the region is mem_size - 2 * MEM_BLOCK_META_SIZE
*/
first_block = (void*)mem_start_addr;
first_block->next = LWMEM_GET_LW(lw)->end_block;/* Next block of first is last block */
first_block->next = lwobj->end_block; /* Next block of first is last block */
first_block->size = mem_size - LWMEM_BLOCK_META_SIZE;
/* Check if previous regions exist by checking previous end block state */
@ -772,22 +811,26 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) {
prev_end_block->next = first_block; /* End block of previous region now points to start of current region */
}
LWMEM_GET_LW(lw)->mem_available_bytes += first_block->size; /* Increase number of available bytes */
++LWMEM_GET_LW(lw)->mem_regions_count; /* Increase number of used regions */
lwobj->mem_available_bytes += first_block->size; /* Increase number of available bytes */
++lwobj->mem_regions_count; /* Increase number of used regions */
}
#if defined(LWMEM_DEV)
/* Copy default state of start block */
LWMEM_MEMCPY(&lwmem_default.start_block_first_use, &lwmem_default.start_block, sizeof(lwmem_default.start_block));
#endif /* defined(LWMEM_DEV) */
#if LWMEM_CFG_ENABLE_STATS
lwobj->stats.mem_size_bytes = lwobj->mem_available_bytes;
lwobj->stats.minimum_ever_mem_available_bytes = lwobj->mem_available_bytes;
#endif
return LWMEM_GET_LW(lw)->mem_regions_count; /* Return number of regions used by manager */
return lwobj->mem_regions_count; /* Return number of regions used by manager */
}
/**
* \brief Allocate memory of requested size in specific lwmem instance and optional region.
* \note This is an extended malloc version function declaration to support advanced features
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] region: Optional region instance within LwMEM instance to force allocation from.
* Set to `NULL` to use any region within LwMEM instance
* \param[in] size: Number of bytes to allocate
@ -795,11 +838,12 @@ lwmem_assignmem_ex(lwmem_t* const lw, const lwmem_region_t* regions) {
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
void*
lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t size) {
lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size) {
void* ptr;
LWMEM_PROTECT(lw);
ptr = prv_alloc(lw, region, size);
LWMEM_UNPROTECT(lw);
lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
ptr = prv_alloc(lwobj, region, size);
LWMEM_UNPROTECT(lwobj);
return ptr;
}
@ -810,7 +854,7 @@ lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t si
* It resets allocated block of memory to zero if allocation is successful
* \note This is an extended calloc version function declaration to support advanced features
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] region: Optional region instance within LwMEM instance to force allocation from.
* Set to `NULL` to use any region within LwMEM instance
* \param[in] nitems: Number of elements to be allocated
@ -819,15 +863,16 @@ lwmem_malloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t si
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
void*
lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t nitems, const size_t size) {
lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size) {
void* ptr;
const size_t s = size * nitems;
LWMEM_PROTECT(lw);
if ((ptr = prv_alloc(lw, region, s)) != NULL) {
lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
if ((ptr = prv_alloc(lwobj, region, s)) != NULL) {
LWMEM_MEMSET(ptr, 0x00, s);
}
LWMEM_UNPROTECT(lw);
LWMEM_UNPROTECT(lwobj);
return ptr;
}
@ -843,7 +888,7 @@ lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t ni
* - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)`
* - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success
*
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] region: Pointer to region to allocate from.
* Set to `NULL` to use any region within LwMEM instance.
* Instance must be the same as used during allocation procedure
@ -854,11 +899,12 @@ lwmem_calloc_ex(lwmem_t* const lw, const lwmem_region_t* region, const size_t ni
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
void*
lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const ptr, const size_t size) {
lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) {
void* p;
LWMEM_PROTECT(lw);
p = prv_realloc(lw, region, ptr, size);
LWMEM_UNPROTECT(lw);
lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
p = prv_realloc(lwobj, region, ptr, size);
LWMEM_UNPROTECT(lwobj);
return p;
}
@ -879,7 +925,7 @@ lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const pt
* - `*ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)`, sets input pointer pointing to `NULL`
* - `*ptr != NULL; size > 0`: Function tries to reallocate existing pointer with new size and copy content to new block
*
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
* \param[in] region: Pointer to region to allocate from.
* Set to `NULL` to use any region within LwMEM instance.
* Instance must be the same as used during allocation procedure
@ -891,7 +937,7 @@ lwmem_realloc_ex(lwmem_t* const lw, const lwmem_region_t* region, void* const pt
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
uint8_t
lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const ptr, const size_t size) {
lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size) {
void* new_ptr;
/*
@ -903,10 +949,10 @@ lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const
return 0;
}
new_ptr = lwmem_realloc_ex(lw, region, *ptr, size); /* Try to reallocate existing pointer */
new_ptr = lwmem_realloc_ex(lwobj, region, *ptr, size); /* Try to reallocate existing pointer */
if (new_ptr != NULL) {
*ptr = new_ptr;
} else if (size == 0) { /* size == 0 means free input memory */
} else if (size == 0) { /* size == 0 means free input memory */
*ptr = NULL;
return 1;
}
@ -916,17 +962,18 @@ lwmem_realloc_s_ex(lwmem_t* const lw, const lwmem_region_t* region, void** const
/**
* \brief Free previously allocated memory using one of allocation functions
* in specific lwmem instance.
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance.
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance.
* Instance must be the same as used during allocation procedure
* \note This is an extended free version function declaration to support advanced features
* \param[in] ptr: Memory to free. `NULL` pointer is valid input
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
void
lwmem_free_ex(lwmem_t* const lw, void* const ptr) {
LWMEM_PROTECT(lw);
prv_free(lw, ptr);
LWMEM_UNPROTECT(lw);
lwmem_free_ex(lwmem_t* lwobj, void* const ptr) {
lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
prv_free(lwobj, ptr);
LWMEM_UNPROTECT(lwobj);
}
/**
@ -937,45 +984,68 @@ lwmem_free_ex(lwmem_t* const lw, void* const ptr) {
*
* It is advised to use this function when freeing memory.
*
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance.
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance.
* Instance must be the same as used during allocation procedure
* \param[in] ptr: Pointer to pointer to allocated memory.
* When set to non `NULL`, pointer is freed and set to `NULL`
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
*/
void
lwmem_free_s_ex(lwmem_t* const lw, void** const ptr) {
lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr) {
if (ptr != NULL && *ptr != NULL) {
LWMEM_PROTECT(lw);
prv_free(lw, *ptr);
LWMEM_UNPROTECT(lw);
lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
prv_free(lwobj, *ptr);
LWMEM_UNPROTECT(lwobj);
*ptr = NULL;
}
}
/**
* \brief Get user size of allocated memory
* \param[in] lw: LwMEM instance. Set to `NULL` to use default instance.
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance.
* Instance must be the same as used during allocation procedure
* \param[in] ptr: Pointer to allocated memory
* \return Block size for user in units of bytes
*/
size_t
lwmem_get_size_ex(lwmem_t* const lw, void* ptr) {
lwmem_get_size_ex(lwmem_t* lwobj, void* ptr) {
lwmem_block_t* block;
uint32_t len = 0;
if (ptr != NULL) {
LWMEM_PROTECT(lw);
lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
block = LWMEM_GET_BLOCK_FROM_PTR(ptr);
if (LWMEM_BLOCK_IS_ALLOC(block)) {
len = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE;
}
LWMEM_UNPROTECT(lw);
LWMEM_UNPROTECT(lwobj);
}
return len;
}
#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__
/**
* \brief Get statistics of a LwMEM instance
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance.
* Instance must be the same as used during allocation procedure
* \param[in] stats: Pointer to \ref lwmem_stats_t to store result
*/
void
lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats) {
if (stats != NULL) {
lwobj = LWMEM_GET_LWOBJ(lwobj);
LWMEM_PROTECT(lwobj);
*stats = lwobj->stats;
stats->mem_available_bytes = lwobj->mem_available_bytes;
LWMEM_UNPROTECT(lwobj);
}
}
#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */
/* Part of library used ONLY for LWMEM_DEV purposes */
/* To validate and test library */
@ -1035,11 +1105,7 @@ print_block(size_t i, lwmem_block_t* block) {
is_free = (block->size & LWMEM_ALLOC_BIT) == 0 && block != &lwmem_default.start_block_first_use && block->size > 0;
block_size = block->size & ~LWMEM_ALLOC_BIT;
printf("| %5d | %16p | %6d | %4d | %16d |",
(int)i,
block,
(int)is_free,
(int)block_size,
printf("| %5d | %16p | %6d | %4d | %16d |", (int)i, (void*)block, (int)is_free, (int)block_size,
(int)(is_free ? (block_size - LWMEM_BLOCK_META_SIZE) : 0));
if (block == &lwmem_default.start_block_first_use) {
printf(" Start block ");
@ -1060,6 +1126,9 @@ lwmem_debug_print(uint8_t print_alloc, uint8_t print_free) {
size_t block_size;
lwmem_block_t* block;
(void)print_alloc;
(void)print_free;
printf("|-------|------------------|--------|------|------------------|-----------------|\r\n");
printf("| Block | Address | IsFree | Size | MaxUserAllocSize | Meta |\r\n");
printf("|-------|------------------|--------|------|------------------|-----------------|\r\n");

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
* obtaining a copy of this software and associated documentation
@ -29,7 +29,7 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0
* Version: v2.1.0
*/
#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
* obtaining a copy of this software and associated documentation
@ -29,7 +29,7 @@
* This file is part of LwMEM - Lightweight dynamic memory manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.0
* Version: v2.1.0
*/
#include "system/lwmem_sys.h"

View File

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